]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.c
Roll back to normal version
[mirror_edk2.git] / MdeModulePkg / Library / DxeIpIoLib / DxeIpIoLib.c
CommitLineData
cbf316f2 1/** @file\r
2\r
3Copyright (c) 2005 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 IpIo.c\r
15\r
16Abstract:\r
17\r
18 The implementation of the IpIo layer.\r
19\r
20\r
21**/\r
22\r
23#include <PiDxe.h>\r
24\r
25#include <Protocol/Udp4.h>\r
26\r
27#include <Library/IpIoLib.h>\r
28#include <Library/BaseLib.h>\r
29#include <Library/DebugLib.h>\r
30#include <Library/UefiBootServicesTableLib.h>\r
31#include <Library/MemoryAllocationLib.h>\r
b61439a7 32#include <Library/BaseMemoryLib.h>\r
cbf316f2 33\r
34\r
35#define NET_PROTO_HDR(Buf, Type) ((Type *) ((Buf)->BlockOp[0].Head))\r
36#define ICMP_ERRLEN(IpHdr) \\r
37 (sizeof(IP4_ICMP_HEAD) + EFI_IP4_HEADER_LEN(IpHdr) + 8)\r
38\r
e48e37fc 39LIST_ENTRY mActiveIpIoList = {\r
cbf316f2 40 &mActiveIpIoList,\r
41 &mActiveIpIoList\r
42};\r
43\r
44EFI_IP4_CONFIG_DATA mIpIoDefaultIpConfigData = {\r
45 EFI_IP_PROTO_UDP,\r
46 FALSE,\r
47 TRUE,\r
48 FALSE,\r
49 FALSE,\r
50 FALSE,\r
84b5c78e 51 {{0, 0, 0, 0}},\r
52 {{0, 0, 0, 0}},\r
cbf316f2 53 0,\r
54 255,\r
55 FALSE,\r
56 FALSE,\r
57 0,\r
58 0\r
59};\r
60\r
fe1e36e5 61ICMP_ERROR_INFO mIcmpErrMap[10] = {\r
01750eb0 62 {FALSE, TRUE},\r
63 {FALSE, TRUE},\r
64 {TRUE, TRUE},\r
65 {TRUE, TRUE},\r
66 {TRUE, TRUE},\r
67 {FALSE, TRUE},\r
68 {FALSE, TRUE},\r
69 {FALSE, TRUE},\r
70 {FALSE, FALSE},\r
71 {FALSE, TRUE}\r
72};\r
73\r
36ee91ca 74VOID\r
75EFIAPI\r
76IpIoTransmitHandlerDpc (\r
77 IN VOID *Context\r
78 );\r
79\r
cbf316f2 80VOID\r
81EFIAPI\r
82IpIoTransmitHandler (\r
83 IN EFI_EVENT Event,\r
84 IN VOID *Context\r
85 );\r
86\r
87\r
88/**\r
e6ff63a5 89 This function create an IP child, open the IP protocol and return the opened\r
90 IP protocol as Interface.\r
cbf316f2 91\r
92 @param ControllerHandle The controller handle.\r
93 @param ImageHandle The image handle.\r
e6ff63a5 94 @param ChildHandle Pointer to the buffer to save the IP child handle.\r
95 @param Interface Pointer used to get the IP protocol interface.\r
cbf316f2 96\r
e6ff63a5 97 @retval EFI_SUCCESS The IP child is created and the IP protocol\r
cbf316f2 98 interface is retrieved.\r
e6ff63a5 99 @retval Other The required operation failed.\r
cbf316f2 100\r
101**/\r
cbf316f2 102EFI_STATUS\r
103IpIoCreateIpChildOpenProtocol (\r
104 IN EFI_HANDLE ControllerHandle,\r
105 IN EFI_HANDLE ImageHandle,\r
106 IN EFI_HANDLE *ChildHandle,\r
107 OUT VOID **Interface\r
108 )\r
109{\r
110 EFI_STATUS Status;\r
111\r
112 //\r
113 // Create an ip child.\r
114 //\r
115 Status = NetLibCreateServiceChild (\r
116 ControllerHandle,\r
117 ImageHandle,\r
118 &gEfiIp4ServiceBindingProtocolGuid,\r
119 ChildHandle\r
120 );\r
121 if (EFI_ERROR (Status)) {\r
122 return Status;\r
123 }\r
124\r
125 //\r
126 // Open the ip protocol installed on the *ChildHandle.\r
127 //\r
128 Status = gBS->OpenProtocol (\r
129 *ChildHandle,\r
130 &gEfiIp4ProtocolGuid,\r
131 Interface,\r
132 ImageHandle,\r
133 ControllerHandle,\r
134 EFI_OPEN_PROTOCOL_BY_DRIVER\r
135 );\r
136 if (EFI_ERROR (Status)) {\r
137 //\r
138 // On failure, destroy the ip child.\r
139 //\r
140 NetLibDestroyServiceChild (\r
141 ControllerHandle,\r
142 ImageHandle,\r
143 &gEfiIp4ServiceBindingProtocolGuid,\r
144 *ChildHandle\r
145 );\r
146 }\r
147\r
148 return Status;\r
149}\r
150\r
151\r
152/**\r
e6ff63a5 153 This function close the previously openned IP protocol and destroy the IP child.\r
cbf316f2 154\r
155 @param ControllerHandle The controller handle.\r
156 @param ImageHandle the image handle.\r
e6ff63a5 157 @param ChildHandle The child handle of the IP child.\r
cbf316f2 158\r
e6ff63a5 159 @retval EFI_SUCCESS The IP protocol is closed and the relevant IP child\r
cbf316f2 160 is destroyed.\r
e6ff63a5 161 @retval Other The required operation failed.\r
cbf316f2 162\r
163**/\r
cbf316f2 164EFI_STATUS\r
165IpIoCloseProtocolDestroyIpChild (\r
166 IN EFI_HANDLE ControllerHandle,\r
167 IN EFI_HANDLE ImageHandle,\r
168 IN EFI_HANDLE ChildHandle\r
169 )\r
170{\r
171 EFI_STATUS Status;\r
172\r
173 //\r
174 // Close the previously openned ip protocol.\r
175 //\r
176 gBS->CloseProtocol (\r
177 ChildHandle,\r
178 &gEfiIp4ProtocolGuid,\r
179 ImageHandle,\r
180 ControllerHandle\r
181 );\r
182\r
183 //\r
184 // Destroy the ip child.\r
185 //\r
186 Status = NetLibDestroyServiceChild (\r
187 ControllerHandle,\r
188 ImageHandle,\r
189 &gEfiIp4ServiceBindingProtocolGuid,\r
190 ChildHandle\r
191 );\r
192\r
193 return Status;\r
194}\r
195\r
196\r
197/**\r
e6ff63a5 198 This function handles ICMP packets.\r
cbf316f2 199\r
200 @param IpIo Pointer to the IP_IO instance.\r
201 @param Pkt Pointer to the ICMP packet.\r
202 @param Session Pointer to the net session of this ICMP packet.\r
203\r
204 @retval EFI_SUCCESS The ICMP packet is handled successfully.\r
205 @retval EFI_ABORTED This type of ICMP packet is not supported.\r
206\r
207**/\r
cbf316f2 208EFI_STATUS\r
209IpIoIcmpHandler (\r
210 IN IP_IO *IpIo,\r
211 IN NET_BUF *Pkt,\r
212 IN EFI_NET_SESSION_DATA *Session\r
213 )\r
214{\r
215 IP4_ICMP_ERROR_HEAD *IcmpHdr;\r
216 EFI_IP4_HEADER *IpHdr;\r
217 ICMP_ERROR IcmpErr;\r
218 UINT8 *PayLoadHdr;\r
219 UINT8 Type;\r
220 UINT8 Code;\r
221 UINT32 TrimBytes;\r
222\r
223 IcmpHdr = NET_PROTO_HDR (Pkt, IP4_ICMP_ERROR_HEAD);\r
224 IpHdr = (EFI_IP4_HEADER *) (&IcmpHdr->IpHead);\r
225\r
226 //\r
227 // Check the ICMP packet length.\r
228 //\r
229 if (Pkt->TotalSize < ICMP_ERRLEN (IpHdr)) {\r
230\r
231 return EFI_ABORTED;\r
232 }\r
233\r
234 Type = IcmpHdr->Head.Type;\r
235 Code = IcmpHdr->Head.Code;\r
236\r
237 //\r
238 // Analyze the ICMP Error in this ICMP pkt\r
239 //\r
240 switch (Type) {\r
241 case ICMP_TYPE_UNREACH:\r
242 switch (Code) {\r
243 case ICMP_CODE_UNREACH_NET:\r
244 case ICMP_CODE_UNREACH_HOST:\r
245 case ICMP_CODE_UNREACH_PROTOCOL:\r
246 case ICMP_CODE_UNREACH_PORT:\r
247 case ICMP_CODE_UNREACH_SRCFAIL:\r
4eb65aff 248 IcmpErr = (ICMP_ERROR) (ICMP_ERR_UNREACH_NET + Code);\r
cbf316f2 249\r
250 break;\r
251\r
252 case ICMP_CODE_UNREACH_NEEDFRAG:\r
253 IcmpErr = ICMP_ERR_MSGSIZE;\r
254\r
255 break;\r
256\r
257 case ICMP_CODE_UNREACH_NET_UNKNOWN:\r
258 case ICMP_CODE_UNREACH_NET_PROHIB:\r
259 case ICMP_CODE_UNREACH_TOSNET:\r
260 IcmpErr = ICMP_ERR_UNREACH_NET;\r
261\r
262 break;\r
263\r
264 case ICMP_CODE_UNREACH_HOST_UNKNOWN:\r
265 case ICMP_CODE_UNREACH_ISOLATED:\r
266 case ICMP_CODE_UNREACH_HOST_PROHIB:\r
267 case ICMP_CODE_UNREACH_TOSHOST:\r
268 IcmpErr = ICMP_ERR_UNREACH_HOST;\r
269\r
270 break;\r
271\r
272 default:\r
273 return EFI_ABORTED;\r
274\r
275 break;\r
276 }\r
277\r
278 break;\r
279\r
280 case ICMP_TYPE_TIMXCEED:\r
281 if (Code > 1) {\r
282 return EFI_ABORTED;\r
283 }\r
284\r
4eb65aff 285 IcmpErr = (ICMP_ERROR) (Code + ICMP_ERR_TIMXCEED_INTRANS);\r
cbf316f2 286\r
287 break;\r
288\r
289 case ICMP_TYPE_PARAMPROB:\r
290 if (Code > 1) {\r
291 return EFI_ABORTED;\r
292 }\r
293\r
294 IcmpErr = ICMP_ERR_PARAMPROB;\r
295\r
296 break;\r
297\r
298 case ICMP_TYPE_SOURCEQUENCH:\r
299 if (Code != 0) {\r
300 return EFI_ABORTED;\r
301 }\r
302\r
303 IcmpErr = ICMP_ERR_QUENCH;\r
304\r
305 break;\r
306\r
307 default:\r
308 return EFI_ABORTED;\r
309\r
310 break;\r
311 }\r
312\r
313 //\r
314 // Notify user the ICMP pkt only containing payload except\r
315 // IP and ICMP header\r
316 //\r
317 PayLoadHdr = (UINT8 *) ((UINT8 *) IpHdr + EFI_IP4_HEADER_LEN (IpHdr));\r
318 TrimBytes = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);\r
319\r
320 NetbufTrim (Pkt, TrimBytes, TRUE);\r
321\r
322 IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);\r
323\r
324 return EFI_SUCCESS;\r
325}\r
326\r
327\r
328/**\r
e6ff63a5 329 Free function for receive token of IP_IO. It is used to\r
cbf316f2 330 signal the recycle event to notify IP to recycle the\r
331 data buffer.\r
332\r
333 @param Event The event to be signaled.\r
334\r
cbf316f2 335**/\r
cbf316f2 336VOID\r
337IpIoExtFree (\r
338 IN VOID *Event\r
339 )\r
340{\r
341 gBS->SignalEvent ((EFI_EVENT) Event);\r
342}\r
343\r
344\r
345/**\r
346 Create a send entry to wrap a packet before sending\r
347 out it through IP.\r
348\r
349 @param IpIo Pointer to the IP_IO instance.\r
350 @param Pkt Pointer to the packet.\r
351 @param Sender Pointer to the IP sender.\r
352 @param NotifyData Pointer to the notify data.\r
353 @param Dest Pointer to the destination IP address.\r
354 @param Override Pointer to the overriden IP_IO data.\r
355\r
356 @return Pointer to the data structure created to wrap the packet. If NULL,\r
e6ff63a5 357 resource limit occurred.\r
cbf316f2 358\r
359**/\r
cbf316f2 360IP_IO_SEND_ENTRY *\r
361IpIoCreateSndEntry (\r
362 IN IP_IO *IpIo,\r
363 IN NET_BUF *Pkt,\r
364 IN EFI_IP4_PROTOCOL *Sender,\r
365 IN VOID *Context OPTIONAL,\r
366 IN VOID *NotifyData OPTIONAL,\r
367 IN IP4_ADDR Dest,\r
368 IN IP_IO_OVERRIDE *Override\r
369 )\r
370{\r
371 IP_IO_SEND_ENTRY *SndEntry;\r
372 EFI_IP4_COMPLETION_TOKEN *SndToken;\r
373 EFI_IP4_TRANSMIT_DATA *TxData;\r
374 EFI_STATUS Status;\r
375 EFI_IP4_OVERRIDE_DATA *OverrideData;\r
34edf2ae 376 volatile UINT32 Index;\r
cbf316f2 377\r
378 //\r
379 // Allocate resource for SndEntry\r
380 //\r
e48e37fc 381 SndEntry = AllocatePool (sizeof (IP_IO_SEND_ENTRY));\r
cbf316f2 382 if (NULL == SndEntry) {\r
383 return NULL;\r
384 }\r
385\r
386 //\r
387 // Allocate resource for SndToken\r
388 //\r
e48e37fc 389 SndToken = AllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN));\r
cbf316f2 390 if (NULL == SndToken) {\r
391 goto ReleaseSndEntry;\r
392 }\r
393\r
394 Status = gBS->CreateEvent (\r
395 EVT_NOTIFY_SIGNAL,\r
e48e37fc 396 TPL_NOTIFY,\r
cbf316f2 397 IpIoTransmitHandler,\r
398 SndEntry,\r
399 &(SndToken->Event)\r
400 );\r
401 if (EFI_ERROR (Status)) {\r
402 goto ReleaseSndToken;\r
403 }\r
404\r
405 //\r
406 // Allocate resource for TxData\r
407 //\r
e48e37fc 408 TxData = AllocatePool (\r
cbf316f2 409 sizeof (EFI_IP4_TRANSMIT_DATA) +\r
410 sizeof (EFI_IP4_FRAGMENT_DATA) * (Pkt->BlockOpNum - 1)\r
411 );\r
412\r
413 if (NULL == TxData) {\r
414 goto ReleaseEvent;\r
415 }\r
416\r
417 //\r
418 // Allocate resource for OverrideData if needed\r
419 //\r
420 OverrideData = NULL;\r
421 if (NULL != Override) {\r
422\r
e48e37fc 423 OverrideData = AllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA));\r
cbf316f2 424 if (NULL == OverrideData) {\r
425 goto ReleaseResource;\r
426 }\r
427 //\r
428 // Set the fields of OverrideData\r
429 //\r
36ee91ca 430 CopyMem (OverrideData, Override, sizeof (*OverrideData));\r
cbf316f2 431 }\r
432\r
433 //\r
434 // Set the fields of TxData\r
435 //\r
e48e37fc 436 CopyMem (&TxData->DestinationAddress, &Dest, sizeof (EFI_IPv4_ADDRESS));\r
cbf316f2 437 TxData->OverrideData = OverrideData;\r
438 TxData->OptionsLength = 0;\r
439 TxData->OptionsBuffer = NULL;\r
440 TxData->TotalDataLength = Pkt->TotalSize;\r
441 TxData->FragmentCount = Pkt->BlockOpNum;\r
442\r
cbf316f2 443\r
34edf2ae 444 for (Index = 0; Index < Pkt->BlockOpNum; Index++) {\r
cbf316f2 445 TxData->FragmentTable[Index].FragmentBuffer = Pkt->BlockOp[Index].Head;\r
446 TxData->FragmentTable[Index].FragmentLength = Pkt->BlockOp[Index].Size;\r
447 }\r
448\r
449 //\r
450 // Set the fields of SndToken\r
451 //\r
452 SndToken->Packet.TxData = TxData;\r
453\r
454 //\r
455 // Set the fields of SndEntry\r
456 //\r
457 SndEntry->IpIo = IpIo;\r
458 SndEntry->Ip = Sender;\r
459 SndEntry->Context = Context;\r
460 SndEntry->NotifyData = NotifyData;\r
461\r
462 SndEntry->Pkt = Pkt;\r
463 NET_GET_REF (Pkt);\r
464\r
465 SndEntry->SndToken = SndToken;\r
466\r
e48e37fc 467 InsertTailList (&IpIo->PendingSndList, &SndEntry->Entry);\r
cbf316f2 468\r
469 return SndEntry;\r
470\r
471ReleaseResource:\r
e48e37fc 472 gBS->FreePool (TxData);\r
cbf316f2 473\r
474ReleaseEvent:\r
475 gBS->CloseEvent (SndToken->Event);\r
476\r
477ReleaseSndToken:\r
e48e37fc 478 gBS->FreePool (SndToken);\r
cbf316f2 479\r
480ReleaseSndEntry:\r
e48e37fc 481 gBS->FreePool (SndEntry);\r
cbf316f2 482\r
483 return NULL;\r
484}\r
485\r
486\r
487/**\r
488 Destroy the SndEntry.\r
e6ff63a5 489 \r
490 This function pairs with IpIoCreateSndEntry().\r
cbf316f2 491\r
492 @param SndEntry Pointer to the send entry to be destroyed.\r
493\r
cbf316f2 494**/\r
cbf316f2 495VOID\r
496IpIoDestroySndEntry (\r
497 IN IP_IO_SEND_ENTRY *SndEntry\r
498 )\r
499{\r
500 EFI_IP4_TRANSMIT_DATA *TxData;\r
501\r
502 TxData = SndEntry->SndToken->Packet.TxData;\r
503\r
504 if (NULL != TxData->OverrideData) {\r
e48e37fc 505 gBS->FreePool (TxData->OverrideData);\r
cbf316f2 506 }\r
507\r
e48e37fc 508 gBS->FreePool (TxData);\r
cbf316f2 509 NetbufFree (SndEntry->Pkt);\r
510 gBS->CloseEvent (SndEntry->SndToken->Event);\r
511\r
e48e37fc 512 gBS->FreePool (SndEntry->SndToken);\r
513 RemoveEntryList (&SndEntry->Entry);\r
cbf316f2 514\r
e48e37fc 515 gBS->FreePool (SndEntry);\r
cbf316f2 516}\r
517\r
518\r
519/**\r
520 Notify function for IP transmit token.\r
521\r
cbf316f2 522 @param Context The context passed in by the event notifier.\r
523\r
cbf316f2 524**/\r
cbf316f2 525VOID\r
526EFIAPI\r
36ee91ca 527IpIoTransmitHandlerDpc (\r
cbf316f2 528 IN VOID *Context\r
529 )\r
530{\r
531 IP_IO *IpIo;\r
532 IP_IO_SEND_ENTRY *SndEntry;\r
533\r
534 SndEntry = (IP_IO_SEND_ENTRY *) Context;\r
535\r
536 IpIo = SndEntry->IpIo;\r
537\r
538 if (IpIo->PktSentNotify && SndEntry->NotifyData) {\r
539 IpIo->PktSentNotify (\r
540 SndEntry->SndToken->Status,\r
541 SndEntry->Context,\r
542 SndEntry->Ip,\r
543 SndEntry->NotifyData\r
544 );\r
545 }\r
546\r
547 IpIoDestroySndEntry (SndEntry);\r
548}\r
549\r
36ee91ca 550/**\r
551 Notify function for IP transmit token.\r
552\r
553 @param Event The event signaled.\r
554 @param Context The context passed in by the event notifier.\r
555\r
36ee91ca 556**/\r
557\r
36ee91ca 558VOID\r
559EFIAPI\r
560IpIoTransmitHandler (\r
561 IN EFI_EVENT Event,\r
562 IN VOID *Context\r
563 )\r
564{\r
565 //\r
566 // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK\r
567 //\r
568 NetLibQueueDpc (TPL_CALLBACK, IpIoTransmitHandlerDpc, Context);\r
569}\r
570\r
cbf316f2 571\r
572/**\r
573 The dummy handler for the dummy IP receive token.\r
574\r
cbf316f2 575 @param Context The context passed in by the event notifier.\r
576\r
cbf316f2 577**/\r
cbf316f2 578VOID\r
579EFIAPI\r
36ee91ca 580IpIoDummyHandlerDpc (\r
cbf316f2 581 IN VOID *Context\r
582 )\r
583{\r
584 IP_IO_IP_INFO *IpInfo;\r
585 EFI_IP4_COMPLETION_TOKEN *DummyToken;\r
586\r
cbf316f2 587 IpInfo = (IP_IO_IP_INFO *) Context;\r
588 DummyToken = &(IpInfo->DummyRcvToken);\r
589\r
36ee91ca 590 if (EFI_ABORTED == DummyToken->Status) {\r
591 //\r
592 // The reception is actively aborted by the consumer, directly return.\r
593 //\r
594 return;\r
595 } else if (EFI_SUCCESS == DummyToken->Status) {\r
cbf316f2 596 ASSERT (DummyToken->Packet.RxData);\r
597\r
598 gBS->SignalEvent (DummyToken->Packet.RxData->RecycleSignal);\r
599 }\r
600\r
601 IpInfo->Ip->Receive (IpInfo->Ip, DummyToken);\r
602}\r
603\r
604\r
605/**\r
36ee91ca 606 Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK.\r
cbf316f2 607\r
608 @param Event The event signaled.\r
609 @param Context The context passed in by the event notifier.\r
610\r
cbf316f2 611**/\r
cbf316f2 612VOID\r
613EFIAPI\r
36ee91ca 614IpIoDummyHandler (\r
cbf316f2 615 IN EFI_EVENT Event,\r
616 IN VOID *Context\r
617 )\r
36ee91ca 618{\r
619 //\r
620 // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK\r
621 //\r
622 NetLibQueueDpc (TPL_CALLBACK, IpIoDummyHandlerDpc, Context);\r
623}\r
624\r
625\r
626/**\r
627 Notify function for the IP receive token, used to process\r
628 the received IP packets.\r
629\r
630 @param Context The context passed in by the event notifier.\r
631\r
36ee91ca 632**/\r
36ee91ca 633VOID\r
634EFIAPI\r
635IpIoListenHandlerDpc (\r
636 IN VOID *Context\r
637 )\r
cbf316f2 638{\r
639 IP_IO *IpIo;\r
640 EFI_STATUS Status;\r
641 EFI_IP4_RECEIVE_DATA *RxData;\r
642 EFI_IP4_PROTOCOL *Ip;\r
643 EFI_NET_SESSION_DATA Session;\r
644 NET_BUF *Pkt;\r
645\r
646 IpIo = (IP_IO *) Context;\r
647\r
648 Ip = IpIo->Ip;\r
649 Status = IpIo->RcvToken.Status;\r
650 RxData = IpIo->RcvToken.Packet.RxData;\r
651\r
36ee91ca 652 if (EFI_ABORTED == Status) {\r
653 //\r
654 // The reception is actively aborted by the consumer, directly return.\r
655 //\r
656 return;\r
657 }\r
658\r
cbf316f2 659 if (((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) || (NULL == RxData)) {\r
660 //\r
661 // Only process the normal packets and the icmp error packets, if RxData is NULL\r
662 // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although\r
663 // this should be a bug of the low layer (IP).\r
664 //\r
665 goto Resume;\r
666 }\r
667\r
668 if (NULL == IpIo->PktRcvdNotify) {\r
669 goto CleanUp;\r
670 }\r
671\r
672 if ((EFI_IP4 (RxData->Header->SourceAddress) != 0) &&\r
673 !Ip4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), 0)) {\r
674 //\r
675 // The source address is not zero and it's not a unicast IP address, discard it.\r
676 //\r
677 goto CleanUp;\r
678 }\r
679\r
680 //\r
681 // Create a netbuffer representing packet\r
682 //\r
683 Pkt = NetbufFromExt (\r
684 (NET_FRAGMENT *) RxData->FragmentTable,\r
685 RxData->FragmentCount,\r
686 0,\r
687 0,\r
688 IpIoExtFree,\r
689 RxData->RecycleSignal\r
690 );\r
691 if (NULL == Pkt) {\r
692 goto CleanUp;\r
693 }\r
694\r
695 //\r
696 // Create a net session\r
697 //\r
698 Session.Source = EFI_IP4 (RxData->Header->SourceAddress);\r
699 Session.Dest = EFI_IP4 (RxData->Header->DestinationAddress);\r
700 Session.IpHdr = RxData->Header;\r
701\r
702 if (EFI_SUCCESS == Status) {\r
703\r
4eb65aff 704 IpIo->PktRcvdNotify (EFI_SUCCESS, (ICMP_ERROR) 0, &Session, Pkt, IpIo->RcvdContext);\r
cbf316f2 705 } else {\r
706 //\r
707 // Status is EFI_ICMP_ERROR\r
708 //\r
709 Status = IpIoIcmpHandler (IpIo, Pkt, &Session);\r
710 if (EFI_ERROR (Status)) {\r
711 NetbufFree (Pkt);\r
712 }\r
713 }\r
714\r
715 goto Resume;\r
716\r
717CleanUp:\r
718 gBS->SignalEvent (RxData->RecycleSignal);\r
719\r
720Resume:\r
721 Ip->Receive (Ip, &(IpIo->RcvToken));\r
722}\r
723\r
724\r
36ee91ca 725/**\r
726 Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK\r
727\r
728 @param Event The event signaled.\r
729 @param Context The context passed in by the event notifier.\r
730\r
731 @return None.\r
732\r
733**/\r
36ee91ca 734VOID\r
735EFIAPI\r
736IpIoListenHandler (\r
737 IN EFI_EVENT Event,\r
738 IN VOID *Context\r
739 )\r
740{\r
741 //\r
742 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK\r
743 //\r
744 NetLibQueueDpc (TPL_CALLBACK, IpIoListenHandlerDpc, Context);\r
745}\r
746\r
747\r
cbf316f2 748/**\r
749 Create a new IP_IO instance.\r
e6ff63a5 750 \r
751 This function uses IP4 service binding protocol in Controller to create an IP4\r
752 child (aka IP4 instance).\r
cbf316f2 753\r
e6ff63a5 754 @param Image The image handle of the driver or application that\r
755 consumes IP_IO.\r
756 @param Controller The controller handle that has IP4 service binding\r
757 protocol installed.\r
cbf316f2 758\r
e6ff63a5 759 @return Pointer to a newly created IP_IO instance, or NULL if failed.\r
cbf316f2 760\r
761**/\r
762IP_IO *\r
7b414b4e 763EFIAPI\r
cbf316f2 764IpIoCreate (\r
765 IN EFI_HANDLE Image,\r
766 IN EFI_HANDLE Controller\r
767 )\r
768{\r
769 EFI_STATUS Status;\r
770 IP_IO *IpIo;\r
771\r
e48e37fc 772 IpIo = AllocateZeroPool (sizeof (IP_IO));\r
cbf316f2 773 if (NULL == IpIo) {\r
774 return NULL;\r
775 }\r
776\r
e48e37fc 777 InitializeListHead (&(IpIo->PendingSndList));\r
778 InitializeListHead (&(IpIo->IpList));\r
cbf316f2 779 IpIo->Controller = Controller;\r
780 IpIo->Image = Image;\r
781\r
782 Status = gBS->CreateEvent (\r
783 EVT_NOTIFY_SIGNAL,\r
e48e37fc 784 TPL_NOTIFY,\r
cbf316f2 785 IpIoListenHandler,\r
786 IpIo,\r
787 &(IpIo->RcvToken.Event)\r
788 );\r
789 if (EFI_ERROR (Status)) {\r
790 goto ReleaseIpIo;\r
791 }\r
792\r
793 //\r
794 // Create an IP child and open IP protocol\r
795 //\r
796 Status = IpIoCreateIpChildOpenProtocol (\r
797 Controller,\r
798 Image,\r
799 &IpIo->ChildHandle,\r
800 (VOID **)&(IpIo->Ip)\r
801 );\r
802 if (EFI_ERROR (Status)) {\r
803 goto ReleaseIpIo;\r
804 }\r
805\r
806 return IpIo;\r
807\r
808ReleaseIpIo:\r
809\r
810 if (NULL != IpIo->RcvToken.Event) {\r
811 gBS->CloseEvent (IpIo->RcvToken.Event);\r
812 }\r
813\r
e48e37fc 814 gBS->FreePool (IpIo);\r
cbf316f2 815\r
816 return NULL;\r
817}\r
818\r
819\r
820/**\r
821 Open an IP_IO instance for use.\r
e6ff63a5 822 \r
823 This function is called after IpIoCreate(). It is used for configuring the IP\r
824 instance and register the callbacks and their context data for sending and\r
825 receiving IP packets.\r
cbf316f2 826\r
827 @param IpIo Pointer to an IP_IO instance that needs to open.\r
e6ff63a5 828 @param OpenData The configuration data and callbacks for the IP_IO\r
829 instance.\r
cbf316f2 830\r
831 @retval EFI_SUCCESS The IP_IO instance opened with OpenData\r
832 successfully.\r
e6ff63a5 833 @retval Other Error condition occurred.\r
cbf316f2 834\r
835**/\r
836EFI_STATUS\r
7b414b4e 837EFIAPI\r
cbf316f2 838IpIoOpen (\r
839 IN IP_IO *IpIo,\r
840 IN IP_IO_OPEN_DATA *OpenData\r
841 )\r
842{\r
843 EFI_STATUS Status;\r
844 EFI_IP4_PROTOCOL *Ip;\r
cbf316f2 845\r
846 if (IpIo->IsConfigured) {\r
847 return EFI_ACCESS_DENIED;\r
848 }\r
849\r
850 Ip = IpIo->Ip;\r
851\r
852 //\r
853 // configure ip\r
854 //\r
855 Status = Ip->Configure (Ip, &OpenData->IpConfigData);\r
856 if (EFI_ERROR (Status)) {\r
857 return Status;\r
858 }\r
859\r
860 //\r
861 // bugbug: to delete the default route entry in this Ip, if it is:\r
862 // (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified\r
863 // its code\r
864 //\r
b61439a7 865 Status = Ip->Routes (Ip, TRUE, &mZeroIp4Addr, &mZeroIp4Addr, &mZeroIp4Addr);\r
cbf316f2 866\r
867 if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {\r
868 return Status;\r
869 }\r
870\r
871 IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;\r
872 IpIo->PktSentNotify = OpenData->PktSentNotify;\r
873\r
874 IpIo->RcvdContext = OpenData->RcvdContext;\r
875 IpIo->SndContext = OpenData->SndContext;\r
876\r
877 IpIo->Protocol = OpenData->IpConfigData.DefaultProtocol;\r
878\r
879 //\r
880 // start to listen incoming packet\r
881 //\r
882 Status = Ip->Receive (Ip, &(IpIo->RcvToken));\r
883 if (EFI_ERROR (Status)) {\r
884 Ip->Configure (Ip, NULL);\r
885 goto ErrorExit;\r
886 }\r
887\r
888 IpIo->IsConfigured = TRUE;\r
e48e37fc 889 InsertTailList (&mActiveIpIoList, &IpIo->Entry);\r
cbf316f2 890\r
891ErrorExit:\r
892\r
893 return Status;\r
894}\r
895\r
896\r
897/**\r
898 Stop an IP_IO instance.\r
e6ff63a5 899 \r
900 This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all\r
901 the pending send/receive tokens will be canceled.\r
cbf316f2 902\r
903 @param IpIo Pointer to the IP_IO instance that needs to stop.\r
904\r
905 @retval EFI_SUCCESS The IP_IO instance stopped successfully.\r
e6ff63a5 906 @retval Other Error condition occurred.\r
cbf316f2 907\r
908**/\r
909EFI_STATUS\r
e6ff63a5 910EFIAPI\r
cbf316f2 911IpIoStop (\r
912 IN IP_IO *IpIo\r
913 )\r
914{\r
915 EFI_STATUS Status;\r
916 EFI_IP4_PROTOCOL *Ip;\r
917 IP_IO_IP_INFO *IpInfo;\r
918\r
919 if (!IpIo->IsConfigured) {\r
920 return EFI_SUCCESS;\r
921 }\r
922\r
923 //\r
924 // Remove the IpIo from the active IpIo list.\r
925 //\r
e48e37fc 926 RemoveEntryList (&IpIo->Entry);\r
cbf316f2 927\r
928 Ip = IpIo->Ip;\r
929\r
930 //\r
931 // Configure NULL Ip\r
932 //\r
933 Status = Ip->Configure (Ip, NULL);\r
934 if (EFI_ERROR (Status)) {\r
935 return Status;\r
936 }\r
937\r
938 IpIo->IsConfigured = FALSE;\r
939\r
940 //\r
941 // Detroy the Ip List used by IpIo\r
942 //\r
34edf2ae 943\r
e48e37fc 944 while (!IsListEmpty (&(IpIo->IpList))) {\r
cbf316f2 945 IpInfo = NET_LIST_HEAD (&(IpIo->IpList), IP_IO_IP_INFO, Entry);\r
946\r
947 IpIoRemoveIp (IpIo, IpInfo);\r
948 }\r
949\r
950 //\r
951 // All pending snd tokens should be flushed by reseting the IP instances.\r
952 //\r
e48e37fc 953 ASSERT (IsListEmpty (&IpIo->PendingSndList));\r
cbf316f2 954\r
955 //\r
956 // Close the receive event.\r
957 //\r
958 gBS->CloseEvent (IpIo->RcvToken.Event);\r
959\r
960 return EFI_SUCCESS;\r
961}\r
962\r
963\r
964/**\r
965 Destroy an IP_IO instance.\r
e6ff63a5 966 \r
967 This function is paired with IpIoCreate(). The IP_IO will be closed first.\r
968 Resource will be freed afterwards. See IpIoClose().\r
cbf316f2 969\r
e6ff63a5 970 @param IpIo Pointer to the IP_IO instance that needs to be\r
971 destroyed.\r
cbf316f2 972\r
973 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.\r
e6ff63a5 974 @retval Other Error condition occurred.\r
cbf316f2 975\r
976**/\r
977EFI_STATUS\r
7b414b4e 978EFIAPI\r
cbf316f2 979IpIoDestroy (\r
980 IN IP_IO *IpIo\r
981 )\r
982{\r
983 //\r
984 // Stop the IpIo.\r
985 //\r
986 IpIoStop (IpIo);\r
987\r
988 //\r
989 // Close the IP protocol and destroy the child.\r
990 //\r
991 IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpIo->ChildHandle);\r
992\r
e48e37fc 993 gBS->FreePool (IpIo);\r
cbf316f2 994\r
995 return EFI_SUCCESS;\r
996}\r
997\r
998\r
999/**\r
1000 Send out an IP packet.\r
e6ff63a5 1001 \r
1002 This function is called after IpIoOpen(). The data to be sent are wrapped in\r
1003 Pkt. The IP instance wrapped in IpIo is used for sending by default but can be\r
1004 overriden by Sender. Other sending configs, like source address and gateway\r
1005 address etc., are specified in OverrideData.\r
cbf316f2 1006\r
1007 @param IpIo Pointer to an IP_IO instance used for sending IP\r
1008 packet.\r
1009 @param Pkt Pointer to the IP packet to be sent.\r
1010 @param Sender The IP protocol instance used for sending.\r
e6ff63a5 1011 @param Context Optional context data\r
1012 @param NotifyData Optional notify data\r
cbf316f2 1013 @param Dest The destination IP address to send this packet to.\r
1014 @param OverrideData The data to override some configuration of the IP\r
1015 instance used for sending.\r
1016\r
1017 @retval EFI_SUCCESS The operation is completed successfully.\r
1018 @retval EFI_NOT_STARTED The IpIo is not configured.\r
1019 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
1020\r
1021**/\r
1022EFI_STATUS\r
7b414b4e 1023EFIAPI\r
cbf316f2 1024IpIoSend (\r
1025 IN IP_IO *IpIo,\r
1026 IN NET_BUF *Pkt,\r
e6ff63a5 1027 IN IP_IO_IP_INFO *Sender OPTIONAL,\r
1028 IN VOID *Context OPTIONAL,\r
1029 IN VOID *NotifyData OPTIONAL,\r
cbf316f2 1030 IN IP4_ADDR Dest,\r
e6ff63a5 1031 IN IP_IO_OVERRIDE *OverrideData OPTIONAL\r
cbf316f2 1032 )\r
1033{\r
1034 EFI_STATUS Status;\r
1035 EFI_IP4_PROTOCOL *Ip;\r
1036 IP_IO_SEND_ENTRY *SndEntry;\r
1037\r
1038 if (!IpIo->IsConfigured) {\r
1039 return EFI_NOT_STARTED;\r
1040 }\r
1041\r
1042 Ip = (NULL == Sender) ? IpIo->Ip : Sender->Ip;\r
1043\r
1044 //\r
1045 // create a new SndEntry\r
1046 //\r
1047 SndEntry = IpIoCreateSndEntry (IpIo, Pkt, Ip, Context, NotifyData, Dest, OverrideData);\r
1048 if (NULL == SndEntry) {\r
1049 return EFI_OUT_OF_RESOURCES;\r
1050 }\r
1051\r
1052 //\r
1053 // Send this Packet\r
1054 //\r
1055 Status = Ip->Transmit (Ip, SndEntry->SndToken);\r
1056 if (EFI_ERROR (Status)) {\r
1057 IpIoDestroySndEntry (SndEntry);\r
1058 }\r
1059\r
1060 return Status;\r
1061}\r
1062\r
1063\r
1064/**\r
1065 Cancel the IP transmit token which wraps this Packet.\r
1066\r
1067 @param IpIo Pointer to the IP_IO instance.\r
e6ff63a5 1068 @param Packet Pointer to the packet of NET_BUF to cancel.\r
cbf316f2 1069\r
1070**/\r
1071VOID\r
7b414b4e 1072EFIAPI\r
cbf316f2 1073IpIoCancelTxToken (\r
1074 IN IP_IO *IpIo,\r
1075 IN VOID *Packet\r
1076 )\r
1077{\r
e48e37fc 1078 LIST_ENTRY *Node;\r
cbf316f2 1079 IP_IO_SEND_ENTRY *SndEntry;\r
1080 EFI_IP4_PROTOCOL *Ip;\r
1081\r
1082 ASSERT (IpIo && Packet);\r
1083\r
1084 NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {\r
1085\r
1086 SndEntry = NET_LIST_USER_STRUCT (Node, IP_IO_SEND_ENTRY, Entry);\r
1087\r
1088 if (SndEntry->Pkt == Packet) {\r
1089\r
1090 Ip = SndEntry->Ip;\r
1091 Ip->Cancel (Ip, SndEntry->SndToken);\r
1092\r
cbf316f2 1093 break;\r
1094 }\r
1095 }\r
1096\r
1097}\r
1098\r
1099\r
1100/**\r
1101 Add a new IP instance for sending data.\r
e6ff63a5 1102 \r
1103 The function is used to add the IP_IO to the IP_IO sending list. The caller\r
1104 can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send\r
1105 data.\r
cbf316f2 1106\r
1107 @param IpIo Pointer to a IP_IO instance to add a new IP\r
1108 instance for sending purpose.\r
1109\r
e6ff63a5 1110 @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.\r
cbf316f2 1111\r
1112**/\r
1113IP_IO_IP_INFO *\r
7b414b4e 1114EFIAPI\r
cbf316f2 1115IpIoAddIp (\r
1116 IN IP_IO *IpIo\r
1117 )\r
1118{\r
1119 EFI_STATUS Status;\r
1120 IP_IO_IP_INFO *IpInfo;\r
1121\r
1122 ASSERT (IpIo);\r
1123\r
e48e37fc 1124 IpInfo = AllocatePool (sizeof (IP_IO_IP_INFO));\r
cbf316f2 1125 if (IpInfo == NULL) {\r
1126 return IpInfo;\r
1127 }\r
1128\r
1129 //\r
1130 // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP\r
1131 // instance.\r
1132 //\r
e48e37fc 1133 InitializeListHead (&IpInfo->Entry);\r
cbf316f2 1134 IpInfo->ChildHandle = NULL;\r
1135 IpInfo->Addr = 0;\r
1136 IpInfo->SubnetMask = 0;\r
1137 IpInfo->RefCnt = 1;\r
1138\r
1139 //\r
1140 // Create the IP instance and open the Ip4 protocol.\r
1141 //\r
1142 Status = IpIoCreateIpChildOpenProtocol (\r
1143 IpIo->Controller,\r
1144 IpIo->Image,\r
1145 &IpInfo->ChildHandle,\r
4eb65aff 1146 (VOID **) &IpInfo->Ip\r
cbf316f2 1147 );\r
1148 if (EFI_ERROR (Status)) {\r
1149 goto ReleaseIpInfo;\r
1150 }\r
1151\r
1152 //\r
1153 // Create the event for the DummyRcvToken.\r
1154 //\r
1155 Status = gBS->CreateEvent (\r
1156 EVT_NOTIFY_SIGNAL,\r
e48e37fc 1157 TPL_NOTIFY,\r
cbf316f2 1158 IpIoDummyHandler,\r
1159 IpInfo,\r
1160 &IpInfo->DummyRcvToken.Event\r
1161 );\r
1162 if (EFI_ERROR (Status)) {\r
1163 goto ReleaseIpChild;\r
1164 }\r
1165\r
1166 //\r
1167 // Link this IpInfo into the IpIo.\r
1168 //\r
e48e37fc 1169 InsertTailList (&IpIo->IpList, &IpInfo->Entry);\r
cbf316f2 1170\r
1171 return IpInfo;\r
1172\r
1173ReleaseIpChild:\r
1174\r
1175 IpIoCloseProtocolDestroyIpChild (\r
1176 IpIo->Controller,\r
1177 IpIo->Image,\r
1178 IpInfo->ChildHandle\r
1179 );\r
1180\r
1181ReleaseIpInfo:\r
1182\r
e48e37fc 1183 gBS->FreePool (IpInfo);\r
cbf316f2 1184\r
1185 return NULL;\r
1186}\r
1187\r
1188\r
1189/**\r
1190 Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData\r
1191 is not NULL.\r
1192\r
1193 @param IpInfo Pointer to the IP_IO_IP_INFO instance.\r
e6ff63a5 1194 @param Ip4ConfigData The IP4 configure data used to configure the IP\r
1195 instance, if NULL the IP instance is reset. If\r
cbf316f2 1196 UseDefaultAddress is set to TRUE, and the configure\r
1197 operation succeeds, the default address information\r
1198 is written back in this Ip4ConfigData.\r
1199\r
1200 @retval EFI_STATUS The status returned by IP4->Configure or\r
1201 IP4->Receive.\r
e6ff63a5 1202 @retval Other Configuration fails.\r
cbf316f2 1203\r
1204**/\r
1205EFI_STATUS\r
7b414b4e 1206EFIAPI\r
cbf316f2 1207IpIoConfigIp (\r
1208 IN IP_IO_IP_INFO *IpInfo,\r
1209 IN OUT EFI_IP4_CONFIG_DATA *Ip4ConfigData OPTIONAL\r
1210 )\r
1211{\r
1212 EFI_STATUS Status;\r
1213 EFI_IP4_PROTOCOL *Ip;\r
1214 EFI_IP4_MODE_DATA Ip4ModeData;\r
1215\r
1216 ASSERT (IpInfo);\r
1217\r
1218 if (IpInfo->RefCnt > 1) {\r
1219 //\r
1220 // This IP instance is shared, don't reconfigure it until it has only one\r
1221 // consumer. Currently, only the tcp children cloned from their passive parent\r
1222 // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,\r
1223 // let the last consumer clean the IP instance.\r
1224 //\r
1225 return EFI_SUCCESS;\r
1226 }\r
1227\r
1228 Ip = IpInfo->Ip;\r
1229\r
1230 Status = Ip->Configure (Ip, Ip4ConfigData);\r
1231 if (EFI_ERROR (Status)) {\r
1232 goto OnExit;\r
1233 }\r
1234\r
1235 if (Ip4ConfigData != NULL) {\r
1236\r
1237 if (Ip4ConfigData->UseDefaultAddress) {\r
1238 Ip->GetModeData (Ip, &Ip4ModeData, NULL, NULL);\r
1239\r
1240 Ip4ConfigData->StationAddress = Ip4ModeData.ConfigData.StationAddress;\r
1241 Ip4ConfigData->SubnetMask = Ip4ModeData.ConfigData.SubnetMask;\r
1242 }\r
1243\r
e48e37fc 1244 CopyMem (&IpInfo->Addr, &Ip4ConfigData->StationAddress, sizeof (IP4_ADDR));\r
1245 CopyMem (&IpInfo->SubnetMask, &Ip4ConfigData->SubnetMask, sizeof (IP4_ADDR));\r
cbf316f2 1246\r
1247 Status = Ip->Receive (Ip, &IpInfo->DummyRcvToken);\r
1248 if (EFI_ERROR (Status)) {\r
1249 Ip->Configure (Ip, NULL);\r
1250 }\r
1251 } else {\r
1252\r
1253 //\r
1254 // The IP instance is reseted, set the stored Addr and SubnetMask to zero.\r
1255 //\r
1256 IpInfo->Addr = 0;\r
1257 IpInfo->SubnetMask =0;\r
1258 }\r
1259\r
1260OnExit:\r
1261\r
1262 return Status;\r
1263}\r
1264\r
1265\r
1266/**\r
1267 Destroy an IP instance maintained in IpIo->IpList for\r
1268 sending purpose.\r
e6ff63a5 1269 \r
1270 This function pairs with IpIoAddIp(). The IpInfo is previously created by\r
1271 IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance\r
1272 will be dstroyed if the RefCnt is zero.\r
cbf316f2 1273\r
1274 @param IpIo Pointer to the IP_IO instance.\r
1275 @param IpInfo Pointer to the IpInfo to be removed.\r
1276\r
cbf316f2 1277**/\r
1278VOID\r
7b414b4e 1279EFIAPI\r
cbf316f2 1280IpIoRemoveIp (\r
e6ff63a5 1281 IN IP_IO *IpIo,\r
1282 IN IP_IO_IP_INFO *IpInfo\r
cbf316f2 1283 )\r
1284{\r
1285 ASSERT (IpInfo->RefCnt > 0);\r
1286\r
1287 NET_PUT_REF (IpInfo);\r
1288\r
1289 if (IpInfo->RefCnt > 0) {\r
1290\r
1291 return;\r
1292 }\r
1293\r
e48e37fc 1294 RemoveEntryList (&IpInfo->Entry);\r
cbf316f2 1295\r
1296 IpInfo->Ip->Configure (IpInfo->Ip, NULL);\r
1297\r
1298 IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpInfo->ChildHandle);\r
1299\r
1300 gBS->CloseEvent (IpInfo->DummyRcvToken.Event);\r
1301\r
e48e37fc 1302 gBS->FreePool (IpInfo);\r
cbf316f2 1303}\r
1304\r
1305\r
1306/**\r
1307 Find the first IP protocol maintained in IpIo whose local\r
1308 address is the same with Src.\r
e6ff63a5 1309 \r
1310 This function is called when the caller needs the IpIo to send data to the\r
1311 specified Src. The IpIo was added previously by IpIoAddIp().\r
cbf316f2 1312\r
1313 @param IpIo Pointer to the pointer of the IP_IO instance.\r
1314 @param Src The local IP address.\r
1315\r
1316 @return Pointer to the IP protocol can be used for sending purpose and its local\r
e6ff63a5 1317 address is the same with Src.\r
cbf316f2 1318\r
1319**/\r
1320IP_IO_IP_INFO *\r
7b414b4e 1321EFIAPI\r
cbf316f2 1322IpIoFindSender (\r
1323 IN OUT IP_IO **IpIo,\r
1324 IN IP4_ADDR Src\r
1325 )\r
1326{\r
e48e37fc 1327 LIST_ENTRY *IpIoEntry;\r
cbf316f2 1328 IP_IO *IpIoPtr;\r
e48e37fc 1329 LIST_ENTRY *IpInfoEntry;\r
cbf316f2 1330 IP_IO_IP_INFO *IpInfo;\r
1331\r
1332 NET_LIST_FOR_EACH (IpIoEntry, &mActiveIpIoList) {\r
1333 IpIoPtr = NET_LIST_USER_STRUCT (IpIoEntry, IP_IO, Entry);\r
1334\r
1335 if ((*IpIo != NULL) && (*IpIo != IpIoPtr)) {\r
1336 continue;\r
1337 }\r
1338\r
1339 NET_LIST_FOR_EACH (IpInfoEntry, &IpIoPtr->IpList) {\r
1340 IpInfo = NET_LIST_USER_STRUCT (IpInfoEntry, IP_IO_IP_INFO, Entry);\r
1341\r
1342 if (IpInfo->Addr == Src) {\r
1343 *IpIo = IpIoPtr;\r
1344 return IpInfo;\r
1345 }\r
1346 }\r
1347 }\r
1348\r
1349 //\r
1350 // No match.\r
1351 //\r
1352 return NULL;\r
1353}\r
1354\r
1355\r
1356/**\r
e6ff63a5 1357 Get the ICMP error map information.\r
1358 \r
1359 The ErrorStatus will be returned. The IsHard and Notify are optional. If they\r
1360 are not NULL, this routine will fill them.\r
cbf316f2 1361\r
1362 @param IcmpError IcmpError Type\r
1363 @param IsHard Whether it is a hard error\r
1364 @param Notify Whether it need to notify SockError\r
1365\r
1366 @return ICMP Error Status\r
1367\r
1368**/\r
1369EFI_STATUS\r
7b414b4e 1370EFIAPI\r
cbf316f2 1371IpIoGetIcmpErrStatus (\r
1372 IN ICMP_ERROR IcmpError,\r
e6ff63a5 1373 OUT BOOLEAN *IsHard OPTIONAL,\r
1374 OUT BOOLEAN *Notify OPTIONAL\r
cbf316f2 1375 )\r
1376{\r
01750eb0 1377 ASSERT ((IcmpError >= ICMP_ERR_UNREACH_NET) && (IcmpError <= ICMP_ERR_PARAMPROB));\r
687a2e5f 1378\r
01750eb0 1379 if (IsHard != NULL) {\r
1380 *IsHard = mIcmpErrMap[IcmpError].IsHard;\r
1381 }\r
687a2e5f 1382\r
01750eb0 1383 if (Notify != NULL) {\r
1384 *Notify = mIcmpErrMap[IcmpError].Notify;\r
1385 }\r
687a2e5f 1386\r
01750eb0 1387 switch (IcmpError) {\r
1388 case ICMP_ERR_UNREACH_NET:\r
1389 return EFI_NETWORK_UNREACHABLE;\r
687a2e5f 1390\r
01750eb0 1391 case ICMP_ERR_TIMXCEED_INTRANS:\r
1392 case ICMP_ERR_TIMXCEED_REASS:\r
1393 case ICMP_ERR_UNREACH_HOST:\r
1394 return EFI_HOST_UNREACHABLE;\r
cbf316f2 1395\r
01750eb0 1396 case ICMP_ERR_UNREACH_PROTOCOL:\r
1397 return EFI_PROTOCOL_UNREACHABLE;\r
cbf316f2 1398\r
01750eb0 1399 case ICMP_ERR_UNREACH_PORT:\r
1400 return EFI_PORT_UNREACHABLE;\r
cbf316f2 1401\r
01750eb0 1402 case ICMP_ERR_MSGSIZE:\r
1403 case ICMP_ERR_UNREACH_SRCFAIL:\r
1404 case ICMP_ERR_QUENCH:\r
1405 case ICMP_ERR_PARAMPROB:\r
1406 return EFI_ICMP_ERROR;\r
cbf316f2 1407 }\r
1408\r
01750eb0 1409 //\r
1410 // will never run here!\r
1411 //\r
1412 ASSERT (FALSE);\r
1413 return EFI_UNSUPPORTED;\r
cbf316f2 1414}\r
1415\r