]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Library / DxeIpIoLib / DxeIpIoLib.c
CommitLineData
cbf316f2 1/** @file\r
6aac5e5f 2 IpIo Library.\r
cbf316f2 3\r
35f910f0 4(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
2b208747 5Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 6This program and the accompanying materials\r
cbf316f2 7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
cbf316f2 13**/\r
14\r
6aac5e5f 15#include <Uefi.h>\r
cbf316f2 16\r
17#include <Protocol/Udp4.h>\r
18\r
19#include <Library/IpIoLib.h>\r
20#include <Library/BaseLib.h>\r
21#include <Library/DebugLib.h>\r
752ef5d8 22#include <Library/BaseMemoryLib.h>\r
cbf316f2 23#include <Library/UefiBootServicesTableLib.h>\r
752ef5d8 24#include <Library/MemoryAllocationLib.h>\r
d8d26fb2 25#include <Library/DpcLib.h>\r
cbf316f2 26\r
cbf316f2 27\r
1204fe83 28GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mActiveIpIoList = {\r
cbf316f2 29 &mActiveIpIoList,\r
30 &mActiveIpIoList\r
31};\r
32\r
1204fe83 33GLOBAL_REMOVE_IF_UNREFERENCED EFI_IP4_CONFIG_DATA mIp4IoDefaultIpConfigData = {\r
cbf316f2 34 EFI_IP_PROTO_UDP,\r
35 FALSE,\r
36 TRUE,\r
37 FALSE,\r
38 FALSE,\r
39 FALSE,\r
84b5c78e 40 {{0, 0, 0, 0}},\r
41 {{0, 0, 0, 0}},\r
cbf316f2 42 0,\r
43 255,\r
44 FALSE,\r
45 FALSE,\r
46 0,\r
47 0\r
48};\r
49\r
1204fe83 50GLOBAL_REMOVE_IF_UNREFERENCED EFI_IP6_CONFIG_DATA mIp6IoDefaultIpConfigData = {\r
fb115c61 51 EFI_IP_PROTO_UDP,\r
52 FALSE,\r
53 TRUE,\r
54 FALSE,\r
55 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},\r
56 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},\r
57 0,\r
58 255,\r
59 0,\r
60 0,\r
61 0\r
62};\r
63\r
1204fe83 64GLOBAL_REMOVE_IF_UNREFERENCED ICMP_ERROR_INFO mIcmpErrMap[10] = {\r
3cf888f5 65 {FALSE, TRUE }, // ICMP_ERR_UNREACH_NET\r
66 {FALSE, TRUE }, // ICMP_ERR_UNREACH_HOST\r
67 {TRUE, TRUE }, // ICMP_ERR_UNREACH_PROTOCOL\r
68 {TRUE, TRUE }, // ICMP_ERR_UNREACH_PORT\r
69 {TRUE, TRUE }, // ICMP_ERR_MSGSIZE\r
70 {FALSE, TRUE }, // ICMP_ERR_UNREACH_SRCFAIL\r
71 {FALSE, TRUE }, // ICMP_ERR_TIMXCEED_INTRANS\r
72 {FALSE, TRUE }, // ICMP_ERR_TIMEXCEED_REASS\r
73 {FALSE, FALSE}, // ICMP_ERR_QUENCH\r
74 {FALSE, TRUE } // ICMP_ERR_PARAMPROB\r
fb115c61 75};\r
76\r
1204fe83 77GLOBAL_REMOVE_IF_UNREFERENCED ICMP_ERROR_INFO mIcmp6ErrMap[10] = {\r
3cf888f5 78 {FALSE, TRUE}, // ICMP6_ERR_UNREACH_NET\r
79 {FALSE, TRUE}, // ICMP6_ERR_UNREACH_HOST\r
80 {TRUE, TRUE}, // ICMP6_ERR_UNREACH_PROTOCOL\r
d1102dba 81 {TRUE, TRUE}, // ICMP6_ERR_UNREACH_PORT\r
3cf888f5 82 {TRUE, TRUE}, // ICMP6_ERR_PACKAGE_TOOBIG\r
83 {FALSE, TRUE}, // ICMP6_ERR_TIMXCEED_HOPLIMIT\r
84 {FALSE, TRUE}, // ICMP6_ERR_TIMXCEED_REASS\r
d1102dba 85 {FALSE, TRUE}, // ICMP6_ERR_PARAMPROB_HEADER\r
3cf888f5 86 {FALSE, TRUE}, // ICMP6_ERR_PARAMPROB_NEXHEADER\r
87 {FALSE, TRUE} // ICMP6_ERR_PARAMPROB_IPV6OPTION\r
01750eb0 88};\r
89\r
6aac5e5f 90\r
91/**\r
92 Notify function for IP transmit token.\r
93\r
94 @param[in] Context The context passed in by the event notifier.\r
95\r
96**/\r
36ee91ca 97VOID\r
98EFIAPI\r
99IpIoTransmitHandlerDpc (\r
100 IN VOID *Context\r
101 );\r
102\r
6aac5e5f 103\r
104/**\r
105 Notify function for IP transmit token.\r
106\r
107 @param[in] Event The event signaled.\r
108 @param[in] Context The context passed in by the event notifier.\r
109\r
110**/\r
cbf316f2 111VOID\r
112EFIAPI\r
113IpIoTransmitHandler (\r
114 IN EFI_EVENT Event,\r
115 IN VOID *Context\r
116 );\r
117\r
118\r
119/**\r
6aac5e5f 120 This function create an IP child ,open the IP protocol, and return the opened\r
e6ff63a5 121 IP protocol as Interface.\r
cbf316f2 122\r
6aac5e5f 123 @param[in] ControllerHandle The controller handle.\r
124 @param[in] ImageHandle The image handle.\r
125 @param[in] ChildHandle Pointer to the buffer to save the IP child handle.\r
fb115c61 126 @param[in] IpVersion The version of the IP protocol to use, either\r
127 IPv4 or IPv6.\r
6aac5e5f 128 @param[out] Interface Pointer used to get the IP protocol interface.\r
cbf316f2 129\r
6aac5e5f 130 @retval EFI_SUCCESS The IP child is created and the IP protocol\r
131 interface is retrieved.\r
6dbfed92 132 @retval EFI_UNSUPPORTED Upsupported IpVersion.\r
6aac5e5f 133 @retval Others The required operation failed.\r
cbf316f2 134\r
135**/\r
cbf316f2 136EFI_STATUS\r
137IpIoCreateIpChildOpenProtocol (\r
138 IN EFI_HANDLE ControllerHandle,\r
139 IN EFI_HANDLE ImageHandle,\r
140 IN EFI_HANDLE *ChildHandle,\r
b45b45b2 141 IN UINT8 IpVersion,\r
cbf316f2 142 OUT VOID **Interface\r
143 )\r
144{\r
145 EFI_STATUS Status;\r
fb115c61 146 EFI_GUID *ServiceBindingGuid;\r
147 EFI_GUID *IpProtocolGuid;\r
148\r
149 if (IpVersion == IP_VERSION_4) {\r
150 ServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;\r
151 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
152 } else if (IpVersion == IP_VERSION_6){\r
153 ServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;\r
154 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
155 } else {\r
156 return EFI_UNSUPPORTED;\r
157 }\r
cbf316f2 158\r
159 //\r
6aac5e5f 160 // Create an IP child.\r
cbf316f2 161 //\r
162 Status = NetLibCreateServiceChild (\r
163 ControllerHandle,\r
164 ImageHandle,\r
fb115c61 165 ServiceBindingGuid,\r
cbf316f2 166 ChildHandle\r
167 );\r
168 if (EFI_ERROR (Status)) {\r
169 return Status;\r
170 }\r
171\r
172 //\r
6aac5e5f 173 // Open the IP protocol installed on the *ChildHandle.\r
cbf316f2 174 //\r
175 Status = gBS->OpenProtocol (\r
176 *ChildHandle,\r
fb115c61 177 IpProtocolGuid,\r
cbf316f2 178 Interface,\r
179 ImageHandle,\r
180 ControllerHandle,\r
181 EFI_OPEN_PROTOCOL_BY_DRIVER\r
182 );\r
183 if (EFI_ERROR (Status)) {\r
184 //\r
6aac5e5f 185 // On failure, destroy the IP child.\r
cbf316f2 186 //\r
187 NetLibDestroyServiceChild (\r
188 ControllerHandle,\r
189 ImageHandle,\r
fb115c61 190 ServiceBindingGuid,\r
cbf316f2 191 *ChildHandle\r
192 );\r
193 }\r
194\r
195 return Status;\r
196}\r
197\r
198\r
199/**\r
e6ff63a5 200 This function close the previously openned IP protocol and destroy the IP child.\r
cbf316f2 201\r
6aac5e5f 202 @param[in] ControllerHandle The controller handle.\r
203 @param[in] ImageHandle The image handle.\r
204 @param[in] ChildHandle The child handle of the IP child.\r
fb115c61 205 @param[in] IpVersion The version of the IP protocol to use, either\r
206 IPv4 or IPv6.\r
cbf316f2 207\r
6aac5e5f 208 @retval EFI_SUCCESS The IP protocol is closed and the relevant IP child\r
209 is destroyed.\r
6dbfed92 210 @retval EFI_UNSUPPORTED Upsupported IpVersion.\r
6aac5e5f 211 @retval Others The required operation failed.\r
cbf316f2 212\r
213**/\r
cbf316f2 214EFI_STATUS\r
215IpIoCloseProtocolDestroyIpChild (\r
216 IN EFI_HANDLE ControllerHandle,\r
217 IN EFI_HANDLE ImageHandle,\r
fb115c61 218 IN EFI_HANDLE ChildHandle,\r
b45b45b2 219 IN UINT8 IpVersion\r
cbf316f2 220 )\r
221{\r
222 EFI_STATUS Status;\r
fb115c61 223 EFI_GUID *ServiceBindingGuid;\r
224 EFI_GUID *IpProtocolGuid;\r
225\r
226 if (IpVersion == IP_VERSION_4) {\r
227 ServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;\r
228 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
229 } else if (IpVersion == IP_VERSION_6) {\r
230 ServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;\r
231 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
232 } else {\r
233 return EFI_UNSUPPORTED;\r
234 }\r
cbf316f2 235\r
236 //\r
6aac5e5f 237 // Close the previously openned IP protocol.\r
cbf316f2 238 //\r
c167ef91
FS
239 Status = gBS->CloseProtocol (\r
240 ChildHandle,\r
241 IpProtocolGuid,\r
242 ImageHandle,\r
243 ControllerHandle\r
244 );\r
245 if (EFI_ERROR (Status)) {\r
246 return Status;\r
247 }\r
cbf316f2 248\r
249 //\r
6aac5e5f 250 // Destroy the IP child.\r
cbf316f2 251 //\r
c167ef91
FS
252 return NetLibDestroyServiceChild (\r
253 ControllerHandle,\r
254 ImageHandle,\r
255 ServiceBindingGuid,\r
256 ChildHandle\r
257 );\r
cbf316f2 258}\r
259\r
cbf316f2 260/**\r
d1102dba 261 This function handles ICMPv4 packets. It is the worker function of\r
fb115c61 262 IpIoIcmpHandler.\r
cbf316f2 263\r
fb115c61 264 @param[in] IpIo Pointer to the IP_IO instance.\r
265 @param[in, out] Pkt Pointer to the ICMPv4 packet.\r
266 @param[in] Session Pointer to the net session of this ICMPv4 packet.\r
cbf316f2 267\r
fb115c61 268 @retval EFI_SUCCESS The ICMPv4 packet is handled successfully.\r
269 @retval EFI_ABORTED This type of ICMPv4 packet is not supported.\r
cbf316f2 270\r
271**/\r
cbf316f2 272EFI_STATUS\r
fb115c61 273IpIoIcmpv4Handler (\r
6aac5e5f 274 IN IP_IO *IpIo,\r
275 IN OUT NET_BUF *Pkt,\r
276 IN EFI_NET_SESSION_DATA *Session\r
cbf316f2 277 )\r
278{\r
279 IP4_ICMP_ERROR_HEAD *IcmpHdr;\r
280 EFI_IP4_HEADER *IpHdr;\r
b45b45b2 281 UINT8 IcmpErr;\r
cbf316f2 282 UINT8 *PayLoadHdr;\r
283 UINT8 Type;\r
284 UINT8 Code;\r
285 UINT32 TrimBytes;\r
d1102dba 286\r
6ccfeec2
FS
287 ASSERT (IpIo != NULL);\r
288 ASSERT (Pkt != NULL);\r
289 ASSERT (Session != NULL);\r
fb115c61 290 ASSERT (IpIo->IpVersion == IP_VERSION_4);\r
d1102dba 291\r
cbf316f2 292 //\r
293 // Check the ICMP packet length.\r
294 //\r
6ccfeec2
FS
295 if (Pkt->TotalSize < sizeof (IP4_ICMP_ERROR_HEAD)) {\r
296 return EFI_ABORTED;\r
297 }\r
d1102dba 298\r
6ccfeec2
FS
299 IcmpHdr = NET_PROTO_HDR (Pkt, IP4_ICMP_ERROR_HEAD);\r
300 IpHdr = (EFI_IP4_HEADER *) (&IcmpHdr->IpHead);\r
301\r
cbf316f2 302 if (Pkt->TotalSize < ICMP_ERRLEN (IpHdr)) {\r
303\r
304 return EFI_ABORTED;\r
305 }\r
306\r
307 Type = IcmpHdr->Head.Type;\r
308 Code = IcmpHdr->Head.Code;\r
309\r
310 //\r
311 // Analyze the ICMP Error in this ICMP pkt\r
312 //\r
313 switch (Type) {\r
314 case ICMP_TYPE_UNREACH:\r
315 switch (Code) {\r
316 case ICMP_CODE_UNREACH_NET:\r
317 case ICMP_CODE_UNREACH_HOST:\r
318 case ICMP_CODE_UNREACH_PROTOCOL:\r
319 case ICMP_CODE_UNREACH_PORT:\r
320 case ICMP_CODE_UNREACH_SRCFAIL:\r
b45b45b2 321 IcmpErr = (UINT8) (ICMP_ERR_UNREACH_NET + Code);\r
cbf316f2 322\r
323 break;\r
324\r
325 case ICMP_CODE_UNREACH_NEEDFRAG:\r
326 IcmpErr = ICMP_ERR_MSGSIZE;\r
327\r
328 break;\r
329\r
330 case ICMP_CODE_UNREACH_NET_UNKNOWN:\r
331 case ICMP_CODE_UNREACH_NET_PROHIB:\r
332 case ICMP_CODE_UNREACH_TOSNET:\r
333 IcmpErr = ICMP_ERR_UNREACH_NET;\r
334\r
335 break;\r
336\r
337 case ICMP_CODE_UNREACH_HOST_UNKNOWN:\r
338 case ICMP_CODE_UNREACH_ISOLATED:\r
339 case ICMP_CODE_UNREACH_HOST_PROHIB:\r
340 case ICMP_CODE_UNREACH_TOSHOST:\r
341 IcmpErr = ICMP_ERR_UNREACH_HOST;\r
342\r
343 break;\r
344\r
345 default:\r
346 return EFI_ABORTED;\r
cbf316f2 347 }\r
348\r
349 break;\r
350\r
351 case ICMP_TYPE_TIMXCEED:\r
352 if (Code > 1) {\r
353 return EFI_ABORTED;\r
354 }\r
355\r
b45b45b2 356 IcmpErr = (UINT8) (Code + ICMP_ERR_TIMXCEED_INTRANS);\r
cbf316f2 357\r
358 break;\r
359\r
360 case ICMP_TYPE_PARAMPROB:\r
361 if (Code > 1) {\r
362 return EFI_ABORTED;\r
363 }\r
364\r
365 IcmpErr = ICMP_ERR_PARAMPROB;\r
366\r
367 break;\r
368\r
369 case ICMP_TYPE_SOURCEQUENCH:\r
370 if (Code != 0) {\r
371 return EFI_ABORTED;\r
372 }\r
373\r
374 IcmpErr = ICMP_ERR_QUENCH;\r
375\r
376 break;\r
377\r
378 default:\r
379 return EFI_ABORTED;\r
cbf316f2 380 }\r
381\r
382 //\r
383 // Notify user the ICMP pkt only containing payload except\r
384 // IP and ICMP header\r
385 //\r
386 PayLoadHdr = (UINT8 *) ((UINT8 *) IpHdr + EFI_IP4_HEADER_LEN (IpHdr));\r
387 TrimBytes = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);\r
388\r
389 NetbufTrim (Pkt, TrimBytes, TRUE);\r
d1102dba 390\r
c167ef91 391 //\r
d1102dba 392 // If the input packet has invalid format, and TrimBytes is larger than\r
c167ef91
FS
393 // the packet size, the NetbufTrim might trim the packet to zero.\r
394 //\r
395 if (Pkt->TotalSize != 0) {\r
396 IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);\r
397 }\r
cbf316f2 398\r
d1102dba 399 return EFI_SUCCESS;\r
fb115c61 400}\r
401\r
402/**\r
d1102dba 403 This function handles ICMPv6 packets. It is the worker function of\r
fb115c61 404 IpIoIcmpHandler.\r
405\r
406 @param[in] IpIo Pointer to the IP_IO instance.\r
407 @param[in, out] Pkt Pointer to the ICMPv6 packet.\r
408 @param[in] Session Pointer to the net session of this ICMPv6 packet.\r
409\r
410 @retval EFI_SUCCESS The ICMPv6 packet is handled successfully.\r
411 @retval EFI_ABORTED This type of ICMPv6 packet is not supported.\r
412\r
413**/\r
414EFI_STATUS\r
415IpIoIcmpv6Handler (\r
416 IN IP_IO *IpIo,\r
417 IN OUT NET_BUF *Pkt,\r
418 IN EFI_NET_SESSION_DATA *Session\r
419 )\r
420{\r
421 IP6_ICMP_ERROR_HEAD *IcmpHdr;\r
422 EFI_IP6_HEADER *IpHdr;\r
b45b45b2 423 UINT8 IcmpErr;\r
fb115c61 424 UINT8 *PayLoadHdr;\r
425 UINT8 Type;\r
426 UINT8 Code;\r
427 UINT8 NextHeader;\r
428 UINT32 TrimBytes;\r
429 BOOLEAN Flag;\r
430\r
6ccfeec2
FS
431 ASSERT (IpIo != NULL);\r
432 ASSERT (Pkt != NULL);\r
433 ASSERT (Session != NULL);\r
fb115c61 434 ASSERT (IpIo->IpVersion == IP_VERSION_6);\r
435\r
436 //\r
437 // Check the ICMPv6 packet length.\r
438 //\r
439 if (Pkt->TotalSize < sizeof (IP6_ICMP_ERROR_HEAD)) {\r
440\r
441 return EFI_ABORTED;\r
442 }\r
443\r
444 IcmpHdr = NET_PROTO_HDR (Pkt, IP6_ICMP_ERROR_HEAD);\r
445 Type = IcmpHdr->Head.Type;\r
446 Code = IcmpHdr->Head.Code;\r
447\r
448 //\r
449 // Analyze the ICMPv6 Error in this ICMPv6 packet\r
d1102dba 450 //\r
fb115c61 451 switch (Type) {\r
452 case ICMP_V6_DEST_UNREACHABLE:\r
453 switch (Code) {\r
454 case ICMP_V6_NO_ROUTE_TO_DEST:\r
455 case ICMP_V6_BEYOND_SCOPE:\r
456 case ICMP_V6_ROUTE_REJECTED:\r
457 IcmpErr = ICMP6_ERR_UNREACH_NET;\r
458\r
459 break;\r
460\r
461 case ICMP_V6_COMM_PROHIBITED:\r
462 case ICMP_V6_ADDR_UNREACHABLE:\r
463 case ICMP_V6_SOURCE_ADDR_FAILED:\r
464 IcmpErr = ICMP6_ERR_UNREACH_HOST;\r
465\r
466 break;\r
467\r
468 case ICMP_V6_PORT_UNREACHABLE:\r
469 IcmpErr = ICMP6_ERR_UNREACH_PORT;\r
470\r
471 break;\r
472\r
473 default:\r
474 return EFI_ABORTED;\r
475 }\r
476\r
477 break;\r
478\r
479 case ICMP_V6_PACKET_TOO_BIG:\r
480 if (Code >= 1) {\r
481 return EFI_ABORTED;\r
482 }\r
483\r
484 IcmpErr = ICMP6_ERR_PACKAGE_TOOBIG;\r
485\r
486 break;\r
487\r
488 case ICMP_V6_TIME_EXCEEDED:\r
489 if (Code > 1) {\r
490 return EFI_ABORTED;\r
491 }\r
492\r
b45b45b2 493 IcmpErr = (UINT8) (ICMP6_ERR_TIMXCEED_HOPLIMIT + Code);\r
fb115c61 494\r
495 break;\r
496\r
497 case ICMP_V6_PARAMETER_PROBLEM:\r
498 if (Code > 3) {\r
499 return EFI_ABORTED;\r
500 }\r
501\r
b45b45b2 502 IcmpErr = (UINT8) (ICMP6_ERR_PARAMPROB_HEADER + Code);\r
fb115c61 503\r
504 break;\r
505\r
506 default:\r
507\r
508 return EFI_ABORTED;\r
d1102dba 509 }\r
fb115c61 510\r
511 //\r
512 // Notify user the ICMPv6 packet only containing payload except\r
513 // IPv6 basic header, extension header and ICMP header\r
514 //\r
515\r
516 IpHdr = (EFI_IP6_HEADER *) (&IcmpHdr->IpHead);\r
517 NextHeader = IpHdr->NextHeader;\r
518 PayLoadHdr = (UINT8 *) ((UINT8 *) IcmpHdr + sizeof (IP6_ICMP_ERROR_HEAD));\r
519 Flag = TRUE;\r
d1102dba 520\r
fb115c61 521 do {\r
522 switch (NextHeader) {\r
523 case EFI_IP_PROTO_UDP:\r
524 case EFI_IP_PROTO_TCP:\r
525 case EFI_IP_PROTO_ICMP:\r
526 case IP6_NO_NEXT_HEADER:\r
527 Flag = FALSE;\r
528\r
529 break;\r
530\r
531 case IP6_HOP_BY_HOP:\r
532 case IP6_DESTINATION:\r
533 //\r
534 // The Hdr Ext Len is 8-bit unsigned integer in 8-octet units, not including\r
535 // the first 8 octets.\r
536 //\r
537 NextHeader = *(PayLoadHdr);\r
538 PayLoadHdr = (UINT8 *) (PayLoadHdr + (*(PayLoadHdr + 1) + 1) * 8);\r
539\r
540 break;\r
541\r
542 case IP6_FRAGMENT:\r
543 //\r
544 // The Fragment Header Length is 8 octets.\r
545 //\r
546 NextHeader = *(PayLoadHdr);\r
547 PayLoadHdr = (UINT8 *) (PayLoadHdr + 8);\r
548\r
549 break;\r
550\r
551 default:\r
552\r
553 return EFI_ABORTED;\r
554 }\r
555 } while (Flag);\r
556\r
557 TrimBytes = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);\r
d1102dba 558\r
fb115c61 559 NetbufTrim (Pkt, TrimBytes, TRUE);\r
560\r
c167ef91 561 //\r
d1102dba 562 // If the input packet has invalid format, and TrimBytes is larger than\r
c167ef91
FS
563 // the packet size, the NetbufTrim might trim the packet to zero.\r
564 //\r
565 if (Pkt->TotalSize != 0) {\r
566 IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);\r
567 }\r
fb115c61 568\r
cbf316f2 569 return EFI_SUCCESS;\r
570}\r
571\r
fb115c61 572/**\r
573 This function handles ICMP packets.\r
574\r
575 @param[in] IpIo Pointer to the IP_IO instance.\r
576 @param[in, out] Pkt Pointer to the ICMP packet.\r
577 @param[in] Session Pointer to the net session of this ICMP packet.\r
578\r
579 @retval EFI_SUCCESS The ICMP packet is handled successfully.\r
580 @retval EFI_ABORTED This type of ICMP packet is not supported.\r
581 @retval EFI_UNSUPPORTED The IP protocol version in IP_IO is not supported.\r
582\r
583**/\r
584EFI_STATUS\r
585IpIoIcmpHandler (\r
586 IN IP_IO *IpIo,\r
587 IN OUT NET_BUF *Pkt,\r
588 IN EFI_NET_SESSION_DATA *Session\r
589 )\r
590{\r
591\r
592 if (IpIo->IpVersion == IP_VERSION_4) {\r
593\r
594 return IpIoIcmpv4Handler (IpIo, Pkt, Session);\r
595\r
596 } else if (IpIo->IpVersion == IP_VERSION_6) {\r
597\r
598 return IpIoIcmpv6Handler (IpIo, Pkt, Session);\r
599\r
600 } else {\r
601\r
602 return EFI_UNSUPPORTED;\r
603 }\r
604}\r
605\r
cbf316f2 606\r
607/**\r
e6ff63a5 608 Free function for receive token of IP_IO. It is used to\r
cbf316f2 609 signal the recycle event to notify IP to recycle the\r
610 data buffer.\r
611\r
6aac5e5f 612 @param[in] Event The event to be signaled.\r
cbf316f2 613\r
cbf316f2 614**/\r
cbf316f2 615VOID\r
e798cd87 616EFIAPI\r
cbf316f2 617IpIoExtFree (\r
618 IN VOID *Event\r
619 )\r
620{\r
621 gBS->SignalEvent ((EFI_EVENT) Event);\r
622}\r
623\r
624\r
625/**\r
626 Create a send entry to wrap a packet before sending\r
627 out it through IP.\r
628\r
6aac5e5f 629 @param[in, out] IpIo Pointer to the IP_IO instance.\r
630 @param[in, out] Pkt Pointer to the packet.\r
631 @param[in] Sender Pointer to the IP sender.\r
632 @param[in] Context Pointer to the context.\r
633 @param[in] NotifyData Pointer to the notify data.\r
634 @param[in] Dest Pointer to the destination IP address.\r
635 @param[in] Override Pointer to the overriden IP_IO data.\r
cbf316f2 636\r
d1102dba 637 @return Pointer to the data structure created to wrap the packet. If any error occurs,\r
2b208747 638 then return NULL.\r
cbf316f2 639\r
640**/\r
cbf316f2 641IP_IO_SEND_ENTRY *\r
642IpIoCreateSndEntry (\r
6aac5e5f 643 IN OUT IP_IO *IpIo,\r
644 IN OUT NET_BUF *Pkt,\r
2a2e33b2 645 IN IP_IO_IP_PROTOCOL Sender,\r
6aac5e5f 646 IN VOID *Context OPTIONAL,\r
647 IN VOID *NotifyData OPTIONAL,\r
fb115c61 648 IN EFI_IP_ADDRESS *Dest OPTIONAL,\r
6aac5e5f 649 IN IP_IO_OVERRIDE *Override\r
cbf316f2 650 )\r
651{\r
652 IP_IO_SEND_ENTRY *SndEntry;\r
d1102dba 653 EFI_EVENT Event;\r
cbf316f2 654 EFI_STATUS Status;\r
fb115c61 655 NET_FRAGMENT *ExtFragment;\r
656 UINT32 FragmentCount;\r
657 IP_IO_OVERRIDE *OverrideData;\r
658 IP_IO_IP_TX_DATA *TxData;\r
659 EFI_IP4_TRANSMIT_DATA *Ip4TxData;\r
660 EFI_IP6_TRANSMIT_DATA *Ip6TxData;\r
661\r
662 if ((IpIo->IpVersion != IP_VERSION_4) && (IpIo->IpVersion != IP_VERSION_6)) {\r
663 return NULL;\r
664 }\r
665\r
666 Event = NULL;\r
667 TxData = NULL;\r
668 OverrideData = NULL;\r
cbf316f2 669\r
670 //\r
671 // Allocate resource for SndEntry\r
672 //\r
e48e37fc 673 SndEntry = AllocatePool (sizeof (IP_IO_SEND_ENTRY));\r
cbf316f2 674 if (NULL == SndEntry) {\r
675 return NULL;\r
676 }\r
677\r
cbf316f2 678 Status = gBS->CreateEvent (\r
679 EVT_NOTIFY_SIGNAL,\r
e48e37fc 680 TPL_NOTIFY,\r
cbf316f2 681 IpIoTransmitHandler,\r
682 SndEntry,\r
fb115c61 683 &Event\r
cbf316f2 684 );\r
685 if (EFI_ERROR (Status)) {\r
fb115c61 686 goto ON_ERROR;\r
cbf316f2 687 }\r
688\r
fb115c61 689 FragmentCount = Pkt->BlockOpNum;\r
690\r
cbf316f2 691 //\r
692 // Allocate resource for TxData\r
693 //\r
fb115c61 694 TxData = (IP_IO_IP_TX_DATA *) AllocatePool (\r
695 sizeof (IP_IO_IP_TX_DATA) + sizeof (NET_FRAGMENT) * (FragmentCount - 1)\r
cbf316f2 696 );\r
697\r
698 if (NULL == TxData) {\r
fb115c61 699 goto ON_ERROR;\r
700 }\r
701\r
702 //\r
d1102dba 703 // Build a fragment table to contain the fragments in the packet.\r
fb115c61 704 //\r
705 if (IpIo->IpVersion == IP_VERSION_4) {\r
706 ExtFragment = (NET_FRAGMENT *) TxData->Ip4TxData.FragmentTable;\r
707 } else {\r
708 ExtFragment = (NET_FRAGMENT *) TxData->Ip6TxData.FragmentTable;\r
cbf316f2 709 }\r
710\r
fb115c61 711 NetbufBuildExt (Pkt, ExtFragment, &FragmentCount);\r
712\r
713\r
cbf316f2 714 //\r
715 // Allocate resource for OverrideData if needed\r
716 //\r
cbf316f2 717 if (NULL != Override) {\r
718\r
fb115c61 719 OverrideData = AllocateCopyPool (sizeof (IP_IO_OVERRIDE), Override);\r
cbf316f2 720 if (NULL == OverrideData) {\r
fb115c61 721 goto ON_ERROR;\r
cbf316f2 722 }\r
cbf316f2 723 }\r
724\r
725 //\r
fb115c61 726 // Set other fields of TxData except the fragment table\r
cbf316f2 727 //\r
fb115c61 728 if (IpIo->IpVersion == IP_VERSION_4) {\r
cbf316f2 729\r
fb115c61 730 Ip4TxData = &TxData->Ip4TxData;\r
cbf316f2 731\r
35f910f0 732 IP4_COPY_ADDRESS (&Ip4TxData->DestinationAddress, Dest);\r
cbf316f2 733\r
fb115c61 734 Ip4TxData->OverrideData = &OverrideData->Ip4OverrideData;\r
735 Ip4TxData->OptionsLength = 0;\r
736 Ip4TxData->OptionsBuffer = NULL;\r
737 Ip4TxData->TotalDataLength = Pkt->TotalSize;\r
738 Ip4TxData->FragmentCount = FragmentCount;\r
739\r
740 //\r
741 // Set the fields of SndToken\r
742 //\r
743 SndEntry->SndToken.Ip4Token.Event = Event;\r
744 SndEntry->SndToken.Ip4Token.Packet.TxData = Ip4TxData;\r
745 } else {\r
746\r
747 Ip6TxData = &TxData->Ip6TxData;\r
748\r
749 if (Dest != NULL) {\r
750 CopyMem (&Ip6TxData->DestinationAddress, Dest, sizeof (EFI_IPv6_ADDRESS));\r
751 } else {\r
752 ZeroMem (&Ip6TxData->DestinationAddress, sizeof (EFI_IPv6_ADDRESS));\r
753 }\r
754\r
755 Ip6TxData->OverrideData = &OverrideData->Ip6OverrideData;\r
756 Ip6TxData->DataLength = Pkt->TotalSize;\r
757 Ip6TxData->FragmentCount = FragmentCount;\r
758 Ip6TxData->ExtHdrsLength = 0;\r
759 Ip6TxData->ExtHdrs = NULL;\r
d1102dba 760\r
fb115c61 761 //\r
762 // Set the fields of SndToken\r
763 //\r
764 SndEntry->SndToken.Ip6Token.Event = Event;\r
765 SndEntry->SndToken.Ip6Token.Packet.TxData = Ip6TxData;\r
766 }\r
cbf316f2 767\r
768 //\r
769 // Set the fields of SndEntry\r
770 //\r
771 SndEntry->IpIo = IpIo;\r
6aac5e5f 772 SndEntry->Ip = Sender;\r
cbf316f2 773 SndEntry->Context = Context;\r
774 SndEntry->NotifyData = NotifyData;\r
775\r
776 SndEntry->Pkt = Pkt;\r
777 NET_GET_REF (Pkt);\r
778\r
e48e37fc 779 InsertTailList (&IpIo->PendingSndList, &SndEntry->Entry);\r
cbf316f2 780\r
781 return SndEntry;\r
782\r
fb115c61 783ON_ERROR:\r
784\r
785 if (OverrideData != NULL) {\r
786 FreePool (OverrideData);\r
787 }\r
cbf316f2 788\r
fb115c61 789 if (TxData != NULL) {\r
790 FreePool (TxData);\r
791 }\r
cbf316f2 792\r
fb115c61 793 if (SndEntry != NULL) {\r
794 FreePool (SndEntry);\r
795 }\r
cbf316f2 796\r
fb115c61 797 if (Event != NULL) {\r
798 gBS->CloseEvent (Event);\r
799 }\r
cbf316f2 800\r
801 return NULL;\r
802}\r
803\r
804\r
805/**\r
806 Destroy the SndEntry.\r
d1102dba 807\r
e6ff63a5 808 This function pairs with IpIoCreateSndEntry().\r
cbf316f2 809\r
6aac5e5f 810 @param[in] SndEntry Pointer to the send entry to be destroyed.\r
cbf316f2 811\r
cbf316f2 812**/\r
cbf316f2 813VOID\r
814IpIoDestroySndEntry (\r
815 IN IP_IO_SEND_ENTRY *SndEntry\r
816 )\r
817{\r
fb115c61 818 EFI_EVENT Event;\r
819 IP_IO_IP_TX_DATA *TxData;\r
820 IP_IO_OVERRIDE *Override;\r
821\r
822 if (SndEntry->IpIo->IpVersion == IP_VERSION_4) {\r
823 Event = SndEntry->SndToken.Ip4Token.Event;\r
824 TxData = (IP_IO_IP_TX_DATA *) SndEntry->SndToken.Ip4Token.Packet.TxData;\r
825 Override = (IP_IO_OVERRIDE *) TxData->Ip4TxData.OverrideData;\r
826 } else if (SndEntry->IpIo->IpVersion == IP_VERSION_6) {\r
827 Event = SndEntry->SndToken.Ip6Token.Event;\r
828 TxData = (IP_IO_IP_TX_DATA *) SndEntry->SndToken.Ip6Token.Packet.TxData;\r
829 Override = (IP_IO_OVERRIDE *) TxData->Ip6TxData.OverrideData;\r
830 } else {\r
831 return ;\r
832 }\r
cbf316f2 833\r
fb115c61 834 gBS->CloseEvent (Event);\r
cbf316f2 835\r
fb115c61 836 FreePool (TxData);\r
837\r
838 if (NULL != Override) {\r
839 FreePool (Override);\r
cbf316f2 840 }\r
841\r
cbf316f2 842 NetbufFree (SndEntry->Pkt);\r
cbf316f2 843\r
e48e37fc 844 RemoveEntryList (&SndEntry->Entry);\r
cbf316f2 845\r
fb115c61 846 FreePool (SndEntry);\r
cbf316f2 847}\r
848\r
849\r
850/**\r
851 Notify function for IP transmit token.\r
852\r
6aac5e5f 853 @param[in] Context The context passed in by the event notifier.\r
cbf316f2 854\r
cbf316f2 855**/\r
cbf316f2 856VOID\r
857EFIAPI\r
36ee91ca 858IpIoTransmitHandlerDpc (\r
cbf316f2 859 IN VOID *Context\r
860 )\r
861{\r
862 IP_IO *IpIo;\r
863 IP_IO_SEND_ENTRY *SndEntry;\r
fb115c61 864 EFI_STATUS Status;\r
cbf316f2 865\r
866 SndEntry = (IP_IO_SEND_ENTRY *) Context;\r
867\r
868 IpIo = SndEntry->IpIo;\r
869\r
fb115c61 870 if (IpIo->IpVersion == IP_VERSION_4) {\r
871 Status = SndEntry->SndToken.Ip4Token.Status;\r
872 } else if (IpIo->IpVersion == IP_VERSION_6){\r
873 Status = SndEntry->SndToken.Ip6Token.Status;\r
874 } else {\r
875 return ;\r
876 }\r
877\r
8de75da2 878 if ((IpIo->PktSentNotify != NULL) && (SndEntry->NotifyData != NULL)) {\r
cbf316f2 879 IpIo->PktSentNotify (\r
fb115c61 880 Status,\r
cbf316f2 881 SndEntry->Context,\r
882 SndEntry->Ip,\r
883 SndEntry->NotifyData\r
884 );\r
885 }\r
886\r
887 IpIoDestroySndEntry (SndEntry);\r
888}\r
889\r
6aac5e5f 890\r
36ee91ca 891/**\r
892 Notify function for IP transmit token.\r
893\r
6aac5e5f 894 @param[in] Event The event signaled.\r
895 @param[in] Context The context passed in by the event notifier.\r
36ee91ca 896\r
36ee91ca 897**/\r
36ee91ca 898VOID\r
899EFIAPI\r
900IpIoTransmitHandler (\r
901 IN EFI_EVENT Event,\r
902 IN VOID *Context\r
903 )\r
904{\r
905 //\r
906 // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK\r
907 //\r
d8d26fb2 908 QueueDpc (TPL_CALLBACK, IpIoTransmitHandlerDpc, Context);\r
36ee91ca 909}\r
910\r
cbf316f2 911\r
912/**\r
913 The dummy handler for the dummy IP receive token.\r
914\r
6aac5e5f 915 @param[in] Context The context passed in by the event notifier.\r
cbf316f2 916\r
cbf316f2 917**/\r
cbf316f2 918VOID\r
919EFIAPI\r
36ee91ca 920IpIoDummyHandlerDpc (\r
cbf316f2 921 IN VOID *Context\r
922 )\r
923{\r
924 IP_IO_IP_INFO *IpInfo;\r
fb115c61 925 EFI_STATUS Status;\r
926 EFI_EVENT RecycleEvent;\r
cbf316f2 927\r
cbf316f2 928 IpInfo = (IP_IO_IP_INFO *) Context;\r
cbf316f2 929\r
fb115c61 930 if ((IpInfo->IpVersion != IP_VERSION_4) && (IpInfo->IpVersion != IP_VERSION_6)) {\r
931 return ;\r
932 }\r
933\r
934 RecycleEvent = NULL;\r
935\r
936 if (IpInfo->IpVersion == IP_VERSION_4) {\r
937 Status = IpInfo->DummyRcvToken.Ip4Token.Status;\r
938\r
939 if (IpInfo->DummyRcvToken.Ip4Token.Packet.RxData != NULL) {\r
940 RecycleEvent = IpInfo->DummyRcvToken.Ip4Token.Packet.RxData->RecycleSignal;\r
941 }\r
942 } else {\r
943 Status = IpInfo->DummyRcvToken.Ip6Token.Status;\r
944\r
945 if (IpInfo->DummyRcvToken.Ip6Token.Packet.RxData != NULL) {\r
946 RecycleEvent = IpInfo->DummyRcvToken.Ip6Token.Packet.RxData->RecycleSignal;\r
947 }\r
948 }\r
949\r
950\r
951\r
952 if (EFI_ABORTED == Status) {\r
36ee91ca 953 //\r
954 // The reception is actively aborted by the consumer, directly return.\r
955 //\r
956 return;\r
fb115c61 957 } else if (EFI_SUCCESS == Status) {\r
958 //\r
959 // Recycle the RxData.\r
960 //\r
961 ASSERT (RecycleEvent != NULL);\r
cbf316f2 962\r
fb115c61 963 gBS->SignalEvent (RecycleEvent);\r
cbf316f2 964 }\r
965\r
fb115c61 966 //\r
967 // Continue the receive.\r
968 //\r
969 if (IpInfo->IpVersion == IP_VERSION_4) {\r
2a2e33b2 970 IpInfo->Ip.Ip4->Receive (\r
971 IpInfo->Ip.Ip4,\r
972 &IpInfo->DummyRcvToken.Ip4Token\r
973 );\r
fb115c61 974 } else {\r
2a2e33b2 975 IpInfo->Ip.Ip6->Receive (\r
976 IpInfo->Ip.Ip6,\r
977 &IpInfo->DummyRcvToken.Ip6Token\r
978 );\r
fb115c61 979 }\r
cbf316f2 980}\r
981\r
982\r
983/**\r
6aac5e5f 984 This function add IpIoDummyHandlerDpc to the end of the DPC queue.\r
cbf316f2 985\r
6aac5e5f 986 @param[in] Event The event signaled.\r
987 @param[in] Context The context passed in by the event notifier.\r
cbf316f2 988\r
cbf316f2 989**/\r
cbf316f2 990VOID\r
991EFIAPI\r
36ee91ca 992IpIoDummyHandler (\r
cbf316f2 993 IN EFI_EVENT Event,\r
994 IN VOID *Context\r
995 )\r
36ee91ca 996{\r
997 //\r
998 // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK\r
999 //\r
d8d26fb2 1000 QueueDpc (TPL_CALLBACK, IpIoDummyHandlerDpc, Context);\r
36ee91ca 1001}\r
1002\r
1003\r
1004/**\r
1005 Notify function for the IP receive token, used to process\r
1006 the received IP packets.\r
1007\r
6aac5e5f 1008 @param[in] Context The context passed in by the event notifier.\r
36ee91ca 1009\r
36ee91ca 1010**/\r
36ee91ca 1011VOID\r
1012EFIAPI\r
1013IpIoListenHandlerDpc (\r
1014 IN VOID *Context\r
1015 )\r
cbf316f2 1016{\r
1017 IP_IO *IpIo;\r
1018 EFI_STATUS Status;\r
fb115c61 1019 IP_IO_IP_RX_DATA *RxData;\r
cbf316f2 1020 EFI_NET_SESSION_DATA Session;\r
1021 NET_BUF *Pkt;\r
1022\r
fb115c61 1023 IpIo = (IP_IO *) Context;\r
cbf316f2 1024\r
fb115c61 1025 if (IpIo->IpVersion == IP_VERSION_4) {\r
1026 Status = IpIo->RcvToken.Ip4Token.Status;\r
1027 RxData = (IP_IO_IP_RX_DATA *) IpIo->RcvToken.Ip4Token.Packet.RxData;\r
1028 } else if (IpIo->IpVersion == IP_VERSION_6) {\r
1029 Status = IpIo->RcvToken.Ip6Token.Status;\r
1030 RxData = (IP_IO_IP_RX_DATA *) IpIo->RcvToken.Ip6Token.Packet.RxData;\r
1031 } else {\r
1032 return;\r
1033 }\r
cbf316f2 1034\r
36ee91ca 1035 if (EFI_ABORTED == Status) {\r
1036 //\r
1037 // The reception is actively aborted by the consumer, directly return.\r
1038 //\r
1039 return;\r
1040 }\r
1041\r
0a1bd0a3 1042 if ((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) {\r
cbf316f2 1043 //\r
0a1bd0a3 1044 // Only process the normal packets and the icmp error packets.\r
cbf316f2 1045 //\r
0a1bd0a3
WF
1046 if (RxData != NULL) {\r
1047 goto CleanUp;\r
1048 } else {\r
1049 goto Resume;\r
1050 }\r
1051 }\r
1052\r
1053 //\r
1054 // if RxData is NULL with Status == EFI_SUCCESS or EFI_ICMP_ERROR, this should be a code issue in the low layer (IP).\r
1055 //\r
1056 ASSERT (RxData != NULL);\r
1057 if (RxData == NULL) {\r
cbf316f2 1058 goto Resume;\r
1059 }\r
1060\r
1061 if (NULL == IpIo->PktRcvdNotify) {\r
1062 goto CleanUp;\r
1063 }\r
1064\r
fb115c61 1065 if (IpIo->IpVersion == IP_VERSION_4) {\r
6ccfeec2 1066 ASSERT (RxData->Ip4RxData.Header != NULL);\r
dd29d8b3
FS
1067 if (IP4_IS_LOCAL_BROADCAST (EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress))) {\r
1068 //\r
1069 // The source address is a broadcast address, discard it.\r
1070 //\r
1071 goto CleanUp;\r
1072 }\r
fb115c61 1073 if ((EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress) != 0) &&\r
01b5ac88
FS
1074 (IpIo->SubnetMask != 0) &&\r
1075 IP4_NET_EQUAL (IpIo->StationIp, EFI_NTOHL (((EFI_IP4_RECEIVE_DATA *) RxData)->Header->SourceAddress), IpIo->SubnetMask) &&\r
1076 !NetIp4IsUnicast (EFI_NTOHL (((EFI_IP4_RECEIVE_DATA *) RxData)->Header->SourceAddress), IpIo->SubnetMask)) {\r
1b31acb6 1077 //\r
2b208747 1078 // The source address doesn't match StationIp and it's not a unicast IP address, discard it.\r
1b31acb6
FS
1079 //\r
1080 goto CleanUp;\r
1081 }\r
1082\r
1083 if (RxData->Ip4RxData.DataLength == 0) {\r
1084 //\r
1085 // Discard zero length data payload packet.\r
1086 //\r
1087 goto CleanUp;\r
1088 }\r
1089\r
6ccfeec2
FS
1090 //\r
1091 // The fragment should always be valid for non-zero length packet.\r
1092 //\r
1093 ASSERT (RxData->Ip4RxData.FragmentCount != 0);\r
1094\r
cbf316f2 1095 //\r
1b31acb6 1096 // Create a netbuffer representing IPv4 packet\r
cbf316f2 1097 //\r
1b31acb6
FS
1098 Pkt = NetbufFromExt (\r
1099 (NET_FRAGMENT *) RxData->Ip4RxData.FragmentTable,\r
1100 RxData->Ip4RxData.FragmentCount,\r
1101 0,\r
1102 0,\r
1103 IpIoExtFree,\r
1104 RxData->Ip4RxData.RecycleSignal\r
1105 );\r
1106 if (NULL == Pkt) {\r
1107 goto CleanUp;\r
1108 }\r
cbf316f2 1109\r
1b31acb6
FS
1110 //\r
1111 // Create a net session\r
1112 //\r
1113 Session.Source.Addr[0] = EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress);\r
1114 Session.Dest.Addr[0] = EFI_IP4 (RxData->Ip4RxData.Header->DestinationAddress);\r
1115 Session.IpHdr.Ip4Hdr = RxData->Ip4RxData.Header;\r
1116 Session.IpHdrLen = RxData->Ip4RxData.HeaderLength;\r
1117 Session.IpVersion = IP_VERSION_4;\r
fb115c61 1118 } else {\r
6ccfeec2 1119 ASSERT (RxData->Ip6RxData.Header != NULL);\r
f6b7393c 1120 if (!NetIp6IsValidUnicast(&RxData->Ip6RxData.Header->SourceAddress)) {\r
fb115c61 1121 goto CleanUp;\r
1122 }\r
d1102dba 1123\r
1b31acb6
FS
1124 if (RxData->Ip6RxData.DataLength == 0) {\r
1125 //\r
1126 // Discard zero length data payload packet.\r
1127 //\r
1128 goto CleanUp;\r
1129 }\r
d1102dba 1130\r
6ccfeec2
FS
1131 //\r
1132 // The fragment should always be valid for non-zero length packet.\r
1133 //\r
1134 ASSERT (RxData->Ip6RxData.FragmentCount != 0);\r
d1102dba 1135\r
fb115c61 1136 //\r
1137 // Create a netbuffer representing IPv6 packet\r
1138 //\r
1139 Pkt = NetbufFromExt (\r
1140 (NET_FRAGMENT *) RxData->Ip6RxData.FragmentTable,\r
1141 RxData->Ip6RxData.FragmentCount,\r
1142 0,\r
1143 0,\r
1144 IpIoExtFree,\r
1145 RxData->Ip6RxData.RecycleSignal\r
1146 );\r
1147 if (NULL == Pkt) {\r
1148 goto CleanUp;\r
1149 }\r
1150\r
1151 //\r
1152 // Create a net session\r
1153 //\r
1154 CopyMem (\r
d1102dba 1155 &Session.Source,\r
fb115c61 1156 &RxData->Ip6RxData.Header->SourceAddress,\r
1157 sizeof(EFI_IPv6_ADDRESS)\r
1158 );\r
1159 CopyMem (\r
d1102dba
LG
1160 &Session.Dest,\r
1161 &RxData->Ip6RxData.Header->DestinationAddress,\r
fb115c61 1162 sizeof(EFI_IPv6_ADDRESS)\r
1163 );\r
1164 Session.IpHdr.Ip6Hdr = RxData->Ip6RxData.Header;\r
a09ee46d 1165 Session.IpHdrLen = RxData->Ip6RxData.HeaderLength;\r
fb115c61 1166 Session.IpVersion = IP_VERSION_6;\r
d1102dba 1167 }\r
cbf316f2 1168\r
1169 if (EFI_SUCCESS == Status) {\r
1170\r
b45b45b2 1171 IpIo->PktRcvdNotify (EFI_SUCCESS, 0, &Session, Pkt, IpIo->RcvdContext);\r
cbf316f2 1172 } else {\r
1173 //\r
1174 // Status is EFI_ICMP_ERROR\r
1175 //\r
1176 Status = IpIoIcmpHandler (IpIo, Pkt, &Session);\r
1177 if (EFI_ERROR (Status)) {\r
1178 NetbufFree (Pkt);\r
1179 }\r
1180 }\r
1181\r
1182 goto Resume;\r
1183\r
1184CleanUp:\r
fb115c61 1185\r
1186 if (IpIo->IpVersion == IP_VERSION_4){\r
1187 gBS->SignalEvent (RxData->Ip4RxData.RecycleSignal);\r
1188 } else {\r
d1102dba 1189 gBS->SignalEvent (RxData->Ip6RxData.RecycleSignal);\r
fb115c61 1190 }\r
cbf316f2 1191\r
1192Resume:\r
cbf316f2 1193\r
fb115c61 1194 if (IpIo->IpVersion == IP_VERSION_4){\r
2a2e33b2 1195 IpIo->Ip.Ip4->Receive (IpIo->Ip.Ip4, &(IpIo->RcvToken.Ip4Token));\r
fb115c61 1196 } else {\r
2a2e33b2 1197 IpIo->Ip.Ip6->Receive (IpIo->Ip.Ip6, &(IpIo->RcvToken.Ip6Token));\r
fb115c61 1198 }\r
1199}\r
cbf316f2 1200\r
36ee91ca 1201/**\r
6aac5e5f 1202 This function add IpIoListenHandlerDpc to the end of the DPC queue.\r
36ee91ca 1203\r
6aac5e5f 1204 @param[in] Event The event signaled.\r
1205 @param[in] Context The context passed in by the event notifier.\r
36ee91ca 1206\r
1207**/\r
36ee91ca 1208VOID\r
1209EFIAPI\r
1210IpIoListenHandler (\r
1211 IN EFI_EVENT Event,\r
1212 IN VOID *Context\r
1213 )\r
1214{\r
1215 //\r
1216 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK\r
1217 //\r
d8d26fb2 1218 QueueDpc (TPL_CALLBACK, IpIoListenHandlerDpc, Context);\r
36ee91ca 1219}\r
1220\r
1221\r
cbf316f2 1222/**\r
1223 Create a new IP_IO instance.\r
2b208747
WF
1224\r
1225 If IpVersion is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
d1102dba 1226\r
fb115c61 1227 This function uses IP4/IP6 service binding protocol in Controller to create\r
1228 an IP4/IP6 child (aka IP4/IP6 instance).\r
cbf316f2 1229\r
6aac5e5f 1230 @param[in] Image The image handle of the driver or application that\r
e6ff63a5 1231 consumes IP_IO.\r
fb115c61 1232 @param[in] Controller The controller handle that has IP4 or IP6 service\r
1233 binding protocol installed.\r
1234 @param[in] IpVersion The version of the IP protocol to use, either\r
d1102dba 1235 IPv4 or IPv6.\r
cbf316f2 1236\r
e6ff63a5 1237 @return Pointer to a newly created IP_IO instance, or NULL if failed.\r
cbf316f2 1238\r
1239**/\r
1240IP_IO *\r
7b414b4e 1241EFIAPI\r
cbf316f2 1242IpIoCreate (\r
1243 IN EFI_HANDLE Image,\r
fb115c61 1244 IN EFI_HANDLE Controller,\r
b45b45b2 1245 IN UINT8 IpVersion\r
cbf316f2 1246 )\r
1247{\r
1248 EFI_STATUS Status;\r
1249 IP_IO *IpIo;\r
fb115c61 1250 EFI_EVENT Event;\r
1251\r
1252 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
cbf316f2 1253\r
e48e37fc 1254 IpIo = AllocateZeroPool (sizeof (IP_IO));\r
cbf316f2 1255 if (NULL == IpIo) {\r
1256 return NULL;\r
1257 }\r
1258\r
e48e37fc 1259 InitializeListHead (&(IpIo->PendingSndList));\r
1260 InitializeListHead (&(IpIo->IpList));\r
cbf316f2 1261 IpIo->Controller = Controller;\r
1262 IpIo->Image = Image;\r
fb115c61 1263 IpIo->IpVersion = IpVersion;\r
1264 Event = NULL;\r
cbf316f2 1265\r
1266 Status = gBS->CreateEvent (\r
1267 EVT_NOTIFY_SIGNAL,\r
e48e37fc 1268 TPL_NOTIFY,\r
cbf316f2 1269 IpIoListenHandler,\r
1270 IpIo,\r
fb115c61 1271 &Event\r
cbf316f2 1272 );\r
1273 if (EFI_ERROR (Status)) {\r
1274 goto ReleaseIpIo;\r
1275 }\r
1276\r
fb115c61 1277 if (IpVersion == IP_VERSION_4) {\r
1278 IpIo->RcvToken.Ip4Token.Event = Event;\r
1279 } else {\r
1280 IpIo->RcvToken.Ip6Token.Event = Event;\r
1281 }\r
1282\r
cbf316f2 1283 //\r
1284 // Create an IP child and open IP protocol\r
1285 //\r
1286 Status = IpIoCreateIpChildOpenProtocol (\r
1287 Controller,\r
1288 Image,\r
1289 &IpIo->ChildHandle,\r
d1102dba 1290 IpVersion,\r
2b208747 1291 (VOID **) & (IpIo->Ip)\r
cbf316f2 1292 );\r
1293 if (EFI_ERROR (Status)) {\r
1294 goto ReleaseIpIo;\r
1295 }\r
1296\r
1297 return IpIo;\r
1298\r
1299ReleaseIpIo:\r
1300\r
fb115c61 1301 if (Event != NULL) {\r
1302 gBS->CloseEvent (Event);\r
cbf316f2 1303 }\r
1304\r
e48e37fc 1305 gBS->FreePool (IpIo);\r
cbf316f2 1306\r
1307 return NULL;\r
1308}\r
1309\r
1310\r
1311/**\r
1312 Open an IP_IO instance for use.\r
2b208747
WF
1313\r
1314 If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
1315\r
e6ff63a5 1316 This function is called after IpIoCreate(). It is used for configuring the IP\r
1317 instance and register the callbacks and their context data for sending and\r
1318 receiving IP packets.\r
cbf316f2 1319\r
6aac5e5f 1320 @param[in, out] IpIo Pointer to an IP_IO instance that needs\r
1321 to open.\r
1322 @param[in] OpenData The configuration data and callbacks for\r
1323 the IP_IO instance.\r
cbf316f2 1324\r
6ccfeec2
FS
1325 @retval EFI_SUCCESS The IP_IO instance opened with OpenData\r
1326 successfully.\r
d1102dba 1327 @retval EFI_ACCESS_DENIED The IP_IO instance is configured, avoid to\r
6ccfeec2
FS
1328 reopen it.\r
1329 @retval EFI_UNSUPPORTED IPv4 RawData mode is no supported.\r
1330 @retval EFI_INVALID_PARAMETER Invalid input parameter.\r
1331 @retval Others Error condition occurred.\r
cbf316f2 1332\r
1333**/\r
1334EFI_STATUS\r
7b414b4e 1335EFIAPI\r
cbf316f2 1336IpIoOpen (\r
6aac5e5f 1337 IN OUT IP_IO *IpIo,\r
1338 IN IP_IO_OPEN_DATA *OpenData\r
cbf316f2 1339 )\r
1340{\r
1341 EFI_STATUS Status;\r
b45b45b2 1342 UINT8 IpVersion;\r
cbf316f2 1343\r
6ccfeec2
FS
1344 if (IpIo == NULL || OpenData == NULL) {\r
1345 return EFI_INVALID_PARAMETER;\r
1346 }\r
1347\r
cbf316f2 1348 if (IpIo->IsConfigured) {\r
1349 return EFI_ACCESS_DENIED;\r
1350 }\r
1351\r
fb115c61 1352 IpVersion = IpIo->IpVersion;\r
1353\r
1354 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
1355\r
cbf316f2 1356 //\r
1357 // configure ip\r
1358 //\r
fb115c61 1359 if (IpVersion == IP_VERSION_4){\r
1b31acb6
FS
1360 //\r
1361 // RawData mode is no supported.\r
1362 //\r
1363 ASSERT (!OpenData->IpConfigData.Ip4CfgData.RawData);\r
1364 if (OpenData->IpConfigData.Ip4CfgData.RawData) {\r
1365 return EFI_UNSUPPORTED;\r
1366 }\r
01b5ac88
FS
1367\r
1368 if (!OpenData->IpConfigData.Ip4CfgData.UseDefaultAddress) {\r
1369 IpIo->StationIp = EFI_NTOHL (OpenData->IpConfigData.Ip4CfgData.StationAddress);\r
1370 IpIo->SubnetMask = EFI_NTOHL (OpenData->IpConfigData.Ip4CfgData.SubnetMask);\r
1371 }\r
d1102dba 1372\r
2a2e33b2 1373 Status = IpIo->Ip.Ip4->Configure (\r
1374 IpIo->Ip.Ip4,\r
1375 &OpenData->IpConfigData.Ip4CfgData\r
1376 );\r
fb115c61 1377 } else {\r
1378\r
2a2e33b2 1379 Status = IpIo->Ip.Ip6->Configure (\r
d1102dba 1380 IpIo->Ip.Ip6,\r
2a2e33b2 1381 &OpenData->IpConfigData.Ip6CfgData\r
1382 );\r
fb115c61 1383 }\r
1384\r
cbf316f2 1385 if (EFI_ERROR (Status)) {\r
1386 return Status;\r
1387 }\r
1388\r
1389 //\r
6aac5e5f 1390 // @bug To delete the default route entry in this Ip, if it is:\r
1391 // @bug (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified\r
1392 // @bug its code\r
cbf316f2 1393 //\r
fb115c61 1394 if (IpVersion == IP_VERSION_4){\r
2a2e33b2 1395 Status = IpIo->Ip.Ip4->Routes (\r
1396 IpIo->Ip.Ip4,\r
1397 TRUE,\r
1398 &mZeroIp4Addr,\r
1399 &mZeroIp4Addr,\r
1400 &mZeroIp4Addr\r
1401 );\r
fb115c61 1402\r
1403 if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {\r
1404 return Status;\r
1405 }\r
cbf316f2 1406 }\r
1407\r
1408 IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;\r
1409 IpIo->PktSentNotify = OpenData->PktSentNotify;\r
1410\r
1411 IpIo->RcvdContext = OpenData->RcvdContext;\r
1412 IpIo->SndContext = OpenData->SndContext;\r
1413\r
fb115c61 1414 if (IpVersion == IP_VERSION_4){\r
1415 IpIo->Protocol = OpenData->IpConfigData.Ip4CfgData.DefaultProtocol;\r
cbf316f2 1416\r
fb115c61 1417 //\r
1418 // start to listen incoming packet\r
1419 //\r
2a2e33b2 1420 Status = IpIo->Ip.Ip4->Receive (\r
1421 IpIo->Ip.Ip4,\r
1422 &(IpIo->RcvToken.Ip4Token)\r
1423 );\r
fb115c61 1424 if (EFI_ERROR (Status)) {\r
2a2e33b2 1425 IpIo->Ip.Ip4->Configure (IpIo->Ip.Ip4, NULL);\r
2b208747 1426 return Status;\r
fb115c61 1427 }\r
1428\r
1429 } else {\r
1430\r
1431 IpIo->Protocol = OpenData->IpConfigData.Ip6CfgData.DefaultProtocol;\r
2a2e33b2 1432 Status = IpIo->Ip.Ip6->Receive (\r
1433 IpIo->Ip.Ip6,\r
1434 &(IpIo->RcvToken.Ip6Token)\r
1435 );\r
fb115c61 1436 if (EFI_ERROR (Status)) {\r
2a2e33b2 1437 IpIo->Ip.Ip6->Configure (IpIo->Ip.Ip6, NULL);\r
2b208747 1438 return Status;\r
fb115c61 1439 }\r
cbf316f2 1440 }\r
1441\r
1442 IpIo->IsConfigured = TRUE;\r
e48e37fc 1443 InsertTailList (&mActiveIpIoList, &IpIo->Entry);\r
cbf316f2 1444\r
cbf316f2 1445 return Status;\r
1446}\r
1447\r
1448\r
1449/**\r
1450 Stop an IP_IO instance.\r
2b208747
WF
1451\r
1452 If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
d1102dba 1453\r
e6ff63a5 1454 This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all\r
1455 the pending send/receive tokens will be canceled.\r
cbf316f2 1456\r
6aac5e5f 1457 @param[in, out] IpIo Pointer to the IP_IO instance that needs to stop.\r
cbf316f2 1458\r
6ccfeec2
FS
1459 @retval EFI_SUCCESS The IP_IO instance stopped successfully.\r
1460 @retval EFI_INVALID_PARAMETER Invalid input parameter.\r
1461 @retval Others Error condition occurred.\r
cbf316f2 1462\r
1463**/\r
1464EFI_STATUS\r
e6ff63a5 1465EFIAPI\r
cbf316f2 1466IpIoStop (\r
6aac5e5f 1467 IN OUT IP_IO *IpIo\r
cbf316f2 1468 )\r
1469{\r
1470 EFI_STATUS Status;\r
cbf316f2 1471 IP_IO_IP_INFO *IpInfo;\r
b45b45b2 1472 UINT8 IpVersion;\r
cbf316f2 1473\r
6ccfeec2
FS
1474 if (IpIo == NULL) {\r
1475 return EFI_INVALID_PARAMETER;\r
1476 }\r
1477\r
cbf316f2 1478 if (!IpIo->IsConfigured) {\r
1479 return EFI_SUCCESS;\r
1480 }\r
1481\r
fb115c61 1482 IpVersion = IpIo->IpVersion;\r
1483\r
1484 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
1485\r
cbf316f2 1486 //\r
1487 // Remove the IpIo from the active IpIo list.\r
1488 //\r
e48e37fc 1489 RemoveEntryList (&IpIo->Entry);\r
cbf316f2 1490\r
cbf316f2 1491 //\r
1492 // Configure NULL Ip\r
1493 //\r
fb115c61 1494 if (IpVersion == IP_VERSION_4) {\r
2a2e33b2 1495 Status = IpIo->Ip.Ip4->Configure (IpIo->Ip.Ip4, NULL);\r
fb115c61 1496 } else {\r
2a2e33b2 1497 Status = IpIo->Ip.Ip6->Configure (IpIo->Ip.Ip6, NULL);\r
fb115c61 1498 }\r
cbf316f2 1499 if (EFI_ERROR (Status)) {\r
1500 return Status;\r
1501 }\r
1502\r
1503 IpIo->IsConfigured = FALSE;\r
1504\r
1505 //\r
1506 // Detroy the Ip List used by IpIo\r
1507 //\r
34edf2ae 1508\r
e48e37fc 1509 while (!IsListEmpty (&(IpIo->IpList))) {\r
cbf316f2 1510 IpInfo = NET_LIST_HEAD (&(IpIo->IpList), IP_IO_IP_INFO, Entry);\r
1511\r
1512 IpIoRemoveIp (IpIo, IpInfo);\r
1513 }\r
1514\r
1515 //\r
3b28e744 1516 // All pending send tokens should be flushed by resetting the IP instances.\r
cbf316f2 1517 //\r
e48e37fc 1518 ASSERT (IsListEmpty (&IpIo->PendingSndList));\r
cbf316f2 1519\r
1520 //\r
1521 // Close the receive event.\r
1522 //\r
fb115c61 1523 if (IpVersion == IP_VERSION_4){\r
1524 gBS->CloseEvent (IpIo->RcvToken.Ip4Token.Event);\r
1525 } else {\r
1526 gBS->CloseEvent (IpIo->RcvToken.Ip6Token.Event);\r
1527 }\r
cbf316f2 1528\r
1529 return EFI_SUCCESS;\r
1530}\r
1531\r
1532\r
1533/**\r
1534 Destroy an IP_IO instance.\r
d1102dba 1535\r
e6ff63a5 1536 This function is paired with IpIoCreate(). The IP_IO will be closed first.\r
8f5e6151 1537 Resource will be freed afterwards. See IpIoCloseProtocolDestroyIpChild().\r
cbf316f2 1538\r
6aac5e5f 1539 @param[in, out] IpIo Pointer to the IP_IO instance that needs to be\r
e6ff63a5 1540 destroyed.\r
cbf316f2 1541\r
6aac5e5f 1542 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.\r
1543 @retval Others Error condition occurred.\r
cbf316f2 1544\r
1545**/\r
1546EFI_STATUS\r
7b414b4e 1547EFIAPI\r
cbf316f2 1548IpIoDestroy (\r
6aac5e5f 1549 IN OUT IP_IO *IpIo\r
cbf316f2 1550 )\r
1551{\r
6dbfed92 1552 EFI_STATUS Status;\r
d1102dba 1553\r
cbf316f2 1554 //\r
1555 // Stop the IpIo.\r
1556 //\r
6dbfed92
FS
1557 Status = IpIoStop (IpIo);\r
1558 if (EFI_ERROR (Status)) {\r
1559 return Status;\r
1560 }\r
cbf316f2 1561\r
1562 //\r
1563 // Close the IP protocol and destroy the child.\r
1564 //\r
6dbfed92
FS
1565 Status = IpIoCloseProtocolDestroyIpChild (\r
1566 IpIo->Controller,\r
1567 IpIo->Image,\r
1568 IpIo->ChildHandle,\r
1569 IpIo->IpVersion\r
1570 );\r
1571 if (EFI_ERROR (Status)) {\r
1572 return Status;\r
1573 }\r
cbf316f2 1574\r
e48e37fc 1575 gBS->FreePool (IpIo);\r
cbf316f2 1576\r
1577 return EFI_SUCCESS;\r
1578}\r
1579\r
1580\r
1581/**\r
1582 Send out an IP packet.\r
d1102dba 1583\r
2b208747 1584 This function is called after IpIoOpen(). The data to be sent is wrapped in\r
e6ff63a5 1585 Pkt. The IP instance wrapped in IpIo is used for sending by default but can be\r
1586 overriden by Sender. Other sending configs, like source address and gateway\r
1587 address etc., are specified in OverrideData.\r
cbf316f2 1588\r
6aac5e5f 1589 @param[in, out] IpIo Pointer to an IP_IO instance used for sending IP\r
1590 packet.\r
1591 @param[in, out] Pkt Pointer to the IP packet to be sent.\r
1592 @param[in] Sender The IP protocol instance used for sending.\r
8f5e6151 1593 @param[in] Context Optional context data.\r
1594 @param[in] NotifyData Optional notify data.\r
6aac5e5f 1595 @param[in] Dest The destination IP address to send this packet to.\r
8569a87e 1596 This parameter is optional when using IPv6.\r
6aac5e5f 1597 @param[in] OverrideData The data to override some configuration of the IP\r
1598 instance used for sending.\r
cbf316f2 1599\r
6aac5e5f 1600 @retval EFI_SUCCESS The operation is completed successfully.\r
8569a87e 1601 @retval EFI_INVALID_PARAMETER The input parameter is not correct.\r
6aac5e5f 1602 @retval EFI_NOT_STARTED The IpIo is not configured.\r
1603 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
6dbfed92 1604 @retval Others Error condition occurred.\r
cbf316f2 1605\r
1606**/\r
1607EFI_STATUS\r
7b414b4e 1608EFIAPI\r
cbf316f2 1609IpIoSend (\r
6aac5e5f 1610 IN OUT IP_IO *IpIo,\r
1611 IN OUT NET_BUF *Pkt,\r
1612 IN IP_IO_IP_INFO *Sender OPTIONAL,\r
1613 IN VOID *Context OPTIONAL,\r
1614 IN VOID *NotifyData OPTIONAL,\r
c167ef91 1615 IN EFI_IP_ADDRESS *Dest OPTIONAL,\r
6aac5e5f 1616 IN IP_IO_OVERRIDE *OverrideData OPTIONAL\r
cbf316f2 1617 )\r
1618{\r
1619 EFI_STATUS Status;\r
2a2e33b2 1620 IP_IO_IP_PROTOCOL Ip;\r
cbf316f2 1621 IP_IO_SEND_ENTRY *SndEntry;\r
1622\r
8569a87e
FS
1623 if ((IpIo == NULL) || (Pkt == NULL)) {\r
1624 return EFI_INVALID_PARAMETER;\r
1625 }\r
1626\r
1627 if ((IpIo->IpVersion == IP_VERSION_4) && (Dest == NULL)) {\r
1628 return EFI_INVALID_PARAMETER;\r
1629 }\r
fb115c61 1630\r
cbf316f2 1631 if (!IpIo->IsConfigured) {\r
1632 return EFI_NOT_STARTED;\r
1633 }\r
1634\r
1635 Ip = (NULL == Sender) ? IpIo->Ip : Sender->Ip;\r
1636\r
1637 //\r
1638 // create a new SndEntry\r
1639 //\r
1640 SndEntry = IpIoCreateSndEntry (IpIo, Pkt, Ip, Context, NotifyData, Dest, OverrideData);\r
1641 if (NULL == SndEntry) {\r
1642 return EFI_OUT_OF_RESOURCES;\r
1643 }\r
1644\r
1645 //\r
1646 // Send this Packet\r
1647 //\r
fb115c61 1648 if (IpIo->IpVersion == IP_VERSION_4){\r
2a2e33b2 1649 Status = Ip.Ip4->Transmit (\r
1650 Ip.Ip4,\r
1651 &SndEntry->SndToken.Ip4Token\r
1652 );\r
fb115c61 1653 } else {\r
2a2e33b2 1654 Status = Ip.Ip6->Transmit (\r
1655 Ip.Ip6,\r
1656 &SndEntry->SndToken.Ip6Token\r
1657 );\r
fb115c61 1658 }\r
1659\r
cbf316f2 1660 if (EFI_ERROR (Status)) {\r
1661 IpIoDestroySndEntry (SndEntry);\r
1662 }\r
1663\r
1664 return Status;\r
1665}\r
1666\r
1667\r
1668/**\r
1669 Cancel the IP transmit token which wraps this Packet.\r
1670\r
2b208747
WF
1671 If IpIo is NULL, then ASSERT().\r
1672 If Packet is NULL, then ASSERT().\r
1673\r
6aac5e5f 1674 @param[in] IpIo Pointer to the IP_IO instance.\r
1675 @param[in] Packet Pointer to the packet of NET_BUF to cancel.\r
cbf316f2 1676\r
1677**/\r
1678VOID\r
7b414b4e 1679EFIAPI\r
cbf316f2 1680IpIoCancelTxToken (\r
1681 IN IP_IO *IpIo,\r
1682 IN VOID *Packet\r
1683 )\r
1684{\r
e48e37fc 1685 LIST_ENTRY *Node;\r
cbf316f2 1686 IP_IO_SEND_ENTRY *SndEntry;\r
2a2e33b2 1687 IP_IO_IP_PROTOCOL Ip;\r
cbf316f2 1688\r
fb115c61 1689 ASSERT ((IpIo != NULL) && (Packet != NULL));\r
cbf316f2 1690\r
1691 NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {\r
1692\r
1693 SndEntry = NET_LIST_USER_STRUCT (Node, IP_IO_SEND_ENTRY, Entry);\r
1694\r
1695 if (SndEntry->Pkt == Packet) {\r
1696\r
1697 Ip = SndEntry->Ip;\r
fb115c61 1698\r
1699 if (IpIo->IpVersion == IP_VERSION_4) {\r
2a2e33b2 1700 Ip.Ip4->Cancel (\r
1701 Ip.Ip4,\r
1702 &SndEntry->SndToken.Ip4Token\r
1703 );\r
fb115c61 1704 } else {\r
2a2e33b2 1705 Ip.Ip6->Cancel (\r
1706 Ip.Ip6,\r
1707 &SndEntry->SndToken.Ip6Token\r
1708 );\r
fb115c61 1709 }\r
cbf316f2 1710\r
cbf316f2 1711 break;\r
1712 }\r
1713 }\r
1714\r
1715}\r
1716\r
1717\r
1718/**\r
1719 Add a new IP instance for sending data.\r
2b208747
WF
1720\r
1721 If IpIo is NULL, then ASSERT().\r
1722 If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
d1102dba 1723\r
e6ff63a5 1724 The function is used to add the IP_IO to the IP_IO sending list. The caller\r
1725 can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send\r
1726 data.\r
cbf316f2 1727\r
6aac5e5f 1728 @param[in, out] IpIo Pointer to a IP_IO instance to add a new IP\r
1729 instance for sending purpose.\r
cbf316f2 1730\r
e6ff63a5 1731 @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.\r
cbf316f2 1732\r
1733**/\r
1734IP_IO_IP_INFO *\r
7b414b4e 1735EFIAPI\r
cbf316f2 1736IpIoAddIp (\r
6aac5e5f 1737 IN OUT IP_IO *IpIo\r
cbf316f2 1738 )\r
1739{\r
1740 EFI_STATUS Status;\r
1741 IP_IO_IP_INFO *IpInfo;\r
fb115c61 1742 EFI_EVENT Event;\r
cbf316f2 1743\r
6aac5e5f 1744 ASSERT (IpIo != NULL);\r
6478baf8 1745 ASSERT ((IpIo->IpVersion == IP_VERSION_4) || (IpIo->IpVersion == IP_VERSION_6));\r
cbf316f2 1746\r
e48e37fc 1747 IpInfo = AllocatePool (sizeof (IP_IO_IP_INFO));\r
cbf316f2 1748 if (IpInfo == NULL) {\r
fb115c61 1749 return NULL;\r
cbf316f2 1750 }\r
1751\r
1752 //\r
1753 // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP\r
1754 // instance.\r
1755 //\r
e48e37fc 1756 InitializeListHead (&IpInfo->Entry);\r
cbf316f2 1757 IpInfo->ChildHandle = NULL;\r
fb115c61 1758 ZeroMem (&IpInfo->Addr, sizeof (IpInfo->Addr));\r
1759 ZeroMem (&IpInfo->PreMask, sizeof (IpInfo->PreMask));\r
1760\r
1761 IpInfo->RefCnt = 1;\r
1762 IpInfo->IpVersion = IpIo->IpVersion;\r
cbf316f2 1763\r
1764 //\r
fb115c61 1765 // Create the IP instance and open the IP protocol.\r
cbf316f2 1766 //\r
1767 Status = IpIoCreateIpChildOpenProtocol (\r
1768 IpIo->Controller,\r
1769 IpIo->Image,\r
1770 &IpInfo->ChildHandle,\r
fb115c61 1771 IpInfo->IpVersion,\r
4eb65aff 1772 (VOID **) &IpInfo->Ip\r
cbf316f2 1773 );\r
1774 if (EFI_ERROR (Status)) {\r
1775 goto ReleaseIpInfo;\r
1776 }\r
1777\r
1778 //\r
1779 // Create the event for the DummyRcvToken.\r
1780 //\r
1781 Status = gBS->CreateEvent (\r
1782 EVT_NOTIFY_SIGNAL,\r
e48e37fc 1783 TPL_NOTIFY,\r
cbf316f2 1784 IpIoDummyHandler,\r
1785 IpInfo,\r
fb115c61 1786 &Event\r
cbf316f2 1787 );\r
1788 if (EFI_ERROR (Status)) {\r
1789 goto ReleaseIpChild;\r
1790 }\r
1791\r
fb115c61 1792 if (IpInfo->IpVersion == IP_VERSION_4) {\r
1793 IpInfo->DummyRcvToken.Ip4Token.Event = Event;\r
1794 } else {\r
1795 IpInfo->DummyRcvToken.Ip6Token.Event = Event;\r
1796 }\r
1797\r
cbf316f2 1798 //\r
1799 // Link this IpInfo into the IpIo.\r
1800 //\r
e48e37fc 1801 InsertTailList (&IpIo->IpList, &IpInfo->Entry);\r
cbf316f2 1802\r
1803 return IpInfo;\r
1804\r
1805ReleaseIpChild:\r
1806\r
1807 IpIoCloseProtocolDestroyIpChild (\r
1808 IpIo->Controller,\r
1809 IpIo->Image,\r
fb115c61 1810 IpInfo->ChildHandle,\r
1811 IpInfo->IpVersion\r
cbf316f2 1812 );\r
1813\r
1814ReleaseIpInfo:\r
1815\r
e48e37fc 1816 gBS->FreePool (IpInfo);\r
cbf316f2 1817\r
1818 return NULL;\r
1819}\r
1820\r
1821\r
1822/**\r
fb115c61 1823 Configure the IP instance of this IpInfo and start the receiving if IpConfigData\r
cbf316f2 1824 is not NULL.\r
1825\r
2b208747
WF
1826 If IpInfo is NULL, then ASSERT().\r
1827 If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
1828\r
6aac5e5f 1829 @param[in, out] IpInfo Pointer to the IP_IO_IP_INFO instance.\r
fb115c61 1830 @param[in, out] IpConfigData The IP configure data used to configure the IP\r
6aac5e5f 1831 instance, if NULL the IP instance is reset. If\r
1832 UseDefaultAddress is set to TRUE, and the configure\r
1833 operation succeeds, the default address information\r
fb115c61 1834 is written back in this IpConfigData.\r
cbf316f2 1835\r
6aac5e5f 1836 @retval EFI_SUCCESS The IP instance of this IpInfo is configured successfully\r
1837 or no need to reconfigure it.\r
1838 @retval Others Configuration fails.\r
cbf316f2 1839\r
1840**/\r
1841EFI_STATUS\r
7b414b4e 1842EFIAPI\r
cbf316f2 1843IpIoConfigIp (\r
6aac5e5f 1844 IN OUT IP_IO_IP_INFO *IpInfo,\r
fb115c61 1845 IN OUT VOID *IpConfigData OPTIONAL\r
cbf316f2 1846 )\r
1847{\r
1848 EFI_STATUS Status;\r
2a2e33b2 1849 IP_IO_IP_PROTOCOL Ip;\r
b45b45b2 1850 UINT8 IpVersion;\r
cbf316f2 1851 EFI_IP4_MODE_DATA Ip4ModeData;\r
fb115c61 1852 EFI_IP6_MODE_DATA Ip6ModeData;\r
cbf316f2 1853\r
6aac5e5f 1854 ASSERT (IpInfo != NULL);\r
cbf316f2 1855\r
1856 if (IpInfo->RefCnt > 1) {\r
1857 //\r
1858 // This IP instance is shared, don't reconfigure it until it has only one\r
1859 // consumer. Currently, only the tcp children cloned from their passive parent\r
fb115c61 1860 // will share the same IP. So this cases only happens while IpConfigData is NULL,\r
cbf316f2 1861 // let the last consumer clean the IP instance.\r
1862 //\r
1863 return EFI_SUCCESS;\r
1864 }\r
1865\r
fb115c61 1866 IpVersion = IpInfo->IpVersion;\r
1867 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
1868\r
cbf316f2 1869 Ip = IpInfo->Ip;\r
1870\r
fb115c61 1871 if (IpInfo->IpVersion == IP_VERSION_4) {\r
2a2e33b2 1872 Status = Ip.Ip4->Configure (Ip.Ip4, IpConfigData);\r
fb115c61 1873 } else {\r
2a2e33b2 1874 Status = Ip.Ip6->Configure (Ip.Ip6, IpConfigData);\r
fb115c61 1875 }\r
1876\r
cbf316f2 1877 if (EFI_ERROR (Status)) {\r
2b208747 1878 return Status;\r
cbf316f2 1879 }\r
1880\r
fb115c61 1881 if (IpConfigData != NULL) {\r
c167ef91 1882 if (IpInfo->IpVersion == IP_VERSION_4) {\r
cbf316f2 1883\r
fb115c61 1884 if (((EFI_IP4_CONFIG_DATA *) IpConfigData)->UseDefaultAddress) {\r
c167ef91 1885 Status = Ip.Ip4->GetModeData (\r
d1102dba
LG
1886 Ip.Ip4,\r
1887 &Ip4ModeData,\r
1888 NULL,\r
c167ef91
FS
1889 NULL\r
1890 );\r
1891 if (EFI_ERROR (Status)) {\r
1892 Ip.Ip4->Configure (Ip.Ip4, NULL);\r
2b208747 1893 return Status;\r
c167ef91 1894 }\r
cbf316f2 1895\r
35f910f0
RP
1896 IP4_COPY_ADDRESS (&((EFI_IP4_CONFIG_DATA*) IpConfigData)->StationAddress, &Ip4ModeData.ConfigData.StationAddress);\r
1897 IP4_COPY_ADDRESS (&((EFI_IP4_CONFIG_DATA*) IpConfigData)->SubnetMask, &Ip4ModeData.ConfigData.SubnetMask);\r
c167ef91 1898 }\r
cbf316f2 1899\r
fb115c61 1900 CopyMem (\r
d1102dba
LG
1901 &IpInfo->Addr.Addr,\r
1902 &((EFI_IP4_CONFIG_DATA *) IpConfigData)->StationAddress,\r
fb115c61 1903 sizeof (IP4_ADDR)\r
1904 );\r
1905 CopyMem (\r
d1102dba 1906 &IpInfo->PreMask.SubnetMask,\r
fb115c61 1907 &((EFI_IP4_CONFIG_DATA *) IpConfigData)->SubnetMask,\r
1908 sizeof (IP4_ADDR)\r
1909 );\r
1910\r
2a2e33b2 1911 Status = Ip.Ip4->Receive (\r
1912 Ip.Ip4,\r
1913 &IpInfo->DummyRcvToken.Ip4Token\r
1914 );\r
c167ef91
FS
1915 if (EFI_ERROR (Status)) {\r
1916 Ip.Ip4->Configure (Ip.Ip4, NULL);\r
1917 }\r
1918 } else {\r
1919 Status = Ip.Ip6->GetModeData (\r
1920 Ip.Ip6,\r
1921 &Ip6ModeData,\r
1922 NULL,\r
1923 NULL\r
1924 );\r
1925 if (EFI_ERROR (Status)) {\r
1926 Ip.Ip6->Configure (Ip.Ip6, NULL);\r
2b208747 1927 return Status;\r
c167ef91 1928 }\r
fb115c61 1929\r
1930 if (Ip6ModeData.IsConfigured) {\r
1931 CopyMem (\r
1932 &((EFI_IP6_CONFIG_DATA *) IpConfigData)->StationAddress,\r
1933 &Ip6ModeData.ConfigData.StationAddress,\r
1934 sizeof (EFI_IPv6_ADDRESS)\r
1935 );\r
1936\r
1937 if (Ip6ModeData.AddressList != NULL) {\r
1938 FreePool (Ip6ModeData.AddressList);\r
1939 }\r
1940\r
1941 if (Ip6ModeData.GroupTable != NULL) {\r
1942 FreePool (Ip6ModeData.GroupTable);\r
1943 }\r
1944\r
1945 if (Ip6ModeData.RouteTable != NULL) {\r
1946 FreePool (Ip6ModeData.RouteTable);\r
1947 }\r
1948\r
1949 if (Ip6ModeData.NeighborCache != NULL) {\r
1950 FreePool (Ip6ModeData.NeighborCache);\r
1951 }\r
1952\r
1953 if (Ip6ModeData.PrefixTable != NULL) {\r
1954 FreePool (Ip6ModeData.PrefixTable);\r
1955 }\r
1956\r
1957 if (Ip6ModeData.IcmpTypeList != NULL) {\r
1958 FreePool (Ip6ModeData.IcmpTypeList);\r
1959 }\r
1960\r
1961 } else {\r
1962 Status = EFI_NO_MAPPING;\r
2b208747 1963 return Status;\r
d1102dba 1964 }\r
fb115c61 1965\r
1966 CopyMem (\r
d1102dba
LG
1967 &IpInfo->Addr,\r
1968 &Ip6ModeData.ConfigData.StationAddress,\r
fb115c61 1969 sizeof (EFI_IPv6_ADDRESS)\r
1970 );\r
1971\r
2a2e33b2 1972 Status = Ip.Ip6->Receive (\r
1973 Ip.Ip6,\r
1974 &IpInfo->DummyRcvToken.Ip6Token\r
1975 );\r
fb115c61 1976 if (EFI_ERROR (Status)) {\r
2a2e33b2 1977 Ip.Ip6->Configure (Ip.Ip6, NULL);\r
fb115c61 1978 }\r
d1102dba 1979 }\r
fb115c61 1980 } else {\r
cbf316f2 1981 //\r
fb115c61 1982 // The IP instance is reset, set the stored Addr and SubnetMask to zero.\r
cbf316f2 1983 //\r
fb115c61 1984 ZeroMem (&IpInfo->Addr, sizeof (IpInfo->Addr));\r
1985 ZeroMem (&IpInfo->PreMask, sizeof (IpInfo->PreMask));\r
cbf316f2 1986 }\r
1987\r
cbf316f2 1988 return Status;\r
1989}\r
1990\r
1991\r
1992/**\r
1993 Destroy an IP instance maintained in IpIo->IpList for\r
1994 sending purpose.\r
2b208747
WF
1995\r
1996 If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
d1102dba 1997\r
e6ff63a5 1998 This function pairs with IpIoAddIp(). The IpInfo is previously created by\r
1999 IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance\r
2000 will be dstroyed if the RefCnt is zero.\r
cbf316f2 2001\r
6aac5e5f 2002 @param[in] IpIo Pointer to the IP_IO instance.\r
2003 @param[in] IpInfo Pointer to the IpInfo to be removed.\r
cbf316f2 2004\r
cbf316f2 2005**/\r
2006VOID\r
7b414b4e 2007EFIAPI\r
cbf316f2 2008IpIoRemoveIp (\r
e6ff63a5 2009 IN IP_IO *IpIo,\r
2010 IN IP_IO_IP_INFO *IpInfo\r
cbf316f2 2011 )\r
2012{\r
fb115c61 2013\r
b45b45b2 2014 UINT8 IpVersion;\r
d1102dba 2015\r
6ccfeec2
FS
2016 if (IpIo == NULL || IpInfo == NULL) {\r
2017 return;\r
2018 }\r
fb115c61 2019\r
cbf316f2 2020 ASSERT (IpInfo->RefCnt > 0);\r
2021\r
2022 NET_PUT_REF (IpInfo);\r
2023\r
2024 if (IpInfo->RefCnt > 0) {\r
2025\r
2026 return;\r
2027 }\r
2028\r
fb115c61 2029 IpVersion = IpIo->IpVersion;\r
2030\r
2031 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
2032\r
e48e37fc 2033 RemoveEntryList (&IpInfo->Entry);\r
cbf316f2 2034\r
fb115c61 2035 if (IpVersion == IP_VERSION_4){\r
2a2e33b2 2036 IpInfo->Ip.Ip4->Configure (\r
2037 IpInfo->Ip.Ip4,\r
2038 NULL\r
2039 );\r
fb115c61 2040 IpIoCloseProtocolDestroyIpChild (\r
2041 IpIo->Controller,\r
2042 IpIo->Image,\r
2043 IpInfo->ChildHandle,\r
2044 IP_VERSION_4\r
2045 );\r
2046\r
2047 gBS->CloseEvent (IpInfo->DummyRcvToken.Ip4Token.Event);\r
cbf316f2 2048\r
fb115c61 2049 } else {\r
cbf316f2 2050\r
2a2e33b2 2051 IpInfo->Ip.Ip6->Configure (\r
2052 IpInfo->Ip.Ip6,\r
2053 NULL\r
2054 );\r
cbf316f2 2055\r
fb115c61 2056 IpIoCloseProtocolDestroyIpChild (\r
2057 IpIo->Controller,\r
2058 IpIo->Image,\r
2059 IpInfo->ChildHandle,\r
2060 IP_VERSION_6\r
2061 );\r
2062\r
2063 gBS->CloseEvent (IpInfo->DummyRcvToken.Ip6Token.Event);\r
2064 }\r
2065\r
2066 FreePool (IpInfo);\r
cbf316f2 2067}\r
2068\r
2069\r
2070/**\r
2071 Find the first IP protocol maintained in IpIo whose local\r
fb115c61 2072 address is the same as Src.\r
d1102dba 2073\r
e6ff63a5 2074 This function is called when the caller needs the IpIo to send data to the\r
2075 specified Src. The IpIo was added previously by IpIoAddIp().\r
cbf316f2 2076\r
6aac5e5f 2077 @param[in, out] IpIo Pointer to the pointer of the IP_IO instance.\r
fb115c61 2078 @param[in] IpVersion The version of the IP protocol to use, either\r
2079 IPv4 or IPv6.\r
6aac5e5f 2080 @param[in] Src The local IP address.\r
cbf316f2 2081\r
2082 @return Pointer to the IP protocol can be used for sending purpose and its local\r
6ccfeec2 2083 address is the same with Src. NULL if failed.\r
cbf316f2 2084\r
2085**/\r
2086IP_IO_IP_INFO *\r
7b414b4e 2087EFIAPI\r
cbf316f2 2088IpIoFindSender (\r
fb115c61 2089 IN OUT IP_IO **IpIo,\r
b45b45b2 2090 IN UINT8 IpVersion,\r
fb115c61 2091 IN EFI_IP_ADDRESS *Src\r
cbf316f2 2092 )\r
2093{\r
e48e37fc 2094 LIST_ENTRY *IpIoEntry;\r
cbf316f2 2095 IP_IO *IpIoPtr;\r
e48e37fc 2096 LIST_ENTRY *IpInfoEntry;\r
cbf316f2 2097 IP_IO_IP_INFO *IpInfo;\r
2098\r
6ccfeec2
FS
2099 if (IpIo == NULL || Src == NULL) {\r
2100 return NULL;\r
2101 }\r
2102\r
2103 if ((IpVersion != IP_VERSION_4) && (IpVersion != IP_VERSION_6)) {\r
2104 return NULL;\r
2105 }\r
fb115c61 2106\r
cbf316f2 2107 NET_LIST_FOR_EACH (IpIoEntry, &mActiveIpIoList) {\r
2108 IpIoPtr = NET_LIST_USER_STRUCT (IpIoEntry, IP_IO, Entry);\r
2109\r
fb115c61 2110 if (((*IpIo != NULL) && (*IpIo != IpIoPtr)) || (IpIoPtr->IpVersion != IpVersion)) {\r
cbf316f2 2111 continue;\r
2112 }\r
2113\r
2114 NET_LIST_FOR_EACH (IpInfoEntry, &IpIoPtr->IpList) {\r
2115 IpInfo = NET_LIST_USER_STRUCT (IpInfoEntry, IP_IO_IP_INFO, Entry);\r
fb115c61 2116 if (IpInfo->IpVersion == IP_VERSION_4){\r
2117\r
2118 if (EFI_IP4_EQUAL (&IpInfo->Addr.v4, &Src->v4)) {\r
2119 *IpIo = IpIoPtr;\r
2120 return IpInfo;\r
2121 }\r
2122\r
2123 } else {\r
2124\r
2125 if (EFI_IP6_EQUAL (&IpInfo->Addr.v6, &Src->v6)) {\r
2126 *IpIo = IpIoPtr;\r
d1102dba 2127 return IpInfo;\r
fb115c61 2128 }\r
2b208747 2129 }\r
cbf316f2 2130 }\r
2131 }\r
2132\r
2133 //\r
2134 // No match.\r
2135 //\r
2136 return NULL;\r
2137}\r
2138\r
2139\r
2140/**\r
e6ff63a5 2141 Get the ICMP error map information.\r
d1102dba 2142\r
e6ff63a5 2143 The ErrorStatus will be returned. The IsHard and Notify are optional. If they\r
2144 are not NULL, this routine will fill them.\r
cbf316f2 2145\r
8f5e6151 2146 @param[in] IcmpError IcmpError Type.\r
fb115c61 2147 @param[in] IpVersion The version of the IP protocol to use,\r
d1102dba 2148 either IPv4 or IPv6.\r
3b1464d5 2149 @param[out] IsHard If TRUE, indicates that it is a hard error.\r
2150 @param[out] Notify If TRUE, SockError needs to be notified.\r
cbf316f2 2151\r
6dbfed92 2152 @retval EFI_UNSUPPORTED Unrecognizable ICMP error code.\r
6aac5e5f 2153 @return ICMP Error Status, such as EFI_NETWORK_UNREACHABLE.\r
cbf316f2 2154\r
2155**/\r
2156EFI_STATUS\r
7b414b4e 2157EFIAPI\r
cbf316f2 2158IpIoGetIcmpErrStatus (\r
b45b45b2 2159 IN UINT8 IcmpError,\r
2160 IN UINT8 IpVersion,\r
e6ff63a5 2161 OUT BOOLEAN *IsHard OPTIONAL,\r
2162 OUT BOOLEAN *Notify OPTIONAL\r
cbf316f2 2163 )\r
2164{\r
3cf888f5 2165 if (IpVersion == IP_VERSION_4 ) {\r
b45b45b2 2166 ASSERT (IcmpError <= ICMP_ERR_PARAMPROB);\r
687a2e5f 2167\r
3cf888f5 2168 if (IsHard != NULL) {\r
2169 *IsHard = mIcmpErrMap[IcmpError].IsHard;\r
2170 }\r
687a2e5f 2171\r
3cf888f5 2172 if (Notify != NULL) {\r
2173 *Notify = mIcmpErrMap[IcmpError].Notify;\r
2174 }\r
2175\r
2176 switch (IcmpError) {\r
2177 case ICMP_ERR_UNREACH_NET:\r
2178 return EFI_NETWORK_UNREACHABLE;\r
2179\r
2180 case ICMP_ERR_TIMXCEED_INTRANS:\r
2181 case ICMP_ERR_TIMXCEED_REASS:\r
2182 case ICMP_ERR_UNREACH_HOST:\r
2183 return EFI_HOST_UNREACHABLE;\r
2184\r
2185 case ICMP_ERR_UNREACH_PROTOCOL:\r
2186 return EFI_PROTOCOL_UNREACHABLE;\r
2187\r
2188 case ICMP_ERR_UNREACH_PORT:\r
2189 return EFI_PORT_UNREACHABLE;\r
2190\r
2191 case ICMP_ERR_MSGSIZE:\r
2192 case ICMP_ERR_UNREACH_SRCFAIL:\r
2193 case ICMP_ERR_QUENCH:\r
2194 case ICMP_ERR_PARAMPROB:\r
2195 return EFI_ICMP_ERROR;\r
2196\r
2197 default:\r
2198 ASSERT (FALSE);\r
2199 return EFI_UNSUPPORTED;\r
2200 }\r
687a2e5f 2201\r
fb115c61 2202 } else if (IpVersion == IP_VERSION_6) {\r
2203\r
b45b45b2 2204 ASSERT (IcmpError <= ICMP6_ERR_PARAMPROB_IPV6OPTION);\r
687a2e5f 2205\r
fb115c61 2206 if (IsHard != NULL) {\r
2207 *IsHard = mIcmp6ErrMap[IcmpError].IsHard;\r
2208 }\r
2209\r
2210 if (Notify != NULL) {\r
2211 *Notify = mIcmp6ErrMap[IcmpError].Notify;\r
2212 }\r
3cf888f5 2213\r
2214 switch (IcmpError) {\r
2215 case ICMP6_ERR_UNREACH_NET:\r
2216 return EFI_NETWORK_UNREACHABLE;\r
2217\r
2218 case ICMP6_ERR_UNREACH_HOST:\r
2219 case ICMP6_ERR_TIMXCEED_HOPLIMIT:\r
d1102dba 2220 case ICMP6_ERR_TIMXCEED_REASS:\r
3cf888f5 2221 return EFI_HOST_UNREACHABLE;\r
2222\r
2223 case ICMP6_ERR_UNREACH_PROTOCOL:\r
2224 return EFI_PROTOCOL_UNREACHABLE;\r
d1102dba 2225\r
3cf888f5 2226 case ICMP6_ERR_UNREACH_PORT:\r
2227 return EFI_PORT_UNREACHABLE;\r
2228\r
2229 case ICMP6_ERR_PACKAGE_TOOBIG:\r
2230 case ICMP6_ERR_PARAMPROB_HEADER:\r
2231 case ICMP6_ERR_PARAMPROB_NEXHEADER:\r
2232 case ICMP6_ERR_PARAMPROB_IPV6OPTION:\r
2233 return EFI_ICMP_ERROR;\r
2234\r
2235 default:\r
2236 ASSERT (FALSE);\r
2237 return EFI_UNSUPPORTED;\r
2238 }\r
fb115c61 2239\r
2240 } else {\r
2241 //\r
2242 // Should never be here\r
2243 //\r
2244 ASSERT (FALSE);\r
2245 return EFI_UNSUPPORTED;\r
2246 }\r
2247}\r
cbf316f2 2248\r
cbf316f2 2249\r
fb115c61 2250/**\r
2251 Refresh the remote peer's Neighbor Cache entries.\r
2252\r
2253 This function is called when the caller needs the IpIo to refresh the existing\r
d1102dba
LG
2254 IPv6 neighbor cache entries since the neighbor is considered reachable by the\r
2255 node has recently received a confirmation that packets sent recently to the\r
2256 neighbor were received by its IP layer.\r
fb115c61 2257\r
2258 @param[in] IpIo Pointer to an IP_IO instance\r
2259 @param[in] Neighbor The IP address of the neighbor\r
2260 @param[in] Timeout Time in 100-ns units that this entry will\r
d1102dba
LG
2261 remain in the neighbor cache. A value of\r
2262 zero means that the entry is permanent.\r
2263 A value of non-zero means that the entry is\r
fb115c61 2264 dynamic and will be deleted after Timeout.\r
2265\r
2266 @retval EFI_SUCCESS The operation is completed successfully.\r
2267 @retval EFI_NOT_STARTED The IpIo is not configured.\r
2268 @retval EFI_INVALID_PARAMETER Neighbor Address is invalid.\r
d1102dba
LG
2269 @retval EFI_NOT_FOUND The neighbor cache entry is not in the\r
2270 neighbor table.\r
6dbfed92 2271 @retval EFI_UNSUPPORTED IP version is IPv4, which doesn't support neighbor cache refresh.\r
fb115c61 2272 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
cbf316f2 2273\r
fb115c61 2274**/\r
2275EFI_STATUS\r
2b208747 2276EFIAPI\r
fb115c61 2277IpIoRefreshNeighbor (\r
2278 IN IP_IO *IpIo,\r
2279 IN EFI_IP_ADDRESS *Neighbor,\r
d1102dba 2280 IN UINT32 Timeout\r
fb115c61 2281 )\r
2282{\r
2283 EFI_IP6_PROTOCOL *Ip;\r
2284\r
6dbfed92 2285 if (!IpIo->IsConfigured) {\r
fb115c61 2286 return EFI_NOT_STARTED;\r
cbf316f2 2287 }\r
2288\r
6dbfed92
FS
2289 if (IpIo->IpVersion != IP_VERSION_6) {\r
2290 return EFI_UNSUPPORTED;\r
2291 }\r
2292\r
2a2e33b2 2293 Ip = IpIo->Ip.Ip6;\r
fb115c61 2294\r
2295 return Ip->Neighbors (Ip, FALSE, &Neighbor->v6, NULL, Timeout, TRUE);\r
cbf316f2 2296}\r
2297\r