]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.c
MdeModulePkg/IpIoLib: Check the input parameters before use them.
[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
8569a87e 5Copyright (c) 2005 - 2017, 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
81 {TRUE, TRUE}, // ICMP6_ERR_UNREACH_PORT \r
82 {TRUE, TRUE}, // ICMP6_ERR_PACKAGE_TOOBIG\r
83 {FALSE, TRUE}, // ICMP6_ERR_TIMXCEED_HOPLIMIT\r
84 {FALSE, TRUE}, // ICMP6_ERR_TIMXCEED_REASS\r
85 {FALSE, TRUE}, // ICMP6_ERR_PARAMPROB_HEADER \r
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
fb115c61 261 This function handles ICMPv4 packets. It is the worker function of \r
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
6ccfeec2
FS
286 \r
287 ASSERT (IpIo != NULL);\r
288 ASSERT (Pkt != NULL);\r
289 ASSERT (Session != NULL);\r
fb115c61 290 ASSERT (IpIo->IpVersion == IP_VERSION_4);\r
6ccfeec2 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
298 \r
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
c167ef91
FS
390 \r
391 //\r
392 // If the input packet has invalid format, and TrimBytes is larger than \r
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
fb115c61 399 return EFI_SUCCESS; \r
400}\r
401\r
402/**\r
403 This function handles ICMPv6 packets. It is the worker function of \r
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
450 // \r
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
509 } \r
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
520 \r
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
558 \r
559 NetbufTrim (Pkt, TrimBytes, TRUE);\r
560\r
c167ef91
FS
561 //\r
562 // If the input packet has invalid format, and TrimBytes is larger than \r
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
637 @return Pointer to the data structure created to wrap the packet. If NULL,\r
6aac5e5f 638 @return resource limit occurred.\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
fb115c61 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
703 // Build a fragment table to contain the fragments in the packet. \r
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
760 \r
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
e6ff63a5 807 \r
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
cbf316f2 1042 if (((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) || (NULL == RxData)) {\r
1043 //\r
6aac5e5f 1044 // @bug Only process the normal packets and the icmp error packets, if RxData is NULL\r
1045 // @bug with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although\r
1046 // @bug this should be a bug of the low layer (IP).\r
cbf316f2 1047 //\r
1048 goto Resume;\r
1049 }\r
1050\r
1051 if (NULL == IpIo->PktRcvdNotify) {\r
1052 goto CleanUp;\r
1053 }\r
1054\r
fb115c61 1055 if (IpIo->IpVersion == IP_VERSION_4) {\r
6ccfeec2 1056 ASSERT (RxData->Ip4RxData.Header != NULL);\r
dd29d8b3
FS
1057 if (IP4_IS_LOCAL_BROADCAST (EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress))) {\r
1058 //\r
1059 // The source address is a broadcast address, discard it.\r
1060 //\r
1061 goto CleanUp;\r
1062 }\r
fb115c61 1063 if ((EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress) != 0) &&\r
01b5ac88
FS
1064 (IpIo->SubnetMask != 0) &&\r
1065 IP4_NET_EQUAL (IpIo->StationIp, EFI_NTOHL (((EFI_IP4_RECEIVE_DATA *) RxData)->Header->SourceAddress), IpIo->SubnetMask) &&\r
1066 !NetIp4IsUnicast (EFI_NTOHL (((EFI_IP4_RECEIVE_DATA *) RxData)->Header->SourceAddress), IpIo->SubnetMask)) {\r
1b31acb6
FS
1067 //\r
1068 // The source address is not zero and it's not a unicast IP address, discard it.\r
1069 //\r
1070 goto CleanUp;\r
1071 }\r
1072\r
1073 if (RxData->Ip4RxData.DataLength == 0) {\r
1074 //\r
1075 // Discard zero length data payload packet.\r
1076 //\r
1077 goto CleanUp;\r
1078 }\r
1079\r
6ccfeec2
FS
1080 //\r
1081 // The fragment should always be valid for non-zero length packet.\r
1082 //\r
1083 ASSERT (RxData->Ip4RxData.FragmentCount != 0);\r
1084\r
cbf316f2 1085 //\r
1b31acb6 1086 // Create a netbuffer representing IPv4 packet\r
cbf316f2 1087 //\r
1b31acb6
FS
1088 Pkt = NetbufFromExt (\r
1089 (NET_FRAGMENT *) RxData->Ip4RxData.FragmentTable,\r
1090 RxData->Ip4RxData.FragmentCount,\r
1091 0,\r
1092 0,\r
1093 IpIoExtFree,\r
1094 RxData->Ip4RxData.RecycleSignal\r
1095 );\r
1096 if (NULL == Pkt) {\r
1097 goto CleanUp;\r
1098 }\r
cbf316f2 1099\r
1b31acb6
FS
1100 //\r
1101 // Create a net session\r
1102 //\r
1103 Session.Source.Addr[0] = EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress);\r
1104 Session.Dest.Addr[0] = EFI_IP4 (RxData->Ip4RxData.Header->DestinationAddress);\r
1105 Session.IpHdr.Ip4Hdr = RxData->Ip4RxData.Header;\r
1106 Session.IpHdrLen = RxData->Ip4RxData.HeaderLength;\r
1107 Session.IpVersion = IP_VERSION_4;\r
fb115c61 1108 } else {\r
6ccfeec2 1109 ASSERT (RxData->Ip6RxData.Header != NULL);\r
f6b7393c 1110 if (!NetIp6IsValidUnicast(&RxData->Ip6RxData.Header->SourceAddress)) {\r
fb115c61 1111 goto CleanUp;\r
1112 }\r
1113 \r
1b31acb6
FS
1114 if (RxData->Ip6RxData.DataLength == 0) {\r
1115 //\r
1116 // Discard zero length data payload packet.\r
1117 //\r
1118 goto CleanUp;\r
1119 }\r
1120 \r
6ccfeec2
FS
1121 //\r
1122 // The fragment should always be valid for non-zero length packet.\r
1123 //\r
1124 ASSERT (RxData->Ip6RxData.FragmentCount != 0);\r
1125 \r
fb115c61 1126 //\r
1127 // Create a netbuffer representing IPv6 packet\r
1128 //\r
1129 Pkt = NetbufFromExt (\r
1130 (NET_FRAGMENT *) RxData->Ip6RxData.FragmentTable,\r
1131 RxData->Ip6RxData.FragmentCount,\r
1132 0,\r
1133 0,\r
1134 IpIoExtFree,\r
1135 RxData->Ip6RxData.RecycleSignal\r
1136 );\r
1137 if (NULL == Pkt) {\r
1138 goto CleanUp;\r
1139 }\r
1140\r
1141 //\r
1142 // Create a net session\r
1143 //\r
1144 CopyMem (\r
1145 &Session.Source, \r
1146 &RxData->Ip6RxData.Header->SourceAddress,\r
1147 sizeof(EFI_IPv6_ADDRESS)\r
1148 );\r
1149 CopyMem (\r
1150 &Session.Dest, \r
1151 &RxData->Ip6RxData.Header->DestinationAddress, \r
1152 sizeof(EFI_IPv6_ADDRESS)\r
1153 );\r
1154 Session.IpHdr.Ip6Hdr = RxData->Ip6RxData.Header;\r
a09ee46d 1155 Session.IpHdrLen = RxData->Ip6RxData.HeaderLength;\r
fb115c61 1156 Session.IpVersion = IP_VERSION_6;\r
1157 } \r
cbf316f2 1158\r
1159 if (EFI_SUCCESS == Status) {\r
1160\r
b45b45b2 1161 IpIo->PktRcvdNotify (EFI_SUCCESS, 0, &Session, Pkt, IpIo->RcvdContext);\r
cbf316f2 1162 } else {\r
1163 //\r
1164 // Status is EFI_ICMP_ERROR\r
1165 //\r
1166 Status = IpIoIcmpHandler (IpIo, Pkt, &Session);\r
1167 if (EFI_ERROR (Status)) {\r
1168 NetbufFree (Pkt);\r
1169 }\r
1170 }\r
1171\r
1172 goto Resume;\r
1173\r
1174CleanUp:\r
fb115c61 1175\r
1176 if (IpIo->IpVersion == IP_VERSION_4){\r
1177 gBS->SignalEvent (RxData->Ip4RxData.RecycleSignal);\r
1178 } else {\r
1179 gBS->SignalEvent (RxData->Ip6RxData.RecycleSignal); \r
1180 }\r
cbf316f2 1181\r
1182Resume:\r
cbf316f2 1183\r
fb115c61 1184 if (IpIo->IpVersion == IP_VERSION_4){\r
2a2e33b2 1185 IpIo->Ip.Ip4->Receive (IpIo->Ip.Ip4, &(IpIo->RcvToken.Ip4Token));\r
fb115c61 1186 } else {\r
2a2e33b2 1187 IpIo->Ip.Ip6->Receive (IpIo->Ip.Ip6, &(IpIo->RcvToken.Ip6Token));\r
fb115c61 1188 }\r
1189}\r
cbf316f2 1190\r
36ee91ca 1191/**\r
6aac5e5f 1192 This function add IpIoListenHandlerDpc to the end of the DPC queue.\r
36ee91ca 1193\r
6aac5e5f 1194 @param[in] Event The event signaled.\r
1195 @param[in] Context The context passed in by the event notifier.\r
36ee91ca 1196\r
1197**/\r
36ee91ca 1198VOID\r
1199EFIAPI\r
1200IpIoListenHandler (\r
1201 IN EFI_EVENT Event,\r
1202 IN VOID *Context\r
1203 )\r
1204{\r
1205 //\r
1206 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK\r
1207 //\r
d8d26fb2 1208 QueueDpc (TPL_CALLBACK, IpIoListenHandlerDpc, Context);\r
36ee91ca 1209}\r
1210\r
1211\r
cbf316f2 1212/**\r
1213 Create a new IP_IO instance.\r
e6ff63a5 1214 \r
fb115c61 1215 This function uses IP4/IP6 service binding protocol in Controller to create\r
1216 an IP4/IP6 child (aka IP4/IP6 instance).\r
cbf316f2 1217\r
6aac5e5f 1218 @param[in] Image The image handle of the driver or application that\r
e6ff63a5 1219 consumes IP_IO.\r
fb115c61 1220 @param[in] Controller The controller handle that has IP4 or IP6 service\r
1221 binding protocol installed.\r
1222 @param[in] IpVersion The version of the IP protocol to use, either\r
1223 IPv4 or IPv6. \r
cbf316f2 1224\r
e6ff63a5 1225 @return Pointer to a newly created IP_IO instance, or NULL if failed.\r
cbf316f2 1226\r
1227**/\r
1228IP_IO *\r
7b414b4e 1229EFIAPI\r
cbf316f2 1230IpIoCreate (\r
1231 IN EFI_HANDLE Image,\r
fb115c61 1232 IN EFI_HANDLE Controller,\r
b45b45b2 1233 IN UINT8 IpVersion\r
cbf316f2 1234 )\r
1235{\r
1236 EFI_STATUS Status;\r
1237 IP_IO *IpIo;\r
fb115c61 1238 EFI_EVENT Event;\r
1239\r
1240 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
cbf316f2 1241\r
e48e37fc 1242 IpIo = AllocateZeroPool (sizeof (IP_IO));\r
cbf316f2 1243 if (NULL == IpIo) {\r
1244 return NULL;\r
1245 }\r
1246\r
e48e37fc 1247 InitializeListHead (&(IpIo->PendingSndList));\r
1248 InitializeListHead (&(IpIo->IpList));\r
cbf316f2 1249 IpIo->Controller = Controller;\r
1250 IpIo->Image = Image;\r
fb115c61 1251 IpIo->IpVersion = IpVersion;\r
1252 Event = NULL;\r
cbf316f2 1253\r
1254 Status = gBS->CreateEvent (\r
1255 EVT_NOTIFY_SIGNAL,\r
e48e37fc 1256 TPL_NOTIFY,\r
cbf316f2 1257 IpIoListenHandler,\r
1258 IpIo,\r
fb115c61 1259 &Event\r
cbf316f2 1260 );\r
1261 if (EFI_ERROR (Status)) {\r
1262 goto ReleaseIpIo;\r
1263 }\r
1264\r
fb115c61 1265 if (IpVersion == IP_VERSION_4) {\r
1266 IpIo->RcvToken.Ip4Token.Event = Event;\r
1267 } else {\r
1268 IpIo->RcvToken.Ip6Token.Event = Event;\r
1269 }\r
1270\r
cbf316f2 1271 //\r
1272 // Create an IP child and open IP protocol\r
1273 //\r
1274 Status = IpIoCreateIpChildOpenProtocol (\r
1275 Controller,\r
1276 Image,\r
1277 &IpIo->ChildHandle,\r
fb115c61 1278 IpVersion, \r
cbf316f2 1279 (VOID **)&(IpIo->Ip)\r
1280 );\r
1281 if (EFI_ERROR (Status)) {\r
1282 goto ReleaseIpIo;\r
1283 }\r
1284\r
1285 return IpIo;\r
1286\r
1287ReleaseIpIo:\r
1288\r
fb115c61 1289 if (Event != NULL) {\r
1290 gBS->CloseEvent (Event);\r
cbf316f2 1291 }\r
1292\r
e48e37fc 1293 gBS->FreePool (IpIo);\r
cbf316f2 1294\r
1295 return NULL;\r
1296}\r
1297\r
1298\r
1299/**\r
1300 Open an IP_IO instance for use.\r
e6ff63a5 1301 \r
1302 This function is called after IpIoCreate(). It is used for configuring the IP\r
1303 instance and register the callbacks and their context data for sending and\r
1304 receiving IP packets.\r
cbf316f2 1305\r
6aac5e5f 1306 @param[in, out] IpIo Pointer to an IP_IO instance that needs\r
1307 to open.\r
1308 @param[in] OpenData The configuration data and callbacks for\r
1309 the IP_IO instance.\r
cbf316f2 1310\r
6ccfeec2
FS
1311 @retval EFI_SUCCESS The IP_IO instance opened with OpenData\r
1312 successfully.\r
1313 @retval EFI_ACCESS_DENIED The IP_IO instance is configured, avoid to \r
1314 reopen it.\r
1315 @retval EFI_UNSUPPORTED IPv4 RawData mode is no supported.\r
1316 @retval EFI_INVALID_PARAMETER Invalid input parameter.\r
1317 @retval Others Error condition occurred.\r
cbf316f2 1318\r
1319**/\r
1320EFI_STATUS\r
7b414b4e 1321EFIAPI\r
cbf316f2 1322IpIoOpen (\r
6aac5e5f 1323 IN OUT IP_IO *IpIo,\r
1324 IN IP_IO_OPEN_DATA *OpenData\r
cbf316f2 1325 )\r
1326{\r
1327 EFI_STATUS Status;\r
b45b45b2 1328 UINT8 IpVersion;\r
cbf316f2 1329\r
6ccfeec2
FS
1330 if (IpIo == NULL || OpenData == NULL) {\r
1331 return EFI_INVALID_PARAMETER;\r
1332 }\r
1333\r
cbf316f2 1334 if (IpIo->IsConfigured) {\r
1335 return EFI_ACCESS_DENIED;\r
1336 }\r
1337\r
fb115c61 1338 IpVersion = IpIo->IpVersion;\r
1339\r
1340 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
1341\r
cbf316f2 1342 //\r
1343 // configure ip\r
1344 //\r
fb115c61 1345 if (IpVersion == IP_VERSION_4){\r
1b31acb6
FS
1346 //\r
1347 // RawData mode is no supported.\r
1348 //\r
1349 ASSERT (!OpenData->IpConfigData.Ip4CfgData.RawData);\r
1350 if (OpenData->IpConfigData.Ip4CfgData.RawData) {\r
1351 return EFI_UNSUPPORTED;\r
1352 }\r
01b5ac88
FS
1353\r
1354 if (!OpenData->IpConfigData.Ip4CfgData.UseDefaultAddress) {\r
1355 IpIo->StationIp = EFI_NTOHL (OpenData->IpConfigData.Ip4CfgData.StationAddress);\r
1356 IpIo->SubnetMask = EFI_NTOHL (OpenData->IpConfigData.Ip4CfgData.SubnetMask);\r
1357 }\r
1b31acb6 1358 \r
2a2e33b2 1359 Status = IpIo->Ip.Ip4->Configure (\r
1360 IpIo->Ip.Ip4,\r
1361 &OpenData->IpConfigData.Ip4CfgData\r
1362 );\r
fb115c61 1363 } else {\r
1364\r
2a2e33b2 1365 Status = IpIo->Ip.Ip6->Configure (\r
1366 IpIo->Ip.Ip6, \r
1367 &OpenData->IpConfigData.Ip6CfgData\r
1368 );\r
fb115c61 1369 }\r
1370\r
cbf316f2 1371 if (EFI_ERROR (Status)) {\r
1372 return Status;\r
1373 }\r
1374\r
1375 //\r
6aac5e5f 1376 // @bug To delete the default route entry in this Ip, if it is:\r
1377 // @bug (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified\r
1378 // @bug its code\r
cbf316f2 1379 //\r
fb115c61 1380 if (IpVersion == IP_VERSION_4){\r
2a2e33b2 1381 Status = IpIo->Ip.Ip4->Routes (\r
1382 IpIo->Ip.Ip4,\r
1383 TRUE,\r
1384 &mZeroIp4Addr,\r
1385 &mZeroIp4Addr,\r
1386 &mZeroIp4Addr\r
1387 );\r
fb115c61 1388\r
1389 if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {\r
1390 return Status;\r
1391 }\r
cbf316f2 1392 }\r
1393\r
1394 IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;\r
1395 IpIo->PktSentNotify = OpenData->PktSentNotify;\r
1396\r
1397 IpIo->RcvdContext = OpenData->RcvdContext;\r
1398 IpIo->SndContext = OpenData->SndContext;\r
1399\r
fb115c61 1400 if (IpVersion == IP_VERSION_4){\r
1401 IpIo->Protocol = OpenData->IpConfigData.Ip4CfgData.DefaultProtocol;\r
cbf316f2 1402\r
fb115c61 1403 //\r
1404 // start to listen incoming packet\r
1405 //\r
2a2e33b2 1406 Status = IpIo->Ip.Ip4->Receive (\r
1407 IpIo->Ip.Ip4,\r
1408 &(IpIo->RcvToken.Ip4Token)\r
1409 );\r
fb115c61 1410 if (EFI_ERROR (Status)) {\r
2a2e33b2 1411 IpIo->Ip.Ip4->Configure (IpIo->Ip.Ip4, NULL);\r
fb115c61 1412 goto ErrorExit;\r
1413 }\r
1414\r
1415 } else {\r
1416\r
1417 IpIo->Protocol = OpenData->IpConfigData.Ip6CfgData.DefaultProtocol;\r
2a2e33b2 1418 Status = IpIo->Ip.Ip6->Receive (\r
1419 IpIo->Ip.Ip6,\r
1420 &(IpIo->RcvToken.Ip6Token)\r
1421 );\r
fb115c61 1422 if (EFI_ERROR (Status)) {\r
2a2e33b2 1423 IpIo->Ip.Ip6->Configure (IpIo->Ip.Ip6, NULL);\r
fb115c61 1424 goto ErrorExit;\r
1425 }\r
cbf316f2 1426 }\r
1427\r
1428 IpIo->IsConfigured = TRUE;\r
e48e37fc 1429 InsertTailList (&mActiveIpIoList, &IpIo->Entry);\r
cbf316f2 1430\r
1431ErrorExit:\r
1432\r
1433 return Status;\r
1434}\r
1435\r
1436\r
1437/**\r
1438 Stop an IP_IO instance.\r
e6ff63a5 1439 \r
1440 This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all\r
1441 the pending send/receive tokens will be canceled.\r
cbf316f2 1442\r
6aac5e5f 1443 @param[in, out] IpIo Pointer to the IP_IO instance that needs to stop.\r
cbf316f2 1444\r
6ccfeec2
FS
1445 @retval EFI_SUCCESS The IP_IO instance stopped successfully.\r
1446 @retval EFI_INVALID_PARAMETER Invalid input parameter.\r
1447 @retval Others Error condition occurred.\r
cbf316f2 1448\r
1449**/\r
1450EFI_STATUS\r
e6ff63a5 1451EFIAPI\r
cbf316f2 1452IpIoStop (\r
6aac5e5f 1453 IN OUT IP_IO *IpIo\r
cbf316f2 1454 )\r
1455{\r
1456 EFI_STATUS Status;\r
cbf316f2 1457 IP_IO_IP_INFO *IpInfo;\r
b45b45b2 1458 UINT8 IpVersion;\r
cbf316f2 1459\r
6ccfeec2
FS
1460 if (IpIo == NULL) {\r
1461 return EFI_INVALID_PARAMETER;\r
1462 }\r
1463\r
cbf316f2 1464 if (!IpIo->IsConfigured) {\r
1465 return EFI_SUCCESS;\r
1466 }\r
1467\r
fb115c61 1468 IpVersion = IpIo->IpVersion;\r
1469\r
1470 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
1471\r
cbf316f2 1472 //\r
1473 // Remove the IpIo from the active IpIo list.\r
1474 //\r
e48e37fc 1475 RemoveEntryList (&IpIo->Entry);\r
cbf316f2 1476\r
cbf316f2 1477 //\r
1478 // Configure NULL Ip\r
1479 //\r
fb115c61 1480 if (IpVersion == IP_VERSION_4) {\r
2a2e33b2 1481 Status = IpIo->Ip.Ip4->Configure (IpIo->Ip.Ip4, NULL);\r
fb115c61 1482 } else {\r
2a2e33b2 1483 Status = IpIo->Ip.Ip6->Configure (IpIo->Ip.Ip6, NULL);\r
fb115c61 1484 }\r
cbf316f2 1485 if (EFI_ERROR (Status)) {\r
1486 return Status;\r
1487 }\r
1488\r
1489 IpIo->IsConfigured = FALSE;\r
1490\r
1491 //\r
1492 // Detroy the Ip List used by IpIo\r
1493 //\r
34edf2ae 1494\r
e48e37fc 1495 while (!IsListEmpty (&(IpIo->IpList))) {\r
cbf316f2 1496 IpInfo = NET_LIST_HEAD (&(IpIo->IpList), IP_IO_IP_INFO, Entry);\r
1497\r
1498 IpIoRemoveIp (IpIo, IpInfo);\r
1499 }\r
1500\r
1501 //\r
3b28e744 1502 // All pending send tokens should be flushed by resetting the IP instances.\r
cbf316f2 1503 //\r
e48e37fc 1504 ASSERT (IsListEmpty (&IpIo->PendingSndList));\r
cbf316f2 1505\r
1506 //\r
1507 // Close the receive event.\r
1508 //\r
fb115c61 1509 if (IpVersion == IP_VERSION_4){\r
1510 gBS->CloseEvent (IpIo->RcvToken.Ip4Token.Event);\r
1511 } else {\r
1512 gBS->CloseEvent (IpIo->RcvToken.Ip6Token.Event);\r
1513 }\r
cbf316f2 1514\r
1515 return EFI_SUCCESS;\r
1516}\r
1517\r
1518\r
1519/**\r
1520 Destroy an IP_IO instance.\r
e6ff63a5 1521 \r
1522 This function is paired with IpIoCreate(). The IP_IO will be closed first.\r
8f5e6151 1523 Resource will be freed afterwards. See IpIoCloseProtocolDestroyIpChild().\r
cbf316f2 1524\r
6aac5e5f 1525 @param[in, out] IpIo Pointer to the IP_IO instance that needs to be\r
e6ff63a5 1526 destroyed.\r
cbf316f2 1527\r
6aac5e5f 1528 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.\r
1529 @retval Others Error condition occurred.\r
cbf316f2 1530\r
1531**/\r
1532EFI_STATUS\r
7b414b4e 1533EFIAPI\r
cbf316f2 1534IpIoDestroy (\r
6aac5e5f 1535 IN OUT IP_IO *IpIo\r
cbf316f2 1536 )\r
1537{\r
6dbfed92
FS
1538 EFI_STATUS Status;\r
1539 \r
cbf316f2 1540 //\r
1541 // Stop the IpIo.\r
1542 //\r
6dbfed92
FS
1543 Status = IpIoStop (IpIo);\r
1544 if (EFI_ERROR (Status)) {\r
1545 return Status;\r
1546 }\r
cbf316f2 1547\r
1548 //\r
1549 // Close the IP protocol and destroy the child.\r
1550 //\r
6dbfed92
FS
1551 Status = IpIoCloseProtocolDestroyIpChild (\r
1552 IpIo->Controller,\r
1553 IpIo->Image,\r
1554 IpIo->ChildHandle,\r
1555 IpIo->IpVersion\r
1556 );\r
1557 if (EFI_ERROR (Status)) {\r
1558 return Status;\r
1559 }\r
cbf316f2 1560\r
e48e37fc 1561 gBS->FreePool (IpIo);\r
cbf316f2 1562\r
1563 return EFI_SUCCESS;\r
1564}\r
1565\r
1566\r
1567/**\r
1568 Send out an IP packet.\r
e6ff63a5 1569 \r
1570 This function is called after IpIoOpen(). The data to be sent are wrapped in\r
1571 Pkt. The IP instance wrapped in IpIo is used for sending by default but can be\r
1572 overriden by Sender. Other sending configs, like source address and gateway\r
1573 address etc., are specified in OverrideData.\r
cbf316f2 1574\r
6aac5e5f 1575 @param[in, out] IpIo Pointer to an IP_IO instance used for sending IP\r
1576 packet.\r
1577 @param[in, out] Pkt Pointer to the IP packet to be sent.\r
1578 @param[in] Sender The IP protocol instance used for sending.\r
8f5e6151 1579 @param[in] Context Optional context data.\r
1580 @param[in] NotifyData Optional notify data.\r
6aac5e5f 1581 @param[in] Dest The destination IP address to send this packet to.\r
8569a87e 1582 This parameter is optional when using IPv6.\r
6aac5e5f 1583 @param[in] OverrideData The data to override some configuration of the IP\r
1584 instance used for sending.\r
cbf316f2 1585\r
6aac5e5f 1586 @retval EFI_SUCCESS The operation is completed successfully.\r
8569a87e 1587 @retval EFI_INVALID_PARAMETER The input parameter is not correct.\r
6aac5e5f 1588 @retval EFI_NOT_STARTED The IpIo is not configured.\r
1589 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
6dbfed92 1590 @retval Others Error condition occurred.\r
cbf316f2 1591\r
1592**/\r
1593EFI_STATUS\r
7b414b4e 1594EFIAPI\r
cbf316f2 1595IpIoSend (\r
6aac5e5f 1596 IN OUT IP_IO *IpIo,\r
1597 IN OUT NET_BUF *Pkt,\r
1598 IN IP_IO_IP_INFO *Sender OPTIONAL,\r
1599 IN VOID *Context OPTIONAL,\r
1600 IN VOID *NotifyData OPTIONAL,\r
c167ef91 1601 IN EFI_IP_ADDRESS *Dest OPTIONAL,\r
6aac5e5f 1602 IN IP_IO_OVERRIDE *OverrideData OPTIONAL\r
cbf316f2 1603 )\r
1604{\r
1605 EFI_STATUS Status;\r
2a2e33b2 1606 IP_IO_IP_PROTOCOL Ip;\r
cbf316f2 1607 IP_IO_SEND_ENTRY *SndEntry;\r
1608\r
8569a87e
FS
1609 if ((IpIo == NULL) || (Pkt == NULL)) {\r
1610 return EFI_INVALID_PARAMETER;\r
1611 }\r
1612\r
1613 if ((IpIo->IpVersion == IP_VERSION_4) && (Dest == NULL)) {\r
1614 return EFI_INVALID_PARAMETER;\r
1615 }\r
fb115c61 1616\r
cbf316f2 1617 if (!IpIo->IsConfigured) {\r
1618 return EFI_NOT_STARTED;\r
1619 }\r
1620\r
1621 Ip = (NULL == Sender) ? IpIo->Ip : Sender->Ip;\r
1622\r
1623 //\r
1624 // create a new SndEntry\r
1625 //\r
1626 SndEntry = IpIoCreateSndEntry (IpIo, Pkt, Ip, Context, NotifyData, Dest, OverrideData);\r
1627 if (NULL == SndEntry) {\r
1628 return EFI_OUT_OF_RESOURCES;\r
1629 }\r
1630\r
1631 //\r
1632 // Send this Packet\r
1633 //\r
fb115c61 1634 if (IpIo->IpVersion == IP_VERSION_4){\r
2a2e33b2 1635 Status = Ip.Ip4->Transmit (\r
1636 Ip.Ip4,\r
1637 &SndEntry->SndToken.Ip4Token\r
1638 );\r
fb115c61 1639 } else {\r
2a2e33b2 1640 Status = Ip.Ip6->Transmit (\r
1641 Ip.Ip6,\r
1642 &SndEntry->SndToken.Ip6Token\r
1643 );\r
fb115c61 1644 }\r
1645\r
cbf316f2 1646 if (EFI_ERROR (Status)) {\r
1647 IpIoDestroySndEntry (SndEntry);\r
1648 }\r
1649\r
1650 return Status;\r
1651}\r
1652\r
1653\r
1654/**\r
1655 Cancel the IP transmit token which wraps this Packet.\r
1656\r
6aac5e5f 1657 @param[in] IpIo Pointer to the IP_IO instance.\r
1658 @param[in] Packet Pointer to the packet of NET_BUF to cancel.\r
cbf316f2 1659\r
1660**/\r
1661VOID\r
7b414b4e 1662EFIAPI\r
cbf316f2 1663IpIoCancelTxToken (\r
1664 IN IP_IO *IpIo,\r
1665 IN VOID *Packet\r
1666 )\r
1667{\r
e48e37fc 1668 LIST_ENTRY *Node;\r
cbf316f2 1669 IP_IO_SEND_ENTRY *SndEntry;\r
2a2e33b2 1670 IP_IO_IP_PROTOCOL Ip;\r
cbf316f2 1671\r
fb115c61 1672 ASSERT ((IpIo != NULL) && (Packet != NULL));\r
cbf316f2 1673\r
1674 NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {\r
1675\r
1676 SndEntry = NET_LIST_USER_STRUCT (Node, IP_IO_SEND_ENTRY, Entry);\r
1677\r
1678 if (SndEntry->Pkt == Packet) {\r
1679\r
1680 Ip = SndEntry->Ip;\r
fb115c61 1681\r
1682 if (IpIo->IpVersion == IP_VERSION_4) {\r
2a2e33b2 1683 Ip.Ip4->Cancel (\r
1684 Ip.Ip4,\r
1685 &SndEntry->SndToken.Ip4Token\r
1686 );\r
fb115c61 1687 } else {\r
2a2e33b2 1688 Ip.Ip6->Cancel (\r
1689 Ip.Ip6,\r
1690 &SndEntry->SndToken.Ip6Token\r
1691 );\r
fb115c61 1692 }\r
cbf316f2 1693\r
cbf316f2 1694 break;\r
1695 }\r
1696 }\r
1697\r
1698}\r
1699\r
1700\r
1701/**\r
1702 Add a new IP instance for sending data.\r
e6ff63a5 1703 \r
1704 The function is used to add the IP_IO to the IP_IO sending list. The caller\r
1705 can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send\r
1706 data.\r
cbf316f2 1707\r
6aac5e5f 1708 @param[in, out] IpIo Pointer to a IP_IO instance to add a new IP\r
1709 instance for sending purpose.\r
cbf316f2 1710\r
e6ff63a5 1711 @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.\r
cbf316f2 1712\r
1713**/\r
1714IP_IO_IP_INFO *\r
7b414b4e 1715EFIAPI\r
cbf316f2 1716IpIoAddIp (\r
6aac5e5f 1717 IN OUT IP_IO *IpIo\r
cbf316f2 1718 )\r
1719{\r
1720 EFI_STATUS Status;\r
1721 IP_IO_IP_INFO *IpInfo;\r
fb115c61 1722 EFI_EVENT Event;\r
cbf316f2 1723\r
6aac5e5f 1724 ASSERT (IpIo != NULL);\r
cbf316f2 1725\r
e48e37fc 1726 IpInfo = AllocatePool (sizeof (IP_IO_IP_INFO));\r
cbf316f2 1727 if (IpInfo == NULL) {\r
fb115c61 1728 return NULL;\r
cbf316f2 1729 }\r
1730\r
1731 //\r
1732 // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP\r
1733 // instance.\r
1734 //\r
e48e37fc 1735 InitializeListHead (&IpInfo->Entry);\r
cbf316f2 1736 IpInfo->ChildHandle = NULL;\r
fb115c61 1737 ZeroMem (&IpInfo->Addr, sizeof (IpInfo->Addr));\r
1738 ZeroMem (&IpInfo->PreMask, sizeof (IpInfo->PreMask));\r
1739\r
1740 IpInfo->RefCnt = 1;\r
1741 IpInfo->IpVersion = IpIo->IpVersion;\r
cbf316f2 1742\r
1743 //\r
fb115c61 1744 // Create the IP instance and open the IP protocol.\r
cbf316f2 1745 //\r
1746 Status = IpIoCreateIpChildOpenProtocol (\r
1747 IpIo->Controller,\r
1748 IpIo->Image,\r
1749 &IpInfo->ChildHandle,\r
fb115c61 1750 IpInfo->IpVersion,\r
4eb65aff 1751 (VOID **) &IpInfo->Ip\r
cbf316f2 1752 );\r
1753 if (EFI_ERROR (Status)) {\r
1754 goto ReleaseIpInfo;\r
1755 }\r
1756\r
1757 //\r
1758 // Create the event for the DummyRcvToken.\r
1759 //\r
1760 Status = gBS->CreateEvent (\r
1761 EVT_NOTIFY_SIGNAL,\r
e48e37fc 1762 TPL_NOTIFY,\r
cbf316f2 1763 IpIoDummyHandler,\r
1764 IpInfo,\r
fb115c61 1765 &Event\r
cbf316f2 1766 );\r
1767 if (EFI_ERROR (Status)) {\r
1768 goto ReleaseIpChild;\r
1769 }\r
1770\r
fb115c61 1771 if (IpInfo->IpVersion == IP_VERSION_4) {\r
1772 IpInfo->DummyRcvToken.Ip4Token.Event = Event;\r
1773 } else {\r
1774 IpInfo->DummyRcvToken.Ip6Token.Event = Event;\r
1775 }\r
1776\r
cbf316f2 1777 //\r
1778 // Link this IpInfo into the IpIo.\r
1779 //\r
e48e37fc 1780 InsertTailList (&IpIo->IpList, &IpInfo->Entry);\r
cbf316f2 1781\r
1782 return IpInfo;\r
1783\r
1784ReleaseIpChild:\r
1785\r
1786 IpIoCloseProtocolDestroyIpChild (\r
1787 IpIo->Controller,\r
1788 IpIo->Image,\r
fb115c61 1789 IpInfo->ChildHandle,\r
1790 IpInfo->IpVersion\r
cbf316f2 1791 );\r
1792\r
1793ReleaseIpInfo:\r
1794\r
e48e37fc 1795 gBS->FreePool (IpInfo);\r
cbf316f2 1796\r
1797 return NULL;\r
1798}\r
1799\r
1800\r
1801/**\r
fb115c61 1802 Configure the IP instance of this IpInfo and start the receiving if IpConfigData\r
cbf316f2 1803 is not NULL.\r
1804\r
6aac5e5f 1805 @param[in, out] IpInfo Pointer to the IP_IO_IP_INFO instance.\r
fb115c61 1806 @param[in, out] IpConfigData The IP configure data used to configure the IP\r
6aac5e5f 1807 instance, if NULL the IP instance is reset. If\r
1808 UseDefaultAddress is set to TRUE, and the configure\r
1809 operation succeeds, the default address information\r
fb115c61 1810 is written back in this IpConfigData.\r
cbf316f2 1811\r
6aac5e5f 1812 @retval EFI_SUCCESS The IP instance of this IpInfo is configured successfully\r
1813 or no need to reconfigure it.\r
1814 @retval Others Configuration fails.\r
cbf316f2 1815\r
1816**/\r
1817EFI_STATUS\r
7b414b4e 1818EFIAPI\r
cbf316f2 1819IpIoConfigIp (\r
6aac5e5f 1820 IN OUT IP_IO_IP_INFO *IpInfo,\r
fb115c61 1821 IN OUT VOID *IpConfigData OPTIONAL\r
cbf316f2 1822 )\r
1823{\r
1824 EFI_STATUS Status;\r
2a2e33b2 1825 IP_IO_IP_PROTOCOL Ip;\r
b45b45b2 1826 UINT8 IpVersion;\r
cbf316f2 1827 EFI_IP4_MODE_DATA Ip4ModeData;\r
fb115c61 1828 EFI_IP6_MODE_DATA Ip6ModeData;\r
cbf316f2 1829\r
6aac5e5f 1830 ASSERT (IpInfo != NULL);\r
cbf316f2 1831\r
1832 if (IpInfo->RefCnt > 1) {\r
1833 //\r
1834 // This IP instance is shared, don't reconfigure it until it has only one\r
1835 // consumer. Currently, only the tcp children cloned from their passive parent\r
fb115c61 1836 // will share the same IP. So this cases only happens while IpConfigData is NULL,\r
cbf316f2 1837 // let the last consumer clean the IP instance.\r
1838 //\r
1839 return EFI_SUCCESS;\r
1840 }\r
1841\r
fb115c61 1842 IpVersion = IpInfo->IpVersion;\r
1843 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
1844\r
cbf316f2 1845 Ip = IpInfo->Ip;\r
1846\r
fb115c61 1847 if (IpInfo->IpVersion == IP_VERSION_4) {\r
2a2e33b2 1848 Status = Ip.Ip4->Configure (Ip.Ip4, IpConfigData);\r
fb115c61 1849 } else {\r
2a2e33b2 1850 Status = Ip.Ip6->Configure (Ip.Ip6, IpConfigData);\r
fb115c61 1851 }\r
1852\r
cbf316f2 1853 if (EFI_ERROR (Status)) {\r
1854 goto OnExit;\r
1855 }\r
1856\r
fb115c61 1857 if (IpConfigData != NULL) {\r
c167ef91 1858 if (IpInfo->IpVersion == IP_VERSION_4) {\r
cbf316f2 1859\r
fb115c61 1860 if (((EFI_IP4_CONFIG_DATA *) IpConfigData)->UseDefaultAddress) {\r
c167ef91
FS
1861 Status = Ip.Ip4->GetModeData (\r
1862 Ip.Ip4, \r
1863 &Ip4ModeData, \r
1864 NULL, \r
1865 NULL\r
1866 );\r
1867 if (EFI_ERROR (Status)) {\r
1868 Ip.Ip4->Configure (Ip.Ip4, NULL);\r
1869 goto OnExit;\r
1870 }\r
cbf316f2 1871\r
35f910f0
RP
1872 IP4_COPY_ADDRESS (&((EFI_IP4_CONFIG_DATA*) IpConfigData)->StationAddress, &Ip4ModeData.ConfigData.StationAddress);\r
1873 IP4_COPY_ADDRESS (&((EFI_IP4_CONFIG_DATA*) IpConfigData)->SubnetMask, &Ip4ModeData.ConfigData.SubnetMask);\r
c167ef91 1874 }\r
cbf316f2 1875\r
fb115c61 1876 CopyMem (\r
1877 &IpInfo->Addr.Addr, \r
1878 &((EFI_IP4_CONFIG_DATA *) IpConfigData)->StationAddress, \r
1879 sizeof (IP4_ADDR)\r
1880 );\r
1881 CopyMem (\r
1882 &IpInfo->PreMask.SubnetMask, \r
1883 &((EFI_IP4_CONFIG_DATA *) IpConfigData)->SubnetMask,\r
1884 sizeof (IP4_ADDR)\r
1885 );\r
1886\r
2a2e33b2 1887 Status = Ip.Ip4->Receive (\r
1888 Ip.Ip4,\r
1889 &IpInfo->DummyRcvToken.Ip4Token\r
1890 );\r
c167ef91
FS
1891 if (EFI_ERROR (Status)) {\r
1892 Ip.Ip4->Configure (Ip.Ip4, NULL);\r
1893 }\r
1894 } else {\r
1895 Status = Ip.Ip6->GetModeData (\r
1896 Ip.Ip6,\r
1897 &Ip6ModeData,\r
1898 NULL,\r
1899 NULL\r
1900 );\r
1901 if (EFI_ERROR (Status)) {\r
1902 Ip.Ip6->Configure (Ip.Ip6, NULL);\r
1903 goto OnExit;\r
1904 }\r
fb115c61 1905\r
1906 if (Ip6ModeData.IsConfigured) {\r
1907 CopyMem (\r
1908 &((EFI_IP6_CONFIG_DATA *) IpConfigData)->StationAddress,\r
1909 &Ip6ModeData.ConfigData.StationAddress,\r
1910 sizeof (EFI_IPv6_ADDRESS)\r
1911 );\r
1912\r
1913 if (Ip6ModeData.AddressList != NULL) {\r
1914 FreePool (Ip6ModeData.AddressList);\r
1915 }\r
1916\r
1917 if (Ip6ModeData.GroupTable != NULL) {\r
1918 FreePool (Ip6ModeData.GroupTable);\r
1919 }\r
1920\r
1921 if (Ip6ModeData.RouteTable != NULL) {\r
1922 FreePool (Ip6ModeData.RouteTable);\r
1923 }\r
1924\r
1925 if (Ip6ModeData.NeighborCache != NULL) {\r
1926 FreePool (Ip6ModeData.NeighborCache);\r
1927 }\r
1928\r
1929 if (Ip6ModeData.PrefixTable != NULL) {\r
1930 FreePool (Ip6ModeData.PrefixTable);\r
1931 }\r
1932\r
1933 if (Ip6ModeData.IcmpTypeList != NULL) {\r
1934 FreePool (Ip6ModeData.IcmpTypeList);\r
1935 }\r
1936\r
1937 } else {\r
1938 Status = EFI_NO_MAPPING;\r
1939 goto OnExit;\r
1940 } \r
1941\r
1942 CopyMem (\r
1943 &IpInfo->Addr, \r
1944 &Ip6ModeData.ConfigData.StationAddress, \r
1945 sizeof (EFI_IPv6_ADDRESS)\r
1946 );\r
1947\r
2a2e33b2 1948 Status = Ip.Ip6->Receive (\r
1949 Ip.Ip6,\r
1950 &IpInfo->DummyRcvToken.Ip6Token\r
1951 );\r
fb115c61 1952 if (EFI_ERROR (Status)) {\r
2a2e33b2 1953 Ip.Ip6->Configure (Ip.Ip6, NULL);\r
fb115c61 1954 }\r
1955 } \r
1956 } else {\r
cbf316f2 1957 //\r
fb115c61 1958 // The IP instance is reset, set the stored Addr and SubnetMask to zero.\r
cbf316f2 1959 //\r
fb115c61 1960 ZeroMem (&IpInfo->Addr, sizeof (IpInfo->Addr));\r
1961 ZeroMem (&IpInfo->PreMask, sizeof (IpInfo->PreMask));\r
cbf316f2 1962 }\r
1963\r
1964OnExit:\r
1965\r
1966 return Status;\r
1967}\r
1968\r
1969\r
1970/**\r
1971 Destroy an IP instance maintained in IpIo->IpList for\r
1972 sending purpose.\r
e6ff63a5 1973 \r
1974 This function pairs with IpIoAddIp(). The IpInfo is previously created by\r
1975 IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance\r
1976 will be dstroyed if the RefCnt is zero.\r
cbf316f2 1977\r
6aac5e5f 1978 @param[in] IpIo Pointer to the IP_IO instance.\r
1979 @param[in] IpInfo Pointer to the IpInfo to be removed.\r
cbf316f2 1980\r
cbf316f2 1981**/\r
1982VOID\r
7b414b4e 1983EFIAPI\r
cbf316f2 1984IpIoRemoveIp (\r
e6ff63a5 1985 IN IP_IO *IpIo,\r
1986 IN IP_IO_IP_INFO *IpInfo\r
cbf316f2 1987 )\r
1988{\r
fb115c61 1989\r
b45b45b2 1990 UINT8 IpVersion;\r
6ccfeec2
FS
1991 \r
1992 if (IpIo == NULL || IpInfo == NULL) {\r
1993 return;\r
1994 }\r
fb115c61 1995\r
cbf316f2 1996 ASSERT (IpInfo->RefCnt > 0);\r
1997\r
1998 NET_PUT_REF (IpInfo);\r
1999\r
2000 if (IpInfo->RefCnt > 0) {\r
2001\r
2002 return;\r
2003 }\r
2004\r
fb115c61 2005 IpVersion = IpIo->IpVersion;\r
2006\r
2007 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
2008\r
e48e37fc 2009 RemoveEntryList (&IpInfo->Entry);\r
cbf316f2 2010\r
fb115c61 2011 if (IpVersion == IP_VERSION_4){\r
2a2e33b2 2012 IpInfo->Ip.Ip4->Configure (\r
2013 IpInfo->Ip.Ip4,\r
2014 NULL\r
2015 );\r
fb115c61 2016 IpIoCloseProtocolDestroyIpChild (\r
2017 IpIo->Controller,\r
2018 IpIo->Image,\r
2019 IpInfo->ChildHandle,\r
2020 IP_VERSION_4\r
2021 );\r
2022\r
2023 gBS->CloseEvent (IpInfo->DummyRcvToken.Ip4Token.Event);\r
cbf316f2 2024\r
fb115c61 2025 } else {\r
cbf316f2 2026\r
2a2e33b2 2027 IpInfo->Ip.Ip6->Configure (\r
2028 IpInfo->Ip.Ip6,\r
2029 NULL\r
2030 );\r
cbf316f2 2031\r
fb115c61 2032 IpIoCloseProtocolDestroyIpChild (\r
2033 IpIo->Controller,\r
2034 IpIo->Image,\r
2035 IpInfo->ChildHandle,\r
2036 IP_VERSION_6\r
2037 );\r
2038\r
2039 gBS->CloseEvent (IpInfo->DummyRcvToken.Ip6Token.Event);\r
2040 }\r
2041\r
2042 FreePool (IpInfo);\r
cbf316f2 2043}\r
2044\r
2045\r
2046/**\r
2047 Find the first IP protocol maintained in IpIo whose local\r
fb115c61 2048 address is the same as Src.\r
e6ff63a5 2049 \r
2050 This function is called when the caller needs the IpIo to send data to the\r
2051 specified Src. The IpIo was added previously by IpIoAddIp().\r
cbf316f2 2052\r
6aac5e5f 2053 @param[in, out] IpIo Pointer to the pointer of the IP_IO instance.\r
fb115c61 2054 @param[in] IpVersion The version of the IP protocol to use, either\r
2055 IPv4 or IPv6.\r
6aac5e5f 2056 @param[in] Src The local IP address.\r
cbf316f2 2057\r
2058 @return Pointer to the IP protocol can be used for sending purpose and its local\r
6ccfeec2 2059 address is the same with Src. NULL if failed.\r
cbf316f2 2060\r
2061**/\r
2062IP_IO_IP_INFO *\r
7b414b4e 2063EFIAPI\r
cbf316f2 2064IpIoFindSender (\r
fb115c61 2065 IN OUT IP_IO **IpIo,\r
b45b45b2 2066 IN UINT8 IpVersion,\r
fb115c61 2067 IN EFI_IP_ADDRESS *Src\r
cbf316f2 2068 )\r
2069{\r
e48e37fc 2070 LIST_ENTRY *IpIoEntry;\r
cbf316f2 2071 IP_IO *IpIoPtr;\r
e48e37fc 2072 LIST_ENTRY *IpInfoEntry;\r
cbf316f2 2073 IP_IO_IP_INFO *IpInfo;\r
2074\r
6ccfeec2
FS
2075 if (IpIo == NULL || Src == NULL) {\r
2076 return NULL;\r
2077 }\r
2078\r
2079 if ((IpVersion != IP_VERSION_4) && (IpVersion != IP_VERSION_6)) {\r
2080 return NULL;\r
2081 }\r
fb115c61 2082\r
cbf316f2 2083 NET_LIST_FOR_EACH (IpIoEntry, &mActiveIpIoList) {\r
2084 IpIoPtr = NET_LIST_USER_STRUCT (IpIoEntry, IP_IO, Entry);\r
2085\r
fb115c61 2086 if (((*IpIo != NULL) && (*IpIo != IpIoPtr)) || (IpIoPtr->IpVersion != IpVersion)) {\r
cbf316f2 2087 continue;\r
2088 }\r
2089\r
2090 NET_LIST_FOR_EACH (IpInfoEntry, &IpIoPtr->IpList) {\r
2091 IpInfo = NET_LIST_USER_STRUCT (IpInfoEntry, IP_IO_IP_INFO, Entry);\r
fb115c61 2092 if (IpInfo->IpVersion == IP_VERSION_4){\r
2093\r
2094 if (EFI_IP4_EQUAL (&IpInfo->Addr.v4, &Src->v4)) {\r
2095 *IpIo = IpIoPtr;\r
2096 return IpInfo;\r
2097 }\r
2098\r
2099 } else {\r
2100\r
2101 if (EFI_IP6_EQUAL (&IpInfo->Addr.v6, &Src->v6)) {\r
2102 *IpIo = IpIoPtr;\r
2103 return IpInfo; \r
2104 }\r
2105 } \r
cbf316f2 2106\r
cbf316f2 2107 }\r
2108 }\r
2109\r
2110 //\r
2111 // No match.\r
2112 //\r
2113 return NULL;\r
2114}\r
2115\r
2116\r
2117/**\r
e6ff63a5 2118 Get the ICMP error map information.\r
2119 \r
2120 The ErrorStatus will be returned. The IsHard and Notify are optional. If they\r
2121 are not NULL, this routine will fill them.\r
cbf316f2 2122\r
8f5e6151 2123 @param[in] IcmpError IcmpError Type.\r
fb115c61 2124 @param[in] IpVersion The version of the IP protocol to use,\r
3b1464d5 2125 either IPv4 or IPv6. \r
2126 @param[out] IsHard If TRUE, indicates that it is a hard error.\r
2127 @param[out] Notify If TRUE, SockError needs to be notified.\r
cbf316f2 2128\r
6dbfed92 2129 @retval EFI_UNSUPPORTED Unrecognizable ICMP error code.\r
6aac5e5f 2130 @return ICMP Error Status, such as EFI_NETWORK_UNREACHABLE.\r
cbf316f2 2131\r
2132**/\r
2133EFI_STATUS\r
7b414b4e 2134EFIAPI\r
cbf316f2 2135IpIoGetIcmpErrStatus (\r
b45b45b2 2136 IN UINT8 IcmpError,\r
2137 IN UINT8 IpVersion,\r
e6ff63a5 2138 OUT BOOLEAN *IsHard OPTIONAL,\r
2139 OUT BOOLEAN *Notify OPTIONAL\r
cbf316f2 2140 )\r
2141{\r
3cf888f5 2142 if (IpVersion == IP_VERSION_4 ) {\r
b45b45b2 2143 ASSERT (IcmpError <= ICMP_ERR_PARAMPROB);\r
687a2e5f 2144\r
3cf888f5 2145 if (IsHard != NULL) {\r
2146 *IsHard = mIcmpErrMap[IcmpError].IsHard;\r
2147 }\r
687a2e5f 2148\r
3cf888f5 2149 if (Notify != NULL) {\r
2150 *Notify = mIcmpErrMap[IcmpError].Notify;\r
2151 }\r
2152\r
2153 switch (IcmpError) {\r
2154 case ICMP_ERR_UNREACH_NET:\r
2155 return EFI_NETWORK_UNREACHABLE;\r
2156\r
2157 case ICMP_ERR_TIMXCEED_INTRANS:\r
2158 case ICMP_ERR_TIMXCEED_REASS:\r
2159 case ICMP_ERR_UNREACH_HOST:\r
2160 return EFI_HOST_UNREACHABLE;\r
2161\r
2162 case ICMP_ERR_UNREACH_PROTOCOL:\r
2163 return EFI_PROTOCOL_UNREACHABLE;\r
2164\r
2165 case ICMP_ERR_UNREACH_PORT:\r
2166 return EFI_PORT_UNREACHABLE;\r
2167\r
2168 case ICMP_ERR_MSGSIZE:\r
2169 case ICMP_ERR_UNREACH_SRCFAIL:\r
2170 case ICMP_ERR_QUENCH:\r
2171 case ICMP_ERR_PARAMPROB:\r
2172 return EFI_ICMP_ERROR;\r
2173\r
2174 default:\r
2175 ASSERT (FALSE);\r
2176 return EFI_UNSUPPORTED;\r
2177 }\r
687a2e5f 2178\r
fb115c61 2179 } else if (IpVersion == IP_VERSION_6) {\r
2180\r
b45b45b2 2181 ASSERT (IcmpError <= ICMP6_ERR_PARAMPROB_IPV6OPTION);\r
687a2e5f 2182\r
fb115c61 2183 if (IsHard != NULL) {\r
2184 *IsHard = mIcmp6ErrMap[IcmpError].IsHard;\r
2185 }\r
2186\r
2187 if (Notify != NULL) {\r
2188 *Notify = mIcmp6ErrMap[IcmpError].Notify;\r
2189 }\r
3cf888f5 2190\r
2191 switch (IcmpError) {\r
2192 case ICMP6_ERR_UNREACH_NET:\r
2193 return EFI_NETWORK_UNREACHABLE;\r
2194\r
2195 case ICMP6_ERR_UNREACH_HOST:\r
2196 case ICMP6_ERR_TIMXCEED_HOPLIMIT:\r
2197 case ICMP6_ERR_TIMXCEED_REASS: \r
2198 return EFI_HOST_UNREACHABLE;\r
2199\r
2200 case ICMP6_ERR_UNREACH_PROTOCOL:\r
2201 return EFI_PROTOCOL_UNREACHABLE;\r
2202 \r
2203 case ICMP6_ERR_UNREACH_PORT:\r
2204 return EFI_PORT_UNREACHABLE;\r
2205\r
2206 case ICMP6_ERR_PACKAGE_TOOBIG:\r
2207 case ICMP6_ERR_PARAMPROB_HEADER:\r
2208 case ICMP6_ERR_PARAMPROB_NEXHEADER:\r
2209 case ICMP6_ERR_PARAMPROB_IPV6OPTION:\r
2210 return EFI_ICMP_ERROR;\r
2211\r
2212 default:\r
2213 ASSERT (FALSE);\r
2214 return EFI_UNSUPPORTED;\r
2215 }\r
fb115c61 2216\r
2217 } else {\r
2218 //\r
2219 // Should never be here\r
2220 //\r
2221 ASSERT (FALSE);\r
2222 return EFI_UNSUPPORTED;\r
2223 }\r
2224}\r
cbf316f2 2225\r
cbf316f2 2226\r
fb115c61 2227/**\r
2228 Refresh the remote peer's Neighbor Cache entries.\r
2229\r
2230 This function is called when the caller needs the IpIo to refresh the existing\r
2231 IPv6 neighbor cache entries since the neighbor is considered reachable by the \r
2232 node has recently received a confirmation that packets sent recently to the \r
2233 neighbor were received by its IP layer. \r
2234\r
2235 @param[in] IpIo Pointer to an IP_IO instance\r
2236 @param[in] Neighbor The IP address of the neighbor\r
2237 @param[in] Timeout Time in 100-ns units that this entry will\r
2238 remain in the neighbor cache. A value of \r
2239 zero means that the entry is permanent. \r
2240 A value of non-zero means that the entry is \r
2241 dynamic and will be deleted after Timeout.\r
2242\r
2243 @retval EFI_SUCCESS The operation is completed successfully.\r
2244 @retval EFI_NOT_STARTED The IpIo is not configured.\r
2245 @retval EFI_INVALID_PARAMETER Neighbor Address is invalid.\r
2246 @retval EFI_NOT_FOUND The neighbor cache entry is not in the \r
2247 neighbor table. \r
6dbfed92 2248 @retval EFI_UNSUPPORTED IP version is IPv4, which doesn't support neighbor cache refresh.\r
fb115c61 2249 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
cbf316f2 2250\r
fb115c61 2251**/\r
2252EFI_STATUS\r
2253IpIoRefreshNeighbor (\r
2254 IN IP_IO *IpIo,\r
2255 IN EFI_IP_ADDRESS *Neighbor,\r
2256 IN UINT32 Timeout \r
2257 )\r
2258{\r
2259 EFI_IP6_PROTOCOL *Ip;\r
2260\r
6dbfed92 2261 if (!IpIo->IsConfigured) {\r
fb115c61 2262 return EFI_NOT_STARTED;\r
cbf316f2 2263 }\r
2264\r
6dbfed92
FS
2265 if (IpIo->IpVersion != IP_VERSION_6) {\r
2266 return EFI_UNSUPPORTED;\r
2267 }\r
2268\r
2a2e33b2 2269 Ip = IpIo->Ip.Ip6;\r
fb115c61 2270\r
2271 return Ip->Neighbors (Ip, FALSE, &Neighbor->v6, NULL, Timeout, TRUE);\r
cbf316f2 2272}\r
2273\r