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