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