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