]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Impl.c
added newline after brief summary
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Udp4Dxe / Udp4Impl.c
CommitLineData
8a67d61d 1/** @file\r
2\r
8792362f 3Copyright (c) 2006 - 2008, Intel Corporation \r
8a67d61d 4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Udp4Impl.c\r
15\r
16Abstract:\r
17\r
18 The implementation of the Udp4 protocol.\r
19\r
20\r
21**/\r
22\r
23\r
24#include "Udp4Impl.h"\r
25\r
26UINT16 mUdp4RandomPort;\r
27\r
ce904bae 28/**\r
29 This function checks and timeouts the I/O datagrams holding by the corresponding\r
30 service context.\r
31\r
32 @param Event The event this function registered to.\r
33 @param Context The context data registered during the creation of\r
34 the Event.\r
35\r
36 @return None.\r
37\r
38**/\r
8a67d61d 39VOID\r
40EFIAPI\r
41Udp4CheckTimeout (\r
42 IN EFI_EVENT Event,\r
43 IN VOID *Context\r
44 );\r
45\r
ce904bae 46/**\r
47 This function finds the udp instance by the specified <Address, Port> pair.\r
48\r
49 @param InstanceList Pointer to the head of the list linking the udp\r
50 instances.\r
51 @param Address Pointer to the specified IPv4 address.\r
52 @param Port The udp port number.\r
53\r
54 @retval TRUE The specified <Address, Port> pair is found.\r
55 @retval FALSE Otherwise.\r
56\r
57**/\r
8a67d61d 58BOOLEAN\r
59Udp4FindInstanceByPort (\r
e48e37fc 60 IN LIST_ENTRY *InstanceList,\r
8a67d61d 61 IN EFI_IPv4_ADDRESS *Address,\r
62 IN UINT16 Port\r
63 );\r
64\r
ce904bae 65/**\r
66 This function is the packet transmitting notify function registered to the IpIo\r
67 interface. It's called to signal the udp TxToken when IpIo layer completes the\r
68 transmitting of the udp datagram.\r
69\r
70 @param Status The completion status of the output udp datagram.\r
71 @param Context Pointer to the context data.\r
72 @param Sender Pointer to the Ip sender of the udp datagram.\r
73 @param NotifyData Pointer to the notify data.\r
74\r
75 @return None.\r
76\r
77**/\r
8a67d61d 78VOID\r
79Udp4DgramSent (\r
80 IN EFI_STATUS Status,\r
81 IN VOID *Context,\r
82 IN VOID *Sender,\r
83 IN VOID *NotifyData\r
84 );\r
85\r
ce904bae 86/**\r
87 This function processes the received datagram passed up by the IpIo layer.\r
88\r
89 @param Status The status of this udp datagram.\r
90 @param IcmpError The IcmpError code, only available when Status is\r
91 EFI_ICMP_ERROR.\r
92 @param NetSession Pointer to the EFI_NET_SESSION_DATA.\r
93 @param Packet Pointer to the NET_BUF containing the received udp\r
94 datagram.\r
95 @param Context Pointer to the context data.\r
96\r
97 @return None.\r
98\r
99**/\r
8a67d61d 100VOID\r
101Udp4DgramRcvd (\r
102 IN EFI_STATUS Status,\r
103 IN ICMP_ERROR IcmpError,\r
104 IN EFI_NET_SESSION_DATA *NetSession,\r
105 IN NET_BUF *Packet,\r
106 IN VOID *Context\r
107 );\r
108\r
ce904bae 109/**\r
110 This function cancels the token specified by Arg in the Map. This is a callback\r
111 used by Udp4InstanceCancelToken().\r
112\r
113 @param Map Pointer to the NET_MAP.\r
114 @param Item Pointer to the NET_MAP_ITEM.\r
115 @param Arg Pointer to the token to be cancelled, if NULL,\r
116 the token specified by Item is cancelled.\r
117\r
118 @retval EFI_SUCCESS The token is cancelled if Arg is NULL or the token\r
119 is not the same as that in the Item if Arg is not\r
120 NULL.\r
121 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is\r
122 cancelled.\r
123\r
124**/\r
8a67d61d 125EFI_STATUS\r
126Udp4CancelTokens (\r
127 IN NET_MAP *Map,\r
128 IN NET_MAP_ITEM *Item,\r
129 IN VOID *Arg OPTIONAL\r
130 );\r
131\r
ce904bae 132/**\r
133 This function matches the received udp datagram with the Instance.\r
134\r
135 @param Instance Pointer to the udp instance context data.\r
136 @param Udp4Session Pointer to the EFI_UDP4_SESSION_DATA abstracted\r
137 from the received udp datagram.\r
138\r
139 @retval TRUE The udp datagram matches the receiving requirments of the\r
140 udp Instance.\r
141 @retval FALSE Otherwise.\r
142\r
143**/\r
8a67d61d 144BOOLEAN\r
145Udp4MatchDgram (\r
146 IN UDP4_INSTANCE_DATA *Instance,\r
147 IN EFI_UDP4_SESSION_DATA *Udp4Session\r
148 );\r
149\r
ce904bae 150/**\r
151 This function removes the Wrap specified by Context and release relevant resources.\r
152\r
153 @param Event The Event this notify function registered to.\r
154 @param Context Pointer to the context data.\r
155\r
156 @return None.\r
157\r
158**/\r
8a67d61d 159VOID\r
160EFIAPI\r
161Udp4RecycleRxDataWrap (\r
162 IN EFI_EVENT Event,\r
163 IN VOID *Context\r
164 );\r
165\r
ce904bae 166/**\r
167 This function wraps the Packet and the RxData.\r
168\r
169 @param Instance Pointer to the instance context data.\r
170 @param Packet Pointer to the buffer containing the received\r
171 datagram.\r
172 @param RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this\r
173 datagram.\r
174\r
175 @return Pointer to the structure wrapping the RxData and the Packet.\r
176\r
177**/\r
8a67d61d 178UDP4_RXDATA_WRAP *\r
179Udp4WrapRxData (\r
180 IN UDP4_INSTANCE_DATA *Instance,\r
181 IN NET_BUF *Packet,\r
182 IN EFI_UDP4_RECEIVE_DATA *RxData\r
183 );\r
184\r
ce904bae 185/**\r
186 This function enqueues the received datagram into the instances' receiving queues.\r
187\r
188 @param Udp4Service Pointer to the udp service context data.\r
189 @param Packet Pointer to the buffer containing the received\r
190 datagram.\r
191 @param RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this\r
192 datagram.\r
193\r
194 @return The times this datagram is enqueued.\r
195\r
196**/\r
8a67d61d 197UINTN\r
198Udp4EnqueueDgram (\r
199 IN UDP4_SERVICE_DATA *Udp4Service,\r
200 IN NET_BUF *Packet,\r
201 IN EFI_UDP4_RECEIVE_DATA *RxData\r
202 );\r
203\r
ce904bae 204/**\r
205 This function delivers the datagrams enqueued in the instances.\r
206\r
207 @param Udp4Service Pointer to the udp service context data.\r
208\r
209 @return None.\r
210\r
211**/\r
8a67d61d 212VOID\r
213Udp4DeliverDgram (\r
214 IN UDP4_SERVICE_DATA *Udp4Service\r
215 );\r
216\r
ce904bae 217/**\r
218 This function demultiplexes the received udp datagram to the apropriate instances.\r
219\r
220 @param Udp4Service Pointer to the udp service context data.\r
221 @param NetSession Pointer to the EFI_NET_SESSION_DATA abstrated from\r
222 the received datagram.\r
223 @param Packet Pointer to the buffer containing the received udp\r
224 datagram.\r
225\r
226 @return None.\r
227\r
228**/\r
8a67d61d 229VOID\r
230Udp4Demultiplex (\r
231 IN UDP4_SERVICE_DATA *Udp4Service,\r
232 IN EFI_NET_SESSION_DATA *NetSession,\r
233 IN NET_BUF *Packet\r
234 );\r
235\r
ce904bae 236/**\r
237 This function handles the received Icmp Error message and demultiplexes it to the\r
238 instance.\r
239\r
240 @param Udp4Service Pointer to the udp service context data.\r
241 @param IcmpError The icmp error code.\r
242 @param NetSession Pointer to the EFI_NET_SESSION_DATA abstracted\r
243 from the received Icmp Error packet.\r
244 @param Packet Pointer to the Icmp Error packet.\r
245\r
246 @return None.\r
247\r
248**/\r
8a67d61d 249VOID\r
250Udp4IcmpHandler (\r
251 IN UDP4_SERVICE_DATA *Udp4Service,\r
252 IN ICMP_ERROR IcmpError,\r
253 IN EFI_NET_SESSION_DATA *NetSession,\r
254 IN NET_BUF *Packet\r
255 );\r
256\r
ce904bae 257/**\r
258 This function builds and sends out a icmp port unreachable message.\r
259\r
260 @param IpIo Pointer to the IP_IO instance.\r
261 @param NetSession Pointer to the EFI_NET_SESSION_DATA of the packet\r
262 causes this icmp error message.\r
263 @param Udp4Header Pointer to the udp header of the datagram causes\r
264 this icmp error message.\r
265\r
266 @return None.\r
267\r
268**/\r
8a67d61d 269VOID\r
270Udp4SendPortUnreach (\r
271 IN IP_IO *IpIo,\r
272 IN EFI_NET_SESSION_DATA *NetSession,\r
273 IN VOID *Udp4Header\r
274 );\r
275\r
276\r
277/**\r
278 Create the Udp service context data.\r
279\r
280 @param Udp4Service Pointer to the UDP4_SERVICE_DATA.\r
281 @param ImageHandle The image handle of this udp4 driver.\r
282 @param ControllerHandle The controller handle this udp4 driver binds on.\r
283\r
284 @retval EFI_SUCCESS The udp4 service context data is created and\r
285 initialized.\r
286 @retval EFI_OUT_OF_RESOURCES Cannot allocate memory.\r
bab52709 287 @retval other Other error occurs.\r
8a67d61d 288\r
289**/\r
290EFI_STATUS\r
291Udp4CreateService (\r
bab52709 292 IN OUT UDP4_SERVICE_DATA *Udp4Service,\r
293 IN EFI_HANDLE ImageHandle,\r
294 IN EFI_HANDLE ControllerHandle\r
8a67d61d 295 )\r
296{\r
297 EFI_STATUS Status;\r
298 IP_IO_OPEN_DATA OpenData;\r
299\r
e48e37fc 300 ZeroMem (Udp4Service, sizeof (UDP4_SERVICE_DATA));\r
c4a62a12 301\r
8a67d61d 302 Udp4Service->Signature = UDP4_SERVICE_DATA_SIGNATURE;\r
303 Udp4Service->ServiceBinding = mUdp4ServiceBinding;\r
304 Udp4Service->ImageHandle = ImageHandle;\r
305 Udp4Service->ControllerHandle = ControllerHandle;\r
306 Udp4Service->ChildrenNumber = 0;\r
307\r
e48e37fc 308 InitializeListHead (&Udp4Service->ChildrenList);\r
8a67d61d 309\r
310 //\r
311 // Create the IpIo for this service context.\r
312 //\r
313 Udp4Service->IpIo = IpIoCreate (ImageHandle, ControllerHandle);\r
314 if (Udp4Service->IpIo == NULL) {\r
315 return EFI_OUT_OF_RESOURCES;\r
316 }\r
317\r
318 //\r
319 // Set the OpenData used to open the IpIo.\r
320 //\r
687a2e5f 321 CopyMem (&OpenData.IpConfigData, &mIpIoDefaultIpConfigData, sizeof (OpenData.IpConfigData));\r
8a67d61d 322 OpenData.IpConfigData.AcceptBroadcast = TRUE;\r
323 OpenData.RcvdContext = (VOID *) Udp4Service;\r
324 OpenData.SndContext = NULL;\r
325 OpenData.PktRcvdNotify = Udp4DgramRcvd;\r
326 OpenData.PktSentNotify = Udp4DgramSent;\r
327\r
328 //\r
329 // Configure and start the IpIo.\r
330 //\r
331 Status = IpIoOpen (Udp4Service->IpIo, &OpenData);\r
332 if (EFI_ERROR (Status)) {\r
c4a62a12 333 goto ON_ERROR;\r
8a67d61d 334 }\r
335\r
336 //\r
337 // Create the event for Udp timeout checking.\r
338 //\r
339 Status = gBS->CreateEvent (\r
340 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
e48e37fc 341 TPL_CALLBACK,\r
8a67d61d 342 Udp4CheckTimeout,\r
343 Udp4Service,\r
344 &Udp4Service->TimeoutEvent\r
345 );\r
346 if (EFI_ERROR (Status)) {\r
c4a62a12 347 goto ON_ERROR;\r
8a67d61d 348 }\r
349\r
350 //\r
351 // Start the timeout timer event.\r
352 //\r
353 Status = gBS->SetTimer (\r
354 Udp4Service->TimeoutEvent,\r
355 TimerPeriodic,\r
356 UDP4_TIMEOUT_INTERVAL\r
357 );\r
358 if (EFI_ERROR (Status)) {\r
c4a62a12 359 goto ON_ERROR;\r
8a67d61d 360 }\r
361\r
8a67d61d 362 return EFI_SUCCESS;\r
363\r
c4a62a12 364ON_ERROR:\r
8a67d61d 365\r
c4a62a12 366 if (Udp4Service->TimeoutEvent != NULL) {\r
367 gBS->CloseEvent (Udp4Service->TimeoutEvent);\r
368 }\r
8a67d61d 369\r
370 IpIoDestroy (Udp4Service->IpIo);\r
371\r
372 return Status;\r
373}\r
374\r
375\r
376/**\r
377 Clean the Udp service context data.\r
378\r
379 @param Udp4Service Pointer to the UDP4_SERVICE_DATA.\r
380\r
381 @return None.\r
382\r
383**/\r
384VOID\r
385Udp4CleanService (\r
386 IN UDP4_SERVICE_DATA *Udp4Service\r
387 )\r
388{\r
389 //\r
390 // Cancel the TimeoutEvent timer.\r
391 //\r
392 gBS->SetTimer (Udp4Service->TimeoutEvent, TimerCancel, 0);\r
393\r
394 //\r
395 // Close the TimeoutEvent timer.\r
396 //\r
397 gBS->CloseEvent (Udp4Service->TimeoutEvent);\r
398\r
399 //\r
400 // Destroy the IpIo.\r
401 //\r
402 IpIoDestroy (Udp4Service->IpIo);\r
403}\r
404\r
405\r
406/**\r
407 This function checks and timeouts the I/O datagrams holding by the corresponding\r
408 service context.\r
409\r
410 @param Event The event this function registered to.\r
bab52709 411 @param Context The context data registered during the creation of\r
8a67d61d 412 the Event.\r
413\r
414 @return None.\r
415\r
416**/\r
8a67d61d 417VOID\r
418EFIAPI\r
419Udp4CheckTimeout (\r
420 IN EFI_EVENT Event,\r
421 IN VOID *Context\r
422 )\r
423{\r
424 UDP4_SERVICE_DATA *Udp4Service;\r
e48e37fc 425 LIST_ENTRY *Entry;\r
8a67d61d 426 UDP4_INSTANCE_DATA *Instance;\r
e48e37fc 427 LIST_ENTRY *WrapEntry;\r
428 LIST_ENTRY *NextEntry;\r
8a67d61d 429 UDP4_RXDATA_WRAP *Wrap;\r
430\r
431 Udp4Service = (UDP4_SERVICE_DATA *) Context;\r
432 NET_CHECK_SIGNATURE (Udp4Service, UDP4_SERVICE_DATA_SIGNATURE);\r
433\r
434 NET_LIST_FOR_EACH (Entry, &Udp4Service->ChildrenList) {\r
435 //\r
436 // Iterate all the instances belonging to this service context.\r
437 //\r
438 Instance = NET_LIST_USER_STRUCT (Entry, UDP4_INSTANCE_DATA, Link);\r
439 NET_CHECK_SIGNATURE (Instance, UDP4_INSTANCE_DATA_SIGNATURE);\r
440\r
441 if (!Instance->Configured || (Instance->ConfigData.ReceiveTimeout == 0)) {\r
442 //\r
443 // Skip this instance if it's not configured or no receive timeout.\r
444 //\r
445 continue;\r
446 }\r
447\r
448 NET_LIST_FOR_EACH_SAFE (WrapEntry, NextEntry, &Instance->RcvdDgramQue) {\r
449 //\r
450 // Iterate all the rxdatas belonging to this udp instance.\r
451 //\r
8792362f 452 Wrap = NET_LIST_USER_STRUCT (WrapEntry, UDP4_RXDATA_WRAP, Link);\r
8a67d61d 453\r
48bd50c5 454 //\r
455 // TimeoutTick unit is ms, MNP_TIMEOUT_CHECK_INTERVAL unit is 100ns.\r
456 //\r
457 if (Wrap->TimeoutTick <= (UDP4_TIMEOUT_INTERVAL / 10)) {\r
8a67d61d 458 //\r
459 // Remove this RxData if it timeouts.\r
460 //\r
461 Udp4RecycleRxDataWrap (NULL, (VOID *) Wrap);\r
462 } else {\r
48bd50c5 463 Wrap->TimeoutTick -= (UDP4_TIMEOUT_INTERVAL / 10);\r
8a67d61d 464 }\r
465 }\r
466 }\r
467}\r
468\r
469\r
470/**\r
471 This function intializes the new created udp instance.\r
472\r
473 @param Udp4Service Pointer to the UDP4_SERVICE_DATA.\r
474 @param Instance Pointer to the un-initialized UDP4_INSTANCE_DATA.\r
475\r
476 @return None.\r
477\r
478**/\r
479VOID\r
480Udp4InitInstance (\r
bab52709 481 IN UDP4_SERVICE_DATA *Udp4Service,\r
482 IN OUT UDP4_INSTANCE_DATA *Instance\r
8a67d61d 483 )\r
484{\r
485 //\r
486 // Set the signature.\r
487 //\r
488 Instance->Signature = UDP4_INSTANCE_DATA_SIGNATURE;\r
489\r
490 //\r
491 // Init the lists.\r
492 //\r
e48e37fc 493 InitializeListHead (&Instance->Link);\r
494 InitializeListHead (&Instance->RcvdDgramQue);\r
495 InitializeListHead (&Instance->DeliveredDgramQue);\r
8a67d61d 496\r
497 //\r
498 // Init the NET_MAPs.\r
499 //\r
500 NetMapInit (&Instance->TxTokens);\r
501 NetMapInit (&Instance->RxTokens);\r
502 NetMapInit (&Instance->McastIps);\r
503\r
504 //\r
505 // Save the pointer to the UDP4_SERVICE_DATA, and initialize other members.\r
506 //\r
507 Instance->Udp4Service = Udp4Service;\r
687a2e5f 508 CopyMem (&Instance->Udp4Proto, &mUdp4Protocol, sizeof (Instance->Udp4Proto));\r
8a67d61d 509 Instance->IcmpError = EFI_SUCCESS;\r
510 Instance->Configured = FALSE;\r
511 Instance->IsNoMapping = FALSE;\r
512 Instance->Destroyed = FALSE;\r
513}\r
514\r
515\r
516/**\r
517 This function cleans the udp instance.\r
518\r
519 @param Instance Pointer to the UDP4_INSTANCE_DATA to clean.\r
520\r
521 @return None.\r
522\r
523**/\r
524VOID\r
525Udp4CleanInstance (\r
526 IN UDP4_INSTANCE_DATA *Instance\r
527 )\r
528{\r
529 NetMapClean (&Instance->McastIps);\r
530 NetMapClean (&Instance->RxTokens);\r
531 NetMapClean (&Instance->TxTokens);\r
532}\r
533\r
534\r
535/**\r
536 This function finds the udp instance by the specified <Address, Port> pair.\r
537\r
538 @param InstanceList Pointer to the head of the list linking the udp\r
539 instances.\r
540 @param Address Pointer to the specified IPv4 address.\r
541 @param Port The udp port number.\r
542\r
bab52709 543 @retval TRUE The specified <Address, Port> pair is found.\r
544 @retval FALSE Otherwise.\r
8a67d61d 545\r
546**/\r
8a67d61d 547BOOLEAN\r
548Udp4FindInstanceByPort (\r
e48e37fc 549 IN LIST_ENTRY *InstanceList,\r
8a67d61d 550 IN EFI_IPv4_ADDRESS *Address,\r
551 IN UINT16 Port\r
552 )\r
553{\r
e48e37fc 554 LIST_ENTRY *Entry;\r
8a67d61d 555 UDP4_INSTANCE_DATA *Instance;\r
556 EFI_UDP4_CONFIG_DATA *ConfigData;\r
557\r
558 NET_LIST_FOR_EACH (Entry, InstanceList) {\r
559 //\r
560 // Iterate all the udp instances.\r
561 //\r
562 Instance = NET_LIST_USER_STRUCT (Entry, UDP4_INSTANCE_DATA, Link);\r
563 ConfigData = &Instance->ConfigData;\r
564\r
565 if (!Instance->Configured || ConfigData->AcceptAnyPort) {\r
566 //\r
567 // If the instance is not configured or the configdata of the instance indicates\r
568 // this instance accepts any port, skip it.\r
569 //\r
570 continue;\r
571 }\r
572\r
84b5c78e 573 if (EFI_IP4_EQUAL (&ConfigData->StationAddress, Address) &&\r
8a67d61d 574 (ConfigData->StationPort == Port)) {\r
575 //\r
576 // if both the address and the port are the same, return TRUE.\r
577 //\r
578 return TRUE;\r
579 }\r
580 }\r
581\r
582 //\r
583 // return FALSE when matching fails.\r
584 //\r
585 return FALSE;\r
586}\r
587\r
588\r
589/**\r
590 This function tries to bind the udp instance according to the configured port\r
bab52709 591 allocation strategy.\r
8a67d61d 592\r
593 @param InstanceList Pointer to the head of the list linking the udp\r
594 instances.\r
595 @param ConfigData Pointer to the ConfigData of the instance to be\r
bab52709 596 bound. ConfigData->StationPort will be assigned\r
597 with an available port value on success.\r
8a67d61d 598\r
599 @retval EFI_SUCCESS The bound operation is completed successfully.\r
600 @retval EFI_ACCESS_DENIED The <Address, Port> specified by the ConfigData is\r
601 already used by other instance.\r
602 @retval EFI_OUT_OF_RESOURCES No available port resources.\r
603\r
604**/\r
605EFI_STATUS\r
606Udp4Bind (\r
bab52709 607 IN LIST_ENTRY *InstanceList,\r
608 IN OUT EFI_UDP4_CONFIG_DATA *ConfigData\r
8a67d61d 609 )\r
610{\r
611 EFI_IPv4_ADDRESS *StationAddress;\r
612 UINT16 StartPort;\r
613\r
614 if (ConfigData->AcceptAnyPort) {\r
615 return EFI_SUCCESS;\r
616 }\r
617\r
618 StationAddress = &ConfigData->StationAddress;\r
619\r
620 if (ConfigData->StationPort != 0) {\r
621\r
622 if (!ConfigData->AllowDuplicatePort &&\r
623 Udp4FindInstanceByPort (InstanceList, StationAddress, ConfigData->StationPort)) {\r
624 //\r
625 // Do not allow duplicate port and the port is already used by other instance.\r
626 //\r
627 return EFI_ACCESS_DENIED;\r
628 }\r
629 } else {\r
630 //\r
631 // select a random port for this instance;\r
632 //\r
633\r
634 if (ConfigData->AllowDuplicatePort) {\r
635 //\r
636 // Just pick up the random port if the instance allows duplicate port.\r
637 //\r
638 ConfigData->StationPort = mUdp4RandomPort;\r
639 } else {\r
640\r
641 StartPort = mUdp4RandomPort;\r
642\r
643 while (Udp4FindInstanceByPort(InstanceList, StationAddress, mUdp4RandomPort)) {\r
644\r
645 mUdp4RandomPort++;\r
646 if (mUdp4RandomPort == 0) {\r
647 mUdp4RandomPort = UDP4_PORT_KNOWN;\r
648 }\r
649\r
650 if (mUdp4RandomPort == StartPort) {\r
651 //\r
652 // No available port.\r
653 //\r
654 return EFI_OUT_OF_RESOURCES;\r
655 }\r
656 }\r
657\r
658 ConfigData->StationPort = mUdp4RandomPort;\r
659 }\r
660\r
661 mUdp4RandomPort++;\r
662 if (mUdp4RandomPort == 0) {\r
663 mUdp4RandomPort = UDP4_PORT_KNOWN;\r
664 }\r
665 }\r
666\r
667 return EFI_SUCCESS;\r
668}\r
669\r
670\r
671/**\r
672 This function is used to check whether the NewConfigData has any un-reconfigurable\r
673 parameters changed compared to the OldConfigData.\r
674\r
675 @param OldConfigData Pointer to the current ConfigData the udp instance\r
676 uses.\r
677 @param NewConfigData Pointer to the new ConfigData.\r
678\r
bab52709 679 @retval TRUE The instance is reconfigurable.\r
680 @retval FALSE Otherwise.\r
8a67d61d 681\r
682**/\r
683BOOLEAN\r
684Udp4IsReconfigurable (\r
685 IN EFI_UDP4_CONFIG_DATA *OldConfigData,\r
686 IN EFI_UDP4_CONFIG_DATA *NewConfigData\r
687 )\r
688{\r
bab52709 689 if ((NewConfigData->AcceptAnyPort != OldConfigData->AcceptAnyPort) ||\r
690 (NewConfigData->AcceptBroadcast != OldConfigData->AcceptBroadcast) ||\r
691 (NewConfigData->AcceptPromiscuous != OldConfigData->AcceptPromiscuous) ||\r
692 (NewConfigData->AllowDuplicatePort != OldConfigData->AllowDuplicatePort)\r
693 ) {\r
8a67d61d 694 //\r
695 // The receiving filter parameters cannot be changed.\r
696 //\r
697 return FALSE;\r
698 }\r
699\r
700 if ((!NewConfigData->AcceptAnyPort) &&\r
bab52709 701 (NewConfigData->StationPort != OldConfigData->StationPort)\r
702 ) {\r
8a67d61d 703 //\r
704 // The port is not changeable.\r
705 //\r
706 return FALSE;\r
707 }\r
708\r
709 if (!NewConfigData->AcceptPromiscuous) {\r
710\r
711 if (NewConfigData->UseDefaultAddress != OldConfigData->UseDefaultAddress) {\r
712 //\r
713 // The NewConfigData differs to the old one on the UseDefaultAddress.\r
714 //\r
715 return FALSE;\r
716 }\r
717\r
718 if (!NewConfigData->UseDefaultAddress &&\r
bab52709 719 (!EFI_IP4_EQUAL (&NewConfigData->StationAddress, &OldConfigData->StationAddress) ||\r
720 !EFI_IP4_EQUAL (&NewConfigData->SubnetMask, &OldConfigData->SubnetMask))\r
721 ) {\r
8a67d61d 722 //\r
723 // If the instance doesn't use the default address, and the new address or\r
724 // new subnet mask is different from the old values.\r
725 //\r
726 return FALSE;\r
727 }\r
728 }\r
729\r
84b5c78e 730 if (!EFI_IP4_EQUAL (&NewConfigData->RemoteAddress, &OldConfigData->RemoteAddress)) {\r
8a67d61d 731 //\r
732 // The remoteaddress is not the same.\r
733 //\r
734 return FALSE;\r
735 }\r
736\r
bab52709 737 if (!EFI_IP4_EQUAL (&NewConfigData->RemoteAddress, &mZeroIp4Addr) &&\r
738 NewConfigData->RemotePort != OldConfigData->RemotePort\r
739 ) {\r
8a67d61d 740 //\r
741 // The RemotePort differs if it's designated in the configdata.\r
742 //\r
743 return FALSE;\r
744 }\r
745\r
746 //\r
747 // All checks pass, return TRUE.\r
748 //\r
749 return TRUE;\r
750}\r
751\r
752\r
753/**\r
754 This function builds the Ip4 configdata from the Udp4ConfigData.\r
755\r
756 @param Udp4ConfigData Pointer to the EFI_UDP4_CONFIG_DATA.\r
757 @param Ip4ConfigData Pointer to the EFI_IP4_CONFIG_DATA.\r
758\r
759 @return None.\r
760\r
761**/\r
762VOID\r
763Udp4BuildIp4ConfigData (\r
bab52709 764 IN EFI_UDP4_CONFIG_DATA *Udp4ConfigData,\r
765 IN OUT EFI_IP4_CONFIG_DATA *Ip4ConfigData\r
8a67d61d 766 )\r
767{\r
687a2e5f 768 CopyMem (Ip4ConfigData, &mIpIoDefaultIpConfigData, sizeof (*Ip4ConfigData));\r
4eb65aff 769\r
8a67d61d 770 Ip4ConfigData->DefaultProtocol = EFI_IP_PROTO_UDP;\r
771 Ip4ConfigData->AcceptBroadcast = Udp4ConfigData->AcceptBroadcast;\r
772 Ip4ConfigData->AcceptPromiscuous = Udp4ConfigData->AcceptPromiscuous;\r
773 Ip4ConfigData->UseDefaultAddress = Udp4ConfigData->UseDefaultAddress;\r
36ee91ca 774 CopyMem (&Ip4ConfigData->StationAddress, &Udp4ConfigData->StationAddress, sizeof (EFI_IPv4_ADDRESS));\r
775 CopyMem (&Ip4ConfigData->SubnetMask, &Udp4ConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
8a67d61d 776\r
777 //\r
778 // use the -1 magic number to disable the receiving process of the ip instance.\r
779 //\r
780 Ip4ConfigData->ReceiveTimeout = (UINT32) (-1);\r
781}\r
782\r
783\r
784/**\r
785 This function validates the TxToken, it returns the error code according to the spec.\r
786\r
787 @param Instance Pointer to the udp instance context data.\r
788 @param TxToken Pointer to the token to be checked.\r
789\r
790 @retval EFI_SUCCESS The TxToken is valid.\r
791 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: This is\r
792 NULL. Token is NULL. Token.Event is NULL.\r
793 Token.Packet.TxData is NULL.\r
794 Token.Packet.TxData.FragmentCount is zero.\r
795 Token.Packet.TxData.DataLength is not equal to the\r
796 sum of fragment lengths. One or more of the\r
797 Token.Packet.TxData.FragmentTable[].\r
798 FragmentLength fields is zero. One or more of the\r
799 Token.Packet.TxData.FragmentTable[].\r
800 FragmentBuffer fields is NULL.\r
801 Token.Packet.TxData. GatewayAddress is not a\r
802 unicast IPv4 address if it is not NULL. One or\r
803 more IPv4 addresses in Token.Packet.TxData.\r
804 UdpSessionData are not valid unicast IPv4\r
805 addresses if the UdpSessionData is not NULL.\r
806 @retval EFI_BAD_BUFFER_SIZE The data length is greater than the maximum UDP\r
807 packet size.\r
808\r
809**/\r
810EFI_STATUS\r
811Udp4ValidateTxToken (\r
812 IN UDP4_INSTANCE_DATA *Instance,\r
813 IN EFI_UDP4_COMPLETION_TOKEN *TxToken\r
814 )\r
815{\r
816 EFI_UDP4_TRANSMIT_DATA *TxData;\r
817 UINT32 Index;\r
818 UINT32 TotalLen;\r
819 EFI_UDP4_CONFIG_DATA *ConfigData;\r
820 EFI_UDP4_SESSION_DATA *UdpSessionData;\r
821 IP4_ADDR SourceAddress;\r
772db4bb 822 IP4_ADDR GatewayAddress;\r
8a67d61d 823\r
824 if (TxToken->Event == NULL) {\r
825 return EFI_INVALID_PARAMETER;\r
826 }\r
827\r
828 TxData = TxToken->Packet.TxData;\r
829\r
830 if ((TxData == NULL) || (TxData->FragmentCount == 0)) {\r
831 return EFI_INVALID_PARAMETER;\r
832 }\r
833\r
834 TotalLen = 0;\r
835 for (Index = 0; Index < TxData->FragmentCount; Index++) {\r
836\r
837 if ((TxData->FragmentTable[Index].FragmentBuffer == NULL) ||\r
838 (TxData->FragmentTable[Index].FragmentLength == 0)) {\r
839 //\r
840 // if the FragmentBuffer is NULL or the FragmentLeng is zero.\r
841 //\r
842 return EFI_INVALID_PARAMETER;\r
843 }\r
844\r
845 TotalLen += TxData->FragmentTable[Index].FragmentLength;\r
846 }\r
847\r
848 if (TotalLen != TxData->DataLength) {\r
849 //\r
850 // The TotalLen calculated by adding all the FragmentLeng doesn't equal to the\r
851 // DataLength.\r
852 //\r
853 return EFI_INVALID_PARAMETER;\r
854 }\r
855\r
772db4bb 856 if (TxData->GatewayAddress != NULL) {\r
e48e37fc 857 CopyMem (&GatewayAddress, TxData->GatewayAddress, sizeof (IP4_ADDR));\r
772db4bb 858\r
859 if (!Ip4IsUnicast (NTOHL (GatewayAddress), 0)) {\r
860 //\r
861 // The specified GatewayAddress is not a unicast IPv4 address while it's not 0.\r
862 //\r
863 return EFI_INVALID_PARAMETER;\r
864 }\r
8a67d61d 865 }\r
866\r
867 ConfigData = &Instance->ConfigData;\r
868 UdpSessionData = TxData->UdpSessionData;\r
869\r
870 if (UdpSessionData != NULL) {\r
871\r
e48e37fc 872 CopyMem (&SourceAddress, &UdpSessionData->SourceAddress, sizeof (IP4_ADDR));\r
8a67d61d 873\r
772db4bb 874 if ((SourceAddress != 0) && !Ip4IsUnicast (HTONL (SourceAddress), 0)) {\r
8a67d61d 875 //\r
876 // Check whether SourceAddress is a valid IPv4 address in case it's not zero.\r
877 // The configured station address is used if SourceAddress is zero.\r
878 //\r
879 return EFI_INVALID_PARAMETER;\r
880 }\r
881\r
882 if ((UdpSessionData->DestinationPort == 0) && (ConfigData->RemotePort == 0)) {\r
883 //\r
884 // Ambiguous, no avalaible DestinationPort for this token.\r
885 //\r
886 return EFI_INVALID_PARAMETER;\r
887 }\r
888\r
84b5c78e 889 if (EFI_IP4_EQUAL (&UdpSessionData->DestinationAddress, &mZeroIp4Addr)) {\r
8a67d61d 890 //\r
891 // The DestinationAddress specified in the UdpSessionData is 0.\r
892 //\r
893 return EFI_INVALID_PARAMETER;\r
894 }\r
84b5c78e 895 } else if (EFI_IP4_EQUAL (&ConfigData->RemoteAddress, &mZeroIp4Addr)) {\r
8a67d61d 896 //\r
897 // the configured RemoteAddress is all zero, and the user doens't override the\r
898 // destination address.\r
899 //\r
900 return EFI_INVALID_PARAMETER;\r
901 }\r
902\r
903 if (TxData->DataLength > UDP4_MAX_DATA_SIZE) {\r
904 return EFI_BAD_BUFFER_SIZE;\r
905 }\r
906\r
907 return EFI_SUCCESS;\r
908}\r
909\r
910\r
911/**\r
912 This function checks whether the specified Token duplicates with the one in the Map.\r
913\r
914 @param Map Pointer to the NET_MAP.\r
915 @param Item Pointer to the NET_MAP_ITEM contain the pointer to\r
916 the Token.\r
917 @param Context Pointer to the Token to be checked.\r
918\r
919 @retval EFI_SUCCESS The Token specified by Context differs from the\r
920 one in the Item.\r
921 @retval EFI_ACCESS_DENIED The Token duplicates with the one in the Item.\r
922\r
923**/\r
924EFI_STATUS\r
925Udp4TokenExist (\r
926 IN NET_MAP *Map,\r
927 IN NET_MAP_ITEM *Item,\r
928 IN VOID *Context\r
929 )\r
930{\r
931 EFI_UDP4_COMPLETION_TOKEN *Token;\r
932 EFI_UDP4_COMPLETION_TOKEN *TokenInItem;\r
933\r
934 Token = (EFI_UDP4_COMPLETION_TOKEN*) Context;\r
935 TokenInItem = (EFI_UDP4_COMPLETION_TOKEN*) Item->Key;\r
936\r
937 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {\r
938 //\r
939 // The Token duplicates with the TokenInItem in case either the two pointers are the\r
940 // same or the Events of these two tokens are the same.\r
941 //\r
942 return EFI_ACCESS_DENIED;\r
943 }\r
944\r
945 return EFI_SUCCESS;\r
946}\r
947\r
948\r
949/**\r
950 This function calculates the checksum for the Packet, utilizing the pre-calculated\r
951 pseudo HeadSum to reduce some overhead.\r
952\r
953 @param Packet Pointer to the NET_BUF contains the udp datagram.\r
954 @param HeadSum Checksum of the pseudo header execpt the length\r
955 field.\r
956\r
957 @return The 16-bit checksum of this udp datagram.\r
958\r
959**/\r
960UINT16\r
961Udp4Checksum (\r
962 IN NET_BUF *Packet,\r
963 IN UINT16 HeadSum\r
964 )\r
965{\r
966 UINT16 Checksum;\r
967\r
968 Checksum = NetbufChecksum (Packet);\r
969 Checksum = NetAddChecksum (Checksum, HeadSum);\r
970\r
971 Checksum = NetAddChecksum (Checksum, HTONS ((UINT16) Packet->TotalSize));\r
972\r
687a2e5f 973 return (UINT16) ~Checksum;\r
8a67d61d 974}\r
975\r
976\r
977/**\r
978 This function removes the specified Token from the TokenMap.\r
979\r
980 @param TokenMap Pointer to the NET_MAP containing the tokens.\r
981 @param Token Pointer to the Token to be removed.\r
982\r
983 @retval EFI_SUCCESS The specified Token is removed from the TokenMap.\r
984 @retval EFI_NOT_FOUND The specified Token is not found in the TokenMap.\r
985\r
986**/\r
987EFI_STATUS\r
988Udp4RemoveToken (\r
bab52709 989 IN OUT NET_MAP *TokenMap,\r
990 IN EFI_UDP4_COMPLETION_TOKEN *Token\r
8a67d61d 991 )\r
992{\r
993 NET_MAP_ITEM *Item;\r
994\r
995 //\r
996 // Find the Token first.\r
997 //\r
998 Item = NetMapFindKey (TokenMap, (VOID *) Token);\r
999\r
1000 if (Item != NULL) {\r
1001 //\r
1002 // Remove the token if it's found in the map.\r
1003 //\r
1004 NetMapRemoveItem (TokenMap, Item, NULL);\r
1005\r
1006 return EFI_SUCCESS;\r
1007 }\r
1008\r
1009 return EFI_NOT_FOUND;\r
1010}\r
1011\r
1012\r
1013/**\r
1014 This function is the packet transmitting notify function registered to the IpIo\r
1015 interface. It's called to signal the udp TxToken when IpIo layer completes the\r
1016 transmitting of the udp datagram.\r
1017\r
1018 @param Status The completion status of the output udp datagram.\r
1019 @param Context Pointer to the context data.\r
1020 @param Sender Pointer to the Ip sender of the udp datagram.\r
1021 @param NotifyData Pointer to the notify data.\r
1022\r
1023 @return None.\r
1024\r
1025**/\r
8a67d61d 1026VOID\r
1027Udp4DgramSent (\r
1028 IN EFI_STATUS Status,\r
1029 IN VOID *Context,\r
1030 IN VOID *Sender,\r
1031 IN VOID *NotifyData\r
1032 )\r
1033{\r
1034 UDP4_INSTANCE_DATA *Instance;\r
1035 EFI_UDP4_COMPLETION_TOKEN *Token;\r
1036\r
1037 Instance = (UDP4_INSTANCE_DATA *) Context;\r
1038 Token = (EFI_UDP4_COMPLETION_TOKEN *) NotifyData;\r
1039\r
1040 if (Udp4RemoveToken (&Instance->TxTokens, Token) == EFI_SUCCESS) {\r
1041 //\r
1042 // The token may be cancelled. Only signal it if the remove operation succeeds.\r
1043 //\r
1044 Token->Status = Status;\r
1045 gBS->SignalEvent (Token->Event);\r
36ee91ca 1046 NetLibDispatchDpc ();\r
8a67d61d 1047 }\r
1048}\r
1049\r
1050\r
1051/**\r
1052 This function processes the received datagram passed up by the IpIo layer.\r
1053\r
1054 @param Status The status of this udp datagram.\r
1055 @param IcmpError The IcmpError code, only available when Status is\r
1056 EFI_ICMP_ERROR.\r
1057 @param NetSession Pointer to the EFI_NET_SESSION_DATA.\r
1058 @param Packet Pointer to the NET_BUF containing the received udp\r
1059 datagram.\r
1060 @param Context Pointer to the context data.\r
1061\r
1062 @return None.\r
1063\r
1064**/\r
8a67d61d 1065VOID\r
1066Udp4DgramRcvd (\r
1067 IN EFI_STATUS Status,\r
1068 IN ICMP_ERROR IcmpError,\r
1069 IN EFI_NET_SESSION_DATA *NetSession,\r
1070 IN NET_BUF *Packet,\r
1071 IN VOID *Context\r
1072 )\r
1073{\r
1074 NET_CHECK_SIGNATURE (Packet, NET_BUF_SIGNATURE);\r
1075\r
1076 //\r
1077 // IpIo only passes received packets with Status EFI_SUCCESS or EFI_ICMP_ERROR.\r
1078 //\r
1079 if (Status == EFI_SUCCESS) {\r
1080 //\r
1081 // Demultiplex the received datagram.\r
1082 //\r
1083 Udp4Demultiplex ((UDP4_SERVICE_DATA *) Context, NetSession, Packet);\r
1084 } else {\r
1085 //\r
1086 // Handle the ICMP_ERROR packet.\r
1087 //\r
1088 Udp4IcmpHandler ((UDP4_SERVICE_DATA *) Context, IcmpError, NetSession, Packet);\r
1089 }\r
36ee91ca 1090\r
1091 //\r
1092 // Dispatch the DPC queued by the NotifyFunction of the rx token's events\r
1093 // which are signaled with received data.\r
1094 //\r
1095 NetLibDispatchDpc ();\r
8a67d61d 1096}\r
1097\r
1098\r
1099/**\r
1100 This function removes the multicast group specified by Arg from the Map.\r
1101\r
1102 @param Map Pointer to the NET_MAP.\r
1103 @param Item Pointer to the NET_MAP_ITEM.\r
1104 @param Arg Pointer to the Arg, it's the pointer to a\r
1105 multicast IPv4 Address.\r
1106\r
1107 @retval EFI_SUCCESS The multicast address is removed.\r
1108 @retval EFI_ABORTED The specified multicast address is removed and the\r
1109 Arg is not NULL.\r
1110\r
1111**/\r
1112EFI_STATUS\r
1113Udp4LeaveGroup (\r
bab52709 1114 IN OUT NET_MAP *Map,\r
1115 IN NET_MAP_ITEM *Item,\r
1116 IN VOID *Arg OPTIONAL\r
8a67d61d 1117 )\r
1118{\r
1119 EFI_IPv4_ADDRESS *McastIp;\r
1120\r
1121 McastIp = Arg;\r
1122\r
84b5c78e 1123 if ((McastIp != NULL) && (!EFI_IP4_EQUAL (McastIp, &(Item->Key)))) {\r
8a67d61d 1124 //\r
687a2e5f 1125 // McastIp is not NULL and the multicast address contained in the Item\r
8a67d61d 1126 // is not the same as McastIp.\r
1127 //\r
1128 return EFI_SUCCESS;\r
1129 }\r
1130\r
1131 //\r
1132 // Remove this Item.\r
1133 //\r
1134 NetMapRemoveItem (Map, Item, NULL);\r
1135\r
1136 if (McastIp != NULL) {\r
1137 //\r
1138 // Return EFI_ABORTED in case McastIp is not NULL to terminate the iteration.\r
1139 //\r
1140 return EFI_ABORTED;\r
1141 }\r
1142\r
1143 return EFI_SUCCESS;\r
1144}\r
1145\r
1146\r
1147/**\r
bab52709 1148 This function cancels the token specified by Arg in the Map. This is a callback\r
1149 used by Udp4InstanceCancelToken().\r
8a67d61d 1150\r
1151 @param Map Pointer to the NET_MAP.\r
1152 @param Item Pointer to the NET_MAP_ITEM.\r
bab52709 1153 @param Arg Pointer to the token to be cancelled, if NULL,\r
1154 the token specified by Item is cancelled.\r
8a67d61d 1155\r
1156 @retval EFI_SUCCESS The token is cancelled if Arg is NULL or the token\r
1157 is not the same as that in the Item if Arg is not\r
1158 NULL.\r
1159 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is\r
1160 cancelled.\r
1161\r
1162**/\r
8a67d61d 1163EFI_STATUS\r
1164Udp4CancelTokens (\r
1165 IN NET_MAP *Map,\r
1166 IN NET_MAP_ITEM *Item,\r
1167 IN VOID *Arg OPTIONAL\r
1168 )\r
1169{\r
1170 EFI_UDP4_COMPLETION_TOKEN *TokenToCancel;\r
1171 NET_BUF *Packet;\r
1172 IP_IO *IpIo;\r
1173\r
1174 if ((Arg != NULL) && (Item->Key != Arg)) {\r
1175 return EFI_SUCCESS;\r
1176 }\r
1177\r
1178 if (Item->Value != NULL) {\r
1179 //\r
1180 // If the token is a transmit token, the corresponding Packet is recorded in\r
1181 // Item->Value, invoke IpIo to cancel this packet first. The IpIoCancelTxToken\r
1182 // will invoke Udp4DgramSent, the token will be signaled and this Item will\r
1183 // be removed from the Map there.\r
1184 //\r
1185 Packet = (NET_BUF *) (Item->Value);\r
1186 IpIo = (IP_IO *) (*((UINTN *) &Packet->ProtoData[0]));\r
1187\r
1188 IpIoCancelTxToken (IpIo, Packet);\r
1189 } else {\r
1190 //\r
1191 // The token is a receive token. Abort it and remove it from the Map.\r
1192 //\r
1193 TokenToCancel = (EFI_UDP4_COMPLETION_TOKEN *) Item->Key;\r
36ee91ca 1194 NetMapRemoveItem (Map, Item, NULL);\r
8a67d61d 1195\r
1196 TokenToCancel->Status = EFI_ABORTED;\r
1197 gBS->SignalEvent (TokenToCancel->Event);\r
8a67d61d 1198 }\r
1199\r
1200 if (Arg != NULL) {\r
1201 return EFI_ABORTED;\r
1202 }\r
1203\r
1204 return EFI_SUCCESS;\r
1205}\r
1206\r
1207\r
1208/**\r
1209 This function removes all the Wrap datas in the RcvdDgramQue.\r
1210\r
bab52709 1211 @param Instance Pointer to the udp instance context data.\r
8a67d61d 1212\r
1213 @return None.\r
1214\r
1215**/\r
1216VOID\r
36ee91ca 1217Udp4FlushRcvdDgram (\r
1218 IN UDP4_INSTANCE_DATA *Instance\r
8a67d61d 1219 )\r
1220{\r
1221 UDP4_RXDATA_WRAP *Wrap;\r
8a67d61d 1222\r
e48e37fc 1223 while (!IsListEmpty (&Instance->RcvdDgramQue)) {\r
8a67d61d 1224 //\r
1225 // Iterate all the Wraps in the RcvdDgramQue.\r
1226 //\r
36ee91ca 1227 Wrap = NET_LIST_HEAD (&Instance->RcvdDgramQue, UDP4_RXDATA_WRAP, Link);\r
8a67d61d 1228\r
1229 //\r
1230 // The Wrap will be removed from the RcvdDgramQue by this function call.\r
1231 //\r
1232 Udp4RecycleRxDataWrap (NULL, (VOID *) Wrap);\r
1233 }\r
8a67d61d 1234}\r
1235\r
1236\r
1237\r
1238/**\r
bab52709 1239 Cancel Udp4 tokens from the Udp4 instance.\r
8a67d61d 1240\r
1241 @param Instance Pointer to the udp instance context data.\r
1242 @param Token Pointer to the token to be canceled, if NULL, all\r
1243 tokens in this instance will be cancelled.\r
1244\r
1245 @retval EFI_SUCCESS The Token is cancelled.\r
1246 @retval EFI_NOT_FOUND The Token is not found.\r
1247\r
1248**/\r
1249EFI_STATUS\r
1250Udp4InstanceCancelToken (\r
1251 IN UDP4_INSTANCE_DATA *Instance,\r
1252 IN EFI_UDP4_COMPLETION_TOKEN *Token OPTIONAL\r
1253 )\r
1254{\r
1255 EFI_STATUS Status;\r
1256\r
1257 //\r
bab52709 1258 // Cancel this token from the TxTokens map.\r
8a67d61d 1259 //\r
1260 Status = NetMapIterate (&Instance->TxTokens, Udp4CancelTokens, Token);\r
1261\r
1262 if ((Token != NULL) && (Status == EFI_ABORTED)) {\r
1263 //\r
1264 // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from\r
1265 // the TxTokens, just return success.\r
1266 //\r
1267 return EFI_SUCCESS;\r
1268 }\r
1269\r
1270 //\r
1271 // Try to cancel this token from the RxTokens map in condition either the Token\r
1272 // is NULL or the specified Token is not in TxTokens.\r
1273 //\r
1274 Status = NetMapIterate (&Instance->RxTokens, Udp4CancelTokens, Token);\r
1275\r
1276 if ((Token != NULL) && (Status == EFI_SUCCESS)) {\r
1277 //\r
1278 // If Token isn't NULL and Status is EFI_SUCCESS, the token is neither in the\r
1279 // TxTokens nor the RxTokens, or say, it's not found.\r
1280 //\r
1281 return EFI_NOT_FOUND;\r
1282 }\r
1283\r
1284 ASSERT ((Token != NULL) || ((0 == NetMapGetCount (&Instance->TxTokens))\r
1285 && (0 == NetMapGetCount (&Instance->RxTokens))));\r
1286\r
1287 return EFI_SUCCESS;\r
1288}\r
1289\r
1290\r
1291/**\r
1292 This function matches the received udp datagram with the Instance.\r
1293\r
1294 @param Instance Pointer to the udp instance context data.\r
1295 @param Udp4Session Pointer to the EFI_UDP4_SESSION_DATA abstracted\r
1296 from the received udp datagram.\r
1297\r
bab52709 1298 @retval TRUE The udp datagram matches the receiving requirments of the\r
1299 udp Instance.\r
1300 @retval FALSE Otherwise.\r
8a67d61d 1301\r
1302**/\r
8a67d61d 1303BOOLEAN\r
1304Udp4MatchDgram (\r
1305 IN UDP4_INSTANCE_DATA *Instance,\r
1306 IN EFI_UDP4_SESSION_DATA *Udp4Session\r
1307 )\r
1308{\r
1309 EFI_UDP4_CONFIG_DATA *ConfigData;\r
1310 IP4_ADDR Destination;\r
1311\r
1312 ConfigData = &Instance->ConfigData;\r
1313\r
1314 if (ConfigData->AcceptPromiscuous) {\r
1315 //\r
1316 // Always matches if this instance is in the promiscuous state.\r
1317 //\r
1318 return TRUE;\r
1319 }\r
1320\r
1321 if ((!ConfigData->AcceptAnyPort && (Udp4Session->DestinationPort != ConfigData->StationPort)) ||\r
bab52709 1322 ((ConfigData->RemotePort != 0) && (Udp4Session->SourcePort != ConfigData->RemotePort))\r
1323 ) {\r
8a67d61d 1324 //\r
1325 // The local port or the remote port doesn't match.\r
1326 //\r
1327 return FALSE;\r
1328 }\r
1329\r
84b5c78e 1330 if (!EFI_IP4_EQUAL (&ConfigData->RemoteAddress, &mZeroIp4Addr) &&\r
bab52709 1331 !EFI_IP4_EQUAL (&ConfigData->RemoteAddress, &Udp4Session->SourceAddress)\r
1332 ) {\r
8a67d61d 1333 //\r
1334 // This datagram doesn't come from the instance's specified sender.\r
1335 //\r
1336 return FALSE;\r
1337 }\r
1338\r
84b5c78e 1339 if (EFI_IP4_EQUAL (&ConfigData->StationAddress, &mZeroIp4Addr) ||\r
bab52709 1340 EFI_IP4_EQUAL (&Udp4Session->DestinationAddress, &ConfigData->StationAddress)\r
1341 ) {\r
8a67d61d 1342 //\r
bab52709 1343 // The instance is configured to receive datagrams destined to any station IP or\r
8a67d61d 1344 // the destination address of this datagram matches the configured station IP.\r
1345 //\r
1346 return TRUE;\r
1347 }\r
1348\r
e48e37fc 1349 CopyMem (&Destination, &Udp4Session->DestinationAddress, sizeof (IP4_ADDR));\r
8a67d61d 1350\r
1351 if (IP4_IS_LOCAL_BROADCAST (Destination) && ConfigData->AcceptBroadcast) {\r
1352 //\r
1353 // The instance is configured to receive broadcast and this is a broadcast packet.\r
1354 //\r
1355 return TRUE;\r
1356 }\r
1357\r
1358 if (IP4_IS_MULTICAST (NTOHL (Destination)) &&\r
bab52709 1359 NetMapFindKey (&Instance->McastIps, (VOID *) (UINTN) Destination) != NULL\r
1360 ) {\r
8a67d61d 1361 //\r
1362 // It's a multicast packet and the multicast address is accepted by this instance.\r
1363 //\r
1364 return TRUE;\r
1365 }\r
1366\r
1367 return FALSE;\r
1368}\r
1369\r
1370\r
1371/**\r
1372 This function removes the Wrap specified by Context and release relevant resources.\r
1373\r
1374 @param Event The Event this notify function registered to.\r
1375 @param Context Pointer to the context data.\r
1376\r
1377 @return None.\r
1378\r
1379**/\r
8a67d61d 1380VOID\r
1381EFIAPI\r
1382Udp4RecycleRxDataWrap (\r
1383 IN EFI_EVENT Event,\r
1384 IN VOID *Context\r
1385 )\r
1386{\r
1387 UDP4_RXDATA_WRAP *Wrap;\r
1388\r
1389 Wrap = (UDP4_RXDATA_WRAP *) Context;\r
1390\r
1391 //\r
1392 // Remove the Wrap from the list it belongs to.\r
1393 //\r
e48e37fc 1394 RemoveEntryList (&Wrap->Link);\r
8a67d61d 1395\r
1396 //\r
1397 // Free the Packet associated with this Wrap.\r
1398 //\r
1399 NetbufFree (Wrap->Packet);\r
1400\r
1401 //\r
1402 // Close the event.\r
1403 //\r
1404 gBS->CloseEvent (Wrap->RxData.RecycleSignal);\r
1405\r
e48e37fc 1406 gBS->FreePool (Wrap);\r
8a67d61d 1407}\r
1408\r
1409\r
1410/**\r
1411 This function wraps the Packet and the RxData.\r
1412\r
1413 @param Instance Pointer to the instance context data.\r
1414 @param Packet Pointer to the buffer containing the received\r
1415 datagram.\r
1416 @param RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this\r
1417 datagram.\r
1418\r
1419 @return Pointer to the structure wrapping the RxData and the Packet.\r
1420\r
1421**/\r
8a67d61d 1422UDP4_RXDATA_WRAP *\r
1423Udp4WrapRxData (\r
1424 IN UDP4_INSTANCE_DATA *Instance,\r
1425 IN NET_BUF *Packet,\r
1426 IN EFI_UDP4_RECEIVE_DATA *RxData\r
1427 )\r
1428{\r
1429 EFI_STATUS Status;\r
1430 UDP4_RXDATA_WRAP *Wrap;\r
1431\r
1432 //\r
1433 // Allocate buffer for the Wrap.\r
1434 //\r
e48e37fc 1435 Wrap = AllocatePool (sizeof (UDP4_RXDATA_WRAP) +\r
8a67d61d 1436 (Packet->BlockOpNum - 1) * sizeof (EFI_UDP4_FRAGMENT_DATA));\r
1437 if (Wrap == NULL) {\r
1438 return NULL;\r
1439 }\r
1440\r
e48e37fc 1441 InitializeListHead (&Wrap->Link);\r
8a67d61d 1442\r
687a2e5f 1443 CopyMem (&Wrap->RxData, RxData, sizeof (Wrap->RxData));\r
8a67d61d 1444\r
1445 //\r
1446 // Create the Recycle event.\r
1447 //\r
1448 Status = gBS->CreateEvent (\r
1449 EVT_NOTIFY_SIGNAL,\r
e48e37fc 1450 TPL_NOTIFY,\r
8a67d61d 1451 Udp4RecycleRxDataWrap,\r
1452 Wrap,\r
1453 &Wrap->RxData.RecycleSignal\r
1454 );\r
1455 if (EFI_ERROR (Status)) {\r
e48e37fc 1456 gBS->FreePool (Wrap);\r
8a67d61d 1457 return NULL;\r
1458 }\r
1459\r
1460 Wrap->Packet = Packet;\r
1461 Wrap->TimeoutTick = Instance->ConfigData.ReceiveTimeout;\r
1462\r
1463 return Wrap;\r
1464}\r
1465\r
1466\r
1467/**\r
1468 This function enqueues the received datagram into the instances' receiving queues.\r
1469\r
1470 @param Udp4Service Pointer to the udp service context data.\r
1471 @param Packet Pointer to the buffer containing the received\r
1472 datagram.\r
1473 @param RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this\r
1474 datagram.\r
1475\r
1476 @return The times this datagram is enqueued.\r
1477\r
1478**/\r
8a67d61d 1479UINTN\r
1480Udp4EnqueueDgram (\r
1481 IN UDP4_SERVICE_DATA *Udp4Service,\r
1482 IN NET_BUF *Packet,\r
1483 IN EFI_UDP4_RECEIVE_DATA *RxData\r
1484 )\r
1485{\r
e48e37fc 1486 LIST_ENTRY *Entry;\r
8a67d61d 1487 UDP4_INSTANCE_DATA *Instance;\r
1488 UDP4_RXDATA_WRAP *Wrap;\r
1489 UINTN Enqueued;\r
1490\r
1491 Enqueued = 0;\r
1492\r
1493 NET_LIST_FOR_EACH (Entry, &Udp4Service->ChildrenList) {\r
1494 //\r
1495 // Iterate the instances.\r
1496 //\r
1497 Instance = NET_LIST_USER_STRUCT (Entry, UDP4_INSTANCE_DATA, Link);\r
1498\r
1499 if (!Instance->Configured) {\r
1500 continue;\r
1501 }\r
1502\r
1503 if (Udp4MatchDgram (Instance, &RxData->UdpSession)) {\r
1504 //\r
1505 // Wrap the RxData and put this Wrap into the instances RcvdDgramQue.\r
1506 //\r
e5e12de7 1507 Wrap = Udp4WrapRxData (Instance, Packet, RxData);\r
8a67d61d 1508 if (Wrap == NULL) {\r
1509 continue;\r
1510 }\r
1511\r
1512 NET_GET_REF (Packet);\r
1513\r
e48e37fc 1514 InsertTailList (&Instance->RcvdDgramQue, &Wrap->Link);\r
8a67d61d 1515\r
1516 Enqueued++;\r
1517 }\r
1518 }\r
1519\r
1520 return Enqueued;\r
1521}\r
1522\r
1523\r
1524/**\r
1525 This function delivers the received datagrams for the specified instance.\r
1526\r
1527 @param Instance Pointer to the instance context data.\r
1528\r
1529 @return None.\r
1530\r
1531**/\r
1532VOID\r
1533Udp4InstanceDeliverDgram (\r
1534 IN UDP4_INSTANCE_DATA *Instance\r
1535 )\r
1536{\r
1537 UDP4_RXDATA_WRAP *Wrap;\r
1538 EFI_UDP4_COMPLETION_TOKEN *Token;\r
1539 NET_BUF *Dup;\r
1540 EFI_UDP4_RECEIVE_DATA *RxData;\r
36ee91ca 1541 EFI_TPL OldTpl;\r
8a67d61d 1542\r
e48e37fc 1543 if (!IsListEmpty (&Instance->RcvdDgramQue) &&\r
bab52709 1544 !NetMapIsEmpty (&Instance->RxTokens)) {\r
8a67d61d 1545\r
1546 Wrap = NET_LIST_HEAD (&Instance->RcvdDgramQue, UDP4_RXDATA_WRAP, Link);\r
1547\r
1548 if (NET_BUF_SHARED (Wrap->Packet)) {\r
1549 //\r
1550 // Duplicate the Packet if it is shared between instances.\r
1551 //\r
1552 Dup = NetbufDuplicate (Wrap->Packet, NULL, 0);\r
1553 if (Dup == NULL) {\r
1554 return;\r
1555 }\r
1556\r
1557 NetbufFree (Wrap->Packet);\r
1558\r
1559 Wrap->Packet = Dup;\r
bab52709 1560 }\r
8a67d61d 1561\r
1562 NetListRemoveHead (&Instance->RcvdDgramQue);\r
1563\r
1564 Token = (EFI_UDP4_COMPLETION_TOKEN *) NetMapRemoveHead (&Instance->RxTokens, NULL);\r
1565\r
1566 //\r
1567 // Build the FragmentTable and set the FragmentCount in RxData.\r
1568 //\r
1569 RxData = &Wrap->RxData;\r
1570 RxData->FragmentCount = Wrap->Packet->BlockOpNum;\r
1571\r
1572 NetbufBuildExt (\r
1573 Wrap->Packet,\r
1574 (NET_FRAGMENT *) RxData->FragmentTable,\r
1575 &RxData->FragmentCount\r
1576 );\r
1577\r
1578 Token->Status = EFI_SUCCESS;\r
1579 Token->Packet.RxData = &Wrap->RxData;\r
1580\r
e48e37fc 1581 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1582 InsertTailList (&Instance->DeliveredDgramQue, &Wrap->Link);\r
1583 gBS->RestoreTPL (OldTpl);\r
36ee91ca 1584\r
1585 gBS->SignalEvent (Token->Event);\r
8a67d61d 1586 }\r
1587}\r
1588\r
1589\r
1590/**\r
1591 This function delivers the datagrams enqueued in the instances.\r
1592\r
1593 @param Udp4Service Pointer to the udp service context data.\r
1594\r
1595 @return None.\r
1596\r
1597**/\r
8a67d61d 1598VOID\r
1599Udp4DeliverDgram (\r
1600 IN UDP4_SERVICE_DATA *Udp4Service\r
1601 )\r
1602{\r
e48e37fc 1603 LIST_ENTRY *Entry;\r
8a67d61d 1604 UDP4_INSTANCE_DATA *Instance;\r
1605\r
1606 NET_LIST_FOR_EACH (Entry, &Udp4Service->ChildrenList) {\r
1607 //\r
1608 // Iterate the instances.\r
1609 //\r
1610 Instance = NET_LIST_USER_STRUCT (Entry, UDP4_INSTANCE_DATA, Link);\r
1611\r
1612 if (!Instance->Configured) {\r
1613 continue;\r
1614 }\r
1615\r
1616 //\r
1617 // Deliver the datagrams of this instance.\r
1618 //\r
1619 Udp4InstanceDeliverDgram (Instance);\r
1620 }\r
1621}\r
1622\r
1623\r
1624/**\r
1625 This function demultiplexes the received udp datagram to the apropriate instances.\r
1626\r
1627 @param Udp4Service Pointer to the udp service context data.\r
1628 @param NetSession Pointer to the EFI_NET_SESSION_DATA abstrated from\r
1629 the received datagram.\r
1630 @param Packet Pointer to the buffer containing the received udp\r
1631 datagram.\r
1632\r
1633 @return None.\r
1634\r
1635**/\r
8a67d61d 1636VOID\r
1637Udp4Demultiplex (\r
1638 IN UDP4_SERVICE_DATA *Udp4Service,\r
1639 IN EFI_NET_SESSION_DATA *NetSession,\r
1640 IN NET_BUF *Packet\r
1641 )\r
1642{\r
1643 EFI_UDP4_HEADER *Udp4Header;\r
1644 UINT16 HeadSum;\r
1645 EFI_UDP4_RECEIVE_DATA RxData;\r
1646 EFI_UDP4_SESSION_DATA *Udp4Session;\r
1647 UINTN Enqueued;\r
1648\r
1649 //\r
1650 // Get the datagram header from the packet buffer.\r
1651 //\r
1652 Udp4Header = (EFI_UDP4_HEADER *) NetbufGetByte (Packet, 0, NULL);\r
1653\r
1654 if (Udp4Header->Checksum != 0) {\r
1655 //\r
1656 // check the checksum.\r
1657 //\r
1658 HeadSum = NetPseudoHeadChecksum (\r
1659 NetSession->Source,\r
1660 NetSession->Dest,\r
1661 EFI_IP_PROTO_UDP,\r
1662 0\r
1663 );\r
1664\r
1665 if (Udp4Checksum (Packet, HeadSum) != 0) {\r
1666 //\r
1667 // Wrong checksum.\r
1668 //\r
1669 return;\r
1670 }\r
1671 }\r
1672\r
1673 gRT->GetTime (&RxData.TimeStamp, NULL);\r
1674\r
772db4bb 1675 Udp4Session = &RxData.UdpSession;\r
1676 Udp4Session->SourcePort = NTOHS (Udp4Header->SrcPort);\r
1677 Udp4Session->DestinationPort = NTOHS (Udp4Header->DstPort);\r
1678\r
e48e37fc 1679 CopyMem (&Udp4Session->SourceAddress, &NetSession->Source, sizeof (EFI_IPv4_ADDRESS));\r
1680 CopyMem (&Udp4Session->DestinationAddress, &NetSession->Dest, sizeof (EFI_IPv4_ADDRESS));\r
8a67d61d 1681\r
1682 //\r
1683 // Trim the UDP header.\r
1684 //\r
1685 NetbufTrim (Packet, UDP4_HEADER_SIZE, TRUE);\r
1686\r
1687 RxData.DataLength = (UINT32) Packet->TotalSize;\r
1688\r
1689 //\r
1690 // Try to enqueue this datagram into the instances.\r
1691 //\r
1692 Enqueued = Udp4EnqueueDgram (Udp4Service, Packet, &RxData);\r
1693\r
1694 if (Enqueued == 0) {\r
1695 //\r
1696 // Send the port unreachable ICMP packet before we free this NET_BUF\r
1697 //\r
1698 Udp4SendPortUnreach (Udp4Service->IpIo, NetSession, Udp4Header);\r
1699 }\r
1700\r
1701 //\r
1702 // Try to free the packet before deliver it.\r
1703 //\r
1704 NetbufFree (Packet);\r
1705\r
1706 if (Enqueued > 0) {\r
1707 //\r
1708 // Deliver the datagram.\r
1709 //\r
1710 Udp4DeliverDgram (Udp4Service);\r
1711 }\r
1712}\r
1713\r
1714\r
1715/**\r
1716 This function builds and sends out a icmp port unreachable message.\r
1717\r
1718 @param IpIo Pointer to the IP_IO instance.\r
1719 @param NetSession Pointer to the EFI_NET_SESSION_DATA of the packet\r
1720 causes this icmp error message.\r
1721 @param Udp4Header Pointer to the udp header of the datagram causes\r
1722 this icmp error message.\r
1723\r
1724 @return None.\r
1725\r
1726**/\r
8a67d61d 1727VOID\r
1728Udp4SendPortUnreach (\r
1729 IN IP_IO *IpIo,\r
1730 IN EFI_NET_SESSION_DATA *NetSession,\r
1731 IN VOID *Udp4Header\r
1732 )\r
1733{\r
1734 NET_BUF *Packet;\r
1735 UINT32 Len;\r
1736 IP4_ICMP_ERROR_HEAD *IcmpErrHdr;\r
1737 EFI_IP4_HEADER *IpHdr;\r
1738 UINT8 *Ptr;\r
1739 IP_IO_OVERRIDE Override;\r
1740 IP_IO_IP_INFO *IpSender;\r
1741\r
1742 IpSender = IpIoFindSender (&IpIo, NetSession->Dest);\r
1743 if (IpSender == NULL) {\r
1744 //\r
1745 // No apropriate sender, since we cannot send out the ICMP message through\r
1746 // the default zero station address IP instance, abort.\r
1747 //\r
1748 return;\r
1749 }\r
1750\r
1751 IpHdr = NetSession->IpHdr;\r
1752\r
1753 //\r
1754 // Calculate the requried length of the icmp error message.\r
1755 //\r
1756 Len = sizeof (IP4_ICMP_ERROR_HEAD) + (EFI_IP4_HEADER_LEN (IpHdr) -\r
1757 sizeof (IP4_HEAD)) + ICMP_ERROR_PACKET_LENGTH;\r
1758\r
1759 //\r
1760 // Allocate buffer for the icmp error message.\r
1761 //\r
1762 Packet = NetbufAlloc (Len);\r
1763 if (Packet == NULL) {\r
1764 return;\r
1765 }\r
1766\r
1767 //\r
1768 // Allocate space for the IP4_ICMP_ERROR_HEAD.\r
1769 //\r
1770 IcmpErrHdr = (IP4_ICMP_ERROR_HEAD *) NetbufAllocSpace (Packet, Len, FALSE);\r
1771\r
1772 //\r
1773 // Set the required fields for the icmp port unreachable message.\r
1774 //\r
1775 IcmpErrHdr->Head.Type = ICMP_TYPE_UNREACH;\r
1776 IcmpErrHdr->Head.Code = ICMP_CODE_UNREACH_PORT;\r
1777 IcmpErrHdr->Head.Checksum = 0;\r
1778 IcmpErrHdr->Fourth = 0;\r
1779\r
1780 //\r
1781 // Copy the IP header of the datagram tragged the error.\r
1782 //\r
e48e37fc 1783 CopyMem (&IcmpErrHdr->IpHead, IpHdr, EFI_IP4_HEADER_LEN (IpHdr));\r
8a67d61d 1784\r
1785 //\r
1786 // Copy the UDP header.\r
1787 //\r
1788 Ptr = (UINT8 *) &IcmpErrHdr->IpHead + EFI_IP4_HEADER_LEN (IpHdr);\r
e48e37fc 1789 CopyMem (Ptr, Udp4Header, ICMP_ERROR_PACKET_LENGTH);\r
8a67d61d 1790\r
1791 //\r
1792 // Calculate the checksum.\r
1793 //\r
687a2e5f 1794 IcmpErrHdr->Head.Checksum = (UINT16) ~(NetbufChecksum (Packet));\r
8a67d61d 1795\r
1796 //\r
1797 // Fill the override data.\r
1798 //\r
772db4bb 1799 Override.DoNotFragment = FALSE;\r
1800 Override.TypeOfService = 0;\r
1801 Override.TimeToLive = 255;\r
1802 Override.Protocol = EFI_IP_PROTO_ICMP;\r
1803\r
e48e37fc 1804 CopyMem (&Override.SourceAddress, &NetSession->Dest, sizeof (EFI_IPv4_ADDRESS));\r
1805 ZeroMem (&Override.GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
8a67d61d 1806\r
1807 //\r
1808 // Send out this icmp packet.\r
1809 //\r
1810 IpIoSend (IpIo, Packet, IpSender, NULL, NULL, NetSession->Source, &Override);\r
1811\r
1812 NetbufFree (Packet);\r
1813}\r
1814\r
1815\r
1816/**\r
1817 This function handles the received Icmp Error message and demultiplexes it to the\r
1818 instance.\r
1819\r
1820 @param Udp4Service Pointer to the udp service context data.\r
1821 @param IcmpError The icmp error code.\r
1822 @param NetSession Pointer to the EFI_NET_SESSION_DATA abstracted\r
1823 from the received Icmp Error packet.\r
1824 @param Packet Pointer to the Icmp Error packet.\r
1825\r
1826 @return None.\r
1827\r
1828**/\r
8a67d61d 1829VOID\r
1830Udp4IcmpHandler (\r
1831 IN UDP4_SERVICE_DATA *Udp4Service,\r
1832 IN ICMP_ERROR IcmpError,\r
1833 IN EFI_NET_SESSION_DATA *NetSession,\r
1834 IN NET_BUF *Packet\r
1835 )\r
1836{\r
1837 EFI_UDP4_HEADER *Udp4Header;\r
1838 EFI_UDP4_SESSION_DATA Udp4Session;\r
e48e37fc 1839 LIST_ENTRY *Entry;\r
8a67d61d 1840 UDP4_INSTANCE_DATA *Instance;\r
1841\r
1842 Udp4Header = (EFI_UDP4_HEADER *) NetbufGetByte (Packet, 0, NULL);\r
1843\r
e48e37fc 1844 CopyMem (&Udp4Session.SourceAddress, &NetSession->Source, sizeof (EFI_IPv4_ADDRESS));\r
1845 CopyMem (&Udp4Session.DestinationAddress, &NetSession->Dest, sizeof (EFI_IPv4_ADDRESS));\r
772db4bb 1846\r
1847 Udp4Session.SourcePort = NTOHS (Udp4Header->DstPort);\r
1848 Udp4Session.DestinationPort = NTOHS (Udp4Header->SrcPort);\r
8a67d61d 1849\r
1850 NET_LIST_FOR_EACH (Entry, &Udp4Service->ChildrenList) {\r
1851 //\r
1852 // Iterate all the instances.\r
1853 //\r
1854 Instance = NET_LIST_USER_STRUCT (Entry, UDP4_INSTANCE_DATA, Link);\r
1855\r
1856 if (!Instance->Configured ||\r
bab52709 1857 Instance->ConfigData.AcceptPromiscuous ||\r
1858 Instance->ConfigData.AcceptAnyPort ||\r
1859 EFI_IP4_EQUAL (&Instance->ConfigData.StationAddress, &mZeroIp4Addr)\r
1860 ) {\r
8a67d61d 1861 //\r
1862 // Don't try to deliver the ICMP error to this instance if it is not configured,\r
1863 // or it's configured to be promiscuous or accept any port or accept all the\r
1864 // datagrams.\r
1865 //\r
1866 continue;\r
1867 }\r
1868\r
1869 if (Udp4MatchDgram (Instance, &Udp4Session)) {\r
1870 //\r
1871 // Translate the Icmp Error code according to the udp spec.\r
1872 //\r
1873 Instance->IcmpError = IpIoGetIcmpErrStatus (IcmpError, NULL, NULL);\r
1874\r
1875 if (IcmpError > ICMP_ERR_UNREACH_PORT) {\r
1876 Instance->IcmpError = EFI_ICMP_ERROR;\r
1877 }\r
1878\r
1879 //\r
1880 // Notify the instance with the received Icmp Error.\r
1881 //\r
1882 Udp4ReportIcmpError (Instance);\r
1883\r
1884 break;\r
1885 }\r
1886 }\r
1887\r
1888 NetbufFree (Packet);\r
1889}\r
1890\r
1891\r
1892/**\r
1893 This function reports the received ICMP error.\r
1894\r
1895 @param Instance Pointer to the udp instance context data.\r
1896\r
1897 @return None.\r
1898\r
1899**/\r
1900VOID\r
1901Udp4ReportIcmpError (\r
1902 IN UDP4_INSTANCE_DATA *Instance\r
1903 )\r
1904{\r
1905 EFI_UDP4_COMPLETION_TOKEN *Token;\r
1906\r
1907 if (NetMapIsEmpty (&Instance->RxTokens)) {\r
1908 //\r
1909 // There are no receive tokens to deliver the ICMP error.\r
1910 //\r
1911 return;\r
1912 }\r
1913\r
1914 if (EFI_ERROR (Instance->IcmpError)) {\r
1915 //\r
1916 // Try to get a RxToken from the RxTokens map.\r
1917 //\r
1918 Token = (EFI_UDP4_COMPLETION_TOKEN *) NetMapRemoveHead (&Instance->RxTokens, NULL);\r
1919\r
1920 if (Token != NULL) {\r
1921 //\r
1922 // Report the error through the Token.\r
1923 //\r
1924 Token->Status = Instance->IcmpError;\r
1925 gBS->SignalEvent (Token->Event);\r
1926\r
1927 //\r
1928 // Clear the IcmpError.\r
1929 //\r
1930 Instance->IcmpError = EFI_SUCCESS;\r
1931 }\r
1932 }\r
1933}\r
1934\r
1935\r
1936/**\r
1937 This function is a dummy ext-free function for the NET_BUF created for the output\r
1938 udp datagram.\r
1939\r
1940 @param Context Pointer to the context data.\r
1941\r
1942 @return None.\r
1943\r
1944**/\r
1945VOID\r
1946Udp4NetVectorExtFree (\r
1947 VOID *Context\r
1948 )\r
1949{\r
1950}\r
1951\r
1952\r
1953/**\r
1954 Set the Udp4 variable data.\r
1955\r
1956 @param Udp4Service Udp4 service data.\r
1957\r
1958 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the\r
1959 variable.\r
bab52709 1960 @retval EFI_SUCCESS Set variable successfully.\r
8a67d61d 1961 @retval other Set variable failed.\r
1962\r
1963**/\r
1964EFI_STATUS\r
1965Udp4SetVariableData (\r
1966 IN UDP4_SERVICE_DATA *Udp4Service\r
1967 )\r
1968{\r
1969 UINT32 NumConfiguredInstance;\r
e48e37fc 1970 LIST_ENTRY *Entry;\r
8a67d61d 1971 UINTN VariableDataSize;\r
1972 EFI_UDP4_VARIABLE_DATA *Udp4VariableData;\r
1973 EFI_UDP4_SERVICE_POINT *Udp4ServicePoint;\r
1974 UDP4_INSTANCE_DATA *Udp4Instance;\r
1975 CHAR16 *NewMacString;\r
1976 EFI_STATUS Status;\r
1977\r
1978 NumConfiguredInstance = 0;\r
1979\r
1980 //\r
1981 // Go through the children list to count the configured children.\r
1982 //\r
1983 NET_LIST_FOR_EACH (Entry, &Udp4Service->ChildrenList) {\r
1984 Udp4Instance = NET_LIST_USER_STRUCT_S (\r
1985 Entry,\r
1986 UDP4_INSTANCE_DATA,\r
1987 Link,\r
1988 UDP4_INSTANCE_DATA_SIGNATURE\r
1989 );\r
1990\r
1991 if (Udp4Instance->Configured) {\r
1992 NumConfiguredInstance++;\r
1993 }\r
1994 }\r
1995\r
1996 //\r
1997 // Calculate the size of the Udp4VariableData. As there may be no Udp4 child,\r
1998 // we should add extra buffer for the service points only if the number of configured\r
1999 // children is more than 1.\r
2000 //\r
2001 VariableDataSize = sizeof (EFI_UDP4_VARIABLE_DATA);\r
2002\r
2003 if (NumConfiguredInstance > 1) {\r
2004 VariableDataSize += sizeof (EFI_UDP4_SERVICE_POINT) * (NumConfiguredInstance - 1);\r
2005 }\r
2006\r
e48e37fc 2007 Udp4VariableData = AllocatePool (VariableDataSize);\r
8a67d61d 2008 if (Udp4VariableData == NULL) {\r
2009 return EFI_OUT_OF_RESOURCES;\r
2010 }\r
2011\r
2012 Udp4VariableData->DriverHandle = Udp4Service->ImageHandle;\r
2013 Udp4VariableData->ServiceCount = NumConfiguredInstance;\r
2014\r
2015 Udp4ServicePoint = &Udp4VariableData->Services[0];\r
2016\r
2017 //\r
2018 // Go through the children list to fill the configured children's address pairs.\r
2019 //\r
2020 NET_LIST_FOR_EACH (Entry, &Udp4Service->ChildrenList) {\r
2021 Udp4Instance = NET_LIST_USER_STRUCT_S (\r
2022 Entry,\r
2023 UDP4_INSTANCE_DATA,\r
2024 Link,\r
2025 UDP4_INSTANCE_DATA_SIGNATURE\r
2026 );\r
2027\r
2028 if (Udp4Instance->Configured) {\r
2029 Udp4ServicePoint->InstanceHandle = Udp4Instance->ChildHandle;\r
2030 Udp4ServicePoint->LocalAddress = Udp4Instance->ConfigData.StationAddress;\r
2031 Udp4ServicePoint->LocalPort = Udp4Instance->ConfigData.StationPort;\r
2032 Udp4ServicePoint->RemoteAddress = Udp4Instance->ConfigData.RemoteAddress;\r
2033 Udp4ServicePoint->RemotePort = Udp4Instance->ConfigData.RemotePort;\r
2034\r
2035 Udp4ServicePoint++;\r
2036 }\r
2037 }\r
2038\r
2039 //\r
2040 // Get the mac string.\r
2041 //\r
2042 Status = NetLibGetMacString (\r
2043 Udp4Service->ControllerHandle,\r
2044 Udp4Service->ImageHandle,\r
2045 &NewMacString\r
2046 );\r
2047 if (EFI_ERROR (Status)) {\r
2048 goto ON_ERROR;\r
2049 }\r
2050\r
2051 if (Udp4Service->MacString != NULL) {\r
2052 //\r
2053 // The variable is set already, we're going to update it.\r
2054 //\r
2055 if (StrCmp (Udp4Service->MacString, NewMacString) != 0) {\r
2056 //\r
2057 // The mac address is changed, delete the previous variable first.\r
2058 //\r
2059 gRT->SetVariable (\r
2060 Udp4Service->MacString,\r
2061 &gEfiUdp4ServiceBindingProtocolGuid,\r
2062 EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
2063 0,\r
2064 NULL\r
2065 );\r
2066 }\r
2067\r
e48e37fc 2068 gBS->FreePool (Udp4Service->MacString);\r
8a67d61d 2069 }\r
2070\r
2071 Udp4Service->MacString = NewMacString;\r
2072\r
2073 Status = gRT->SetVariable (\r
2074 Udp4Service->MacString,\r
2075 &gEfiUdp4ServiceBindingProtocolGuid,\r
2076 EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
2077 VariableDataSize,\r
2078 (VOID *) Udp4VariableData\r
2079 );\r
2080\r
2081ON_ERROR:\r
2082\r
e48e37fc 2083 gBS->FreePool (Udp4VariableData);\r
8a67d61d 2084\r
2085 return Status;\r
2086}\r
2087\r
2088\r
2089/**\r
2090 Clear the variable and free the resource.\r
2091\r
2092 @param Udp4Service Udp4 service data.\r
2093\r
2094 @return None.\r
2095\r
2096**/\r
2097VOID\r
2098Udp4ClearVariableData (\r
2099 IN UDP4_SERVICE_DATA *Udp4Service\r
2100 )\r
2101{\r
2102 ASSERT (Udp4Service->MacString != NULL);\r
2103\r
2104 gRT->SetVariable (\r
2105 Udp4Service->MacString,\r
2106 &gEfiUdp4ServiceBindingProtocolGuid,\r
2107 EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
2108 0,\r
2109 NULL\r
2110 );\r
2111\r
e48e37fc 2112 gBS->FreePool (Udp4Service->MacString);\r
8a67d61d 2113 Udp4Service->MacString = NULL;\r
2114}\r