/** @file\r
+ IpIo Library.\r
\r
-Copyright (c) 2005 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- IpIo.c\r
-\r
-Abstract:\r
-\r
- The implementation of the IpIo layer.\r
-\r
-\r
+(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
+Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
**/\r
\r
-#include <PiDxe.h>\r
+#include <Uefi.h>\r
\r
#include <Protocol/Udp4.h>\r
\r
#include <Library/IpIoLib.h>\r
#include <Library/BaseLib.h>\r
#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-\r
+#include <Library/DpcLib.h>\r
\r
-#define NET_PROTO_HDR(Buf, Type) ((Type *) ((Buf)->BlockOp[0].Head))\r
-#define ICMP_ERRLEN(IpHdr) \\r
- (sizeof(IP4_ICMP_HEAD) + EFI_IP4_HEADER_LEN(IpHdr) + 8)\r
\r
-NET_LIST_ENTRY mActiveIpIoList = {\r
+GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mActiveIpIoList = {\r
&mActiveIpIoList,\r
&mActiveIpIoList\r
};\r
\r
-EFI_IP4_CONFIG_DATA mIpIoDefaultIpConfigData = {\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_IP4_CONFIG_DATA mIp4IoDefaultIpConfigData = {\r
EFI_IP_PROTO_UDP,\r
FALSE,\r
TRUE,\r
0\r
};\r
\r
-STATIC ICMP_ERROR_INFO mIcmpErrMap[10] = {\r
- {FALSE, TRUE},\r
- {FALSE, TRUE},\r
- {TRUE, TRUE},\r
- {TRUE, TRUE},\r
- {TRUE, TRUE},\r
- {FALSE, TRUE},\r
- {FALSE, TRUE},\r
- {FALSE, TRUE},\r
- {FALSE, FALSE},\r
- {FALSE, TRUE}\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_IP6_CONFIG_DATA mIp6IoDefaultIpConfigData = {\r
+ EFI_IP_PROTO_UDP,\r
+ FALSE,\r
+ TRUE,\r
+ FALSE,\r
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},\r
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},\r
+ 0,\r
+ 255,\r
+ 0,\r
+ 0,\r
+ 0\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED ICMP_ERROR_INFO mIcmpErrMap[10] = {\r
+ {FALSE, TRUE }, // ICMP_ERR_UNREACH_NET\r
+ {FALSE, TRUE }, // ICMP_ERR_UNREACH_HOST\r
+ {TRUE, TRUE }, // ICMP_ERR_UNREACH_PROTOCOL\r
+ {TRUE, TRUE }, // ICMP_ERR_UNREACH_PORT\r
+ {TRUE, TRUE }, // ICMP_ERR_MSGSIZE\r
+ {FALSE, TRUE }, // ICMP_ERR_UNREACH_SRCFAIL\r
+ {FALSE, TRUE }, // ICMP_ERR_TIMXCEED_INTRANS\r
+ {FALSE, TRUE }, // ICMP_ERR_TIMEXCEED_REASS\r
+ {FALSE, FALSE}, // ICMP_ERR_QUENCH\r
+ {FALSE, TRUE } // ICMP_ERR_PARAMPROB\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED ICMP_ERROR_INFO mIcmp6ErrMap[10] = {\r
+ {FALSE, TRUE}, // ICMP6_ERR_UNREACH_NET\r
+ {FALSE, TRUE}, // ICMP6_ERR_UNREACH_HOST\r
+ {TRUE, TRUE}, // ICMP6_ERR_UNREACH_PROTOCOL\r
+ {TRUE, TRUE}, // ICMP6_ERR_UNREACH_PORT\r
+ {TRUE, TRUE}, // ICMP6_ERR_PACKAGE_TOOBIG\r
+ {FALSE, TRUE}, // ICMP6_ERR_TIMXCEED_HOPLIMIT\r
+ {FALSE, TRUE}, // ICMP6_ERR_TIMXCEED_REASS\r
+ {FALSE, TRUE}, // ICMP6_ERR_PARAMPROB_HEADER\r
+ {FALSE, TRUE}, // ICMP6_ERR_PARAMPROB_NEXHEADER\r
+ {FALSE, TRUE} // ICMP6_ERR_PARAMPROB_IPV6OPTION\r
};\r
\r
-STATIC\r
+\r
+/**\r
+ Notify function for IP transmit token.\r
+\r
+ @param[in] Context The context passed in by the event notifier.\r
+\r
+**/\r
VOID\r
EFIAPI\r
IpIoTransmitHandlerDpc (\r
IN VOID *Context\r
);\r
\r
-STATIC\r
+\r
+/**\r
+ Notify function for IP transmit token.\r
+\r
+ @param[in] Event The event signaled.\r
+ @param[in] Context The context passed in by the event notifier.\r
+\r
+**/\r
VOID\r
EFIAPI\r
IpIoTransmitHandler (\r
\r
\r
/**\r
- This function create an ip child ,open the IP protocol, return the opened\r
- Ip protocol to Interface.\r
+ This function create an IP child ,open the IP protocol, and return the opened\r
+ IP protocol as Interface.\r
\r
- @param ControllerHandle The controller handle.\r
- @param ImageHandle The image handle.\r
- @param ChildHandle Pointer to the buffer to save the ip child handle.\r
- @param Interface Pointer used to get the ip protocol interface.\r
+ @param[in] ControllerHandle The controller handle.\r
+ @param[in] ImageHandle The image handle.\r
+ @param[in] ChildHandle Pointer to the buffer to save the IP child handle.\r
+ @param[in] IpVersion The version of the IP protocol to use, either\r
+ IPv4 or IPv6.\r
+ @param[out] Interface Pointer used to get the IP protocol interface.\r
\r
- @retval EFI_SUCCESS The ip child is created and the ip protocol\r
- interface is retrieved.\r
- @retval other The required operation failed.\r
+ @retval EFI_SUCCESS The IP child is created and the IP protocol\r
+ interface is retrieved.\r
+ @retval EFI_UNSUPPORTED Upsupported IpVersion.\r
+ @retval Others The required operation failed.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
IpIoCreateIpChildOpenProtocol (\r
IN EFI_HANDLE ControllerHandle,\r
IN EFI_HANDLE ImageHandle,\r
IN EFI_HANDLE *ChildHandle,\r
+ IN UINT8 IpVersion,\r
OUT VOID **Interface\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_GUID *ServiceBindingGuid;\r
+ EFI_GUID *IpProtocolGuid;\r
+\r
+ if (IpVersion == IP_VERSION_4) {\r
+ ServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;\r
+ IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
+ } else if (IpVersion == IP_VERSION_6){\r
+ ServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;\r
+ IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
\r
//\r
- // Create an ip child.\r
+ // Create an IP child.\r
//\r
Status = NetLibCreateServiceChild (\r
ControllerHandle,\r
ImageHandle,\r
- &gEfiIp4ServiceBindingProtocolGuid,\r
+ ServiceBindingGuid,\r
ChildHandle\r
);\r
if (EFI_ERROR (Status)) {\r
}\r
\r
//\r
- // Open the ip protocol installed on the *ChildHandle.\r
+ // Open the IP protocol installed on the *ChildHandle.\r
//\r
Status = gBS->OpenProtocol (\r
*ChildHandle,\r
- &gEfiIp4ProtocolGuid,\r
+ IpProtocolGuid,\r
Interface,\r
ImageHandle,\r
ControllerHandle,\r
);\r
if (EFI_ERROR (Status)) {\r
//\r
- // On failure, destroy the ip child.\r
+ // On failure, destroy the IP child.\r
//\r
NetLibDestroyServiceChild (\r
ControllerHandle,\r
ImageHandle,\r
- &gEfiIp4ServiceBindingProtocolGuid,\r
+ ServiceBindingGuid,\r
*ChildHandle\r
);\r
}\r
\r
\r
/**\r
- This function close the previously openned ip protocol and destroy the ip child.\r
+ This function close the previously openned IP protocol and destroy the IP child.\r
\r
- @param ControllerHandle The controller handle.\r
- @param ImageHandle the image handle.\r
- @param ChildHandle The child handle of the ip child.\r
+ @param[in] ControllerHandle The controller handle.\r
+ @param[in] ImageHandle The image handle.\r
+ @param[in] ChildHandle The child handle of the IP child.\r
+ @param[in] IpVersion The version of the IP protocol to use, either\r
+ IPv4 or IPv6.\r
\r
- @retval EFI_SUCCESS The ip protocol is closed and the relevant ip child\r
- is destroyed.\r
- @retval other The required operation failed.\r
+ @retval EFI_SUCCESS The IP protocol is closed and the relevant IP child\r
+ is destroyed.\r
+ @retval EFI_UNSUPPORTED Upsupported IpVersion.\r
+ @retval Others The required operation failed.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
IpIoCloseProtocolDestroyIpChild (\r
IN EFI_HANDLE ControllerHandle,\r
IN EFI_HANDLE ImageHandle,\r
- IN EFI_HANDLE ChildHandle\r
+ IN EFI_HANDLE ChildHandle,\r
+ IN UINT8 IpVersion\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_GUID *ServiceBindingGuid;\r
+ EFI_GUID *IpProtocolGuid;\r
+\r
+ if (IpVersion == IP_VERSION_4) {\r
+ ServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;\r
+ IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
+ } else if (IpVersion == IP_VERSION_6) {\r
+ ServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;\r
+ IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
\r
//\r
- // Close the previously openned ip protocol.\r
+ // Close the previously openned IP protocol.\r
//\r
- gBS->CloseProtocol (\r
- ChildHandle,\r
- &gEfiIp4ProtocolGuid,\r
- ImageHandle,\r
- ControllerHandle\r
- );\r
+ Status = gBS->CloseProtocol (\r
+ ChildHandle,\r
+ IpProtocolGuid,\r
+ ImageHandle,\r
+ ControllerHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
//\r
- // Destroy the ip child.\r
+ // Destroy the IP child.\r
//\r
- Status = NetLibDestroyServiceChild (\r
- ControllerHandle,\r
- ImageHandle,\r
- &gEfiIp4ServiceBindingProtocolGuid,\r
- ChildHandle\r
- );\r
-\r
- return Status;\r
+ return NetLibDestroyServiceChild (\r
+ ControllerHandle,\r
+ ImageHandle,\r
+ ServiceBindingGuid,\r
+ ChildHandle\r
+ );\r
}\r
\r
-\r
/**\r
- Handle ICMP packets.\r
+ This function handles ICMPv4 packets. It is the worker function of\r
+ IpIoIcmpHandler.\r
\r
- @param IpIo Pointer to the IP_IO instance.\r
- @param Pkt Pointer to the ICMP packet.\r
- @param Session Pointer to the net session of this ICMP packet.\r
+ @param[in] IpIo Pointer to the IP_IO instance.\r
+ @param[in, out] Pkt Pointer to the ICMPv4 packet.\r
+ @param[in] Session Pointer to the net session of this ICMPv4 packet.\r
\r
- @retval EFI_SUCCESS The ICMP packet is handled successfully.\r
- @retval EFI_ABORTED This type of ICMP packet is not supported.\r
+ @retval EFI_SUCCESS The ICMPv4 packet is handled successfully.\r
+ @retval EFI_ABORTED This type of ICMPv4 packet is not supported.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
-IpIoIcmpHandler (\r
- IN IP_IO *IpIo,\r
- IN NET_BUF *Pkt,\r
- IN EFI_NET_SESSION_DATA *Session\r
+IpIoIcmpv4Handler (\r
+ IN IP_IO *IpIo,\r
+ IN OUT NET_BUF *Pkt,\r
+ IN EFI_NET_SESSION_DATA *Session\r
)\r
{\r
IP4_ICMP_ERROR_HEAD *IcmpHdr;\r
EFI_IP4_HEADER *IpHdr;\r
- ICMP_ERROR IcmpErr;\r
+ UINT8 IcmpErr;\r
UINT8 *PayLoadHdr;\r
UINT8 Type;\r
UINT8 Code;\r
UINT32 TrimBytes;\r
\r
- IcmpHdr = NET_PROTO_HDR (Pkt, IP4_ICMP_ERROR_HEAD);\r
- IpHdr = (EFI_IP4_HEADER *) (&IcmpHdr->IpHead);\r
+ ASSERT (IpIo != NULL);\r
+ ASSERT (Pkt != NULL);\r
+ ASSERT (Session != NULL);\r
+ ASSERT (IpIo->IpVersion == IP_VERSION_4);\r
\r
//\r
// Check the ICMP packet length.\r
//\r
+ if (Pkt->TotalSize < sizeof (IP4_ICMP_ERROR_HEAD)) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ IcmpHdr = NET_PROTO_HDR (Pkt, IP4_ICMP_ERROR_HEAD);\r
+ IpHdr = (EFI_IP4_HEADER *) (&IcmpHdr->IpHead);\r
+\r
if (Pkt->TotalSize < ICMP_ERRLEN (IpHdr)) {\r
\r
return EFI_ABORTED;\r
case ICMP_CODE_UNREACH_PROTOCOL:\r
case ICMP_CODE_UNREACH_PORT:\r
case ICMP_CODE_UNREACH_SRCFAIL:\r
- IcmpErr = (ICMP_ERROR) (ICMP_ERR_UNREACH_NET + Code);\r
+ IcmpErr = (UINT8) (ICMP_ERR_UNREACH_NET + Code);\r
\r
break;\r
\r
\r
default:\r
return EFI_ABORTED;\r
-\r
- break;\r
}\r
\r
break;\r
return EFI_ABORTED;\r
}\r
\r
- IcmpErr = (ICMP_ERROR) (Code + ICMP_ERR_TIMXCEED_INTRANS);\r
+ IcmpErr = (UINT8) (Code + ICMP_ERR_TIMXCEED_INTRANS);\r
\r
break;\r
\r
\r
default:\r
return EFI_ABORTED;\r
-\r
- break;\r
}\r
\r
//\r
\r
NetbufTrim (Pkt, TrimBytes, TRUE);\r
\r
- IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);\r
+ //\r
+ // If the input packet has invalid format, and TrimBytes is larger than\r
+ // the packet size, the NetbufTrim might trim the packet to zero.\r
+ //\r
+ if (Pkt->TotalSize != 0) {\r
+ IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function handles ICMPv6 packets. It is the worker function of\r
+ IpIoIcmpHandler.\r
+\r
+ @param[in] IpIo Pointer to the IP_IO instance.\r
+ @param[in, out] Pkt Pointer to the ICMPv6 packet.\r
+ @param[in] Session Pointer to the net session of this ICMPv6 packet.\r
+\r
+ @retval EFI_SUCCESS The ICMPv6 packet is handled successfully.\r
+ @retval EFI_ABORTED This type of ICMPv6 packet is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+IpIoIcmpv6Handler (\r
+ IN IP_IO *IpIo,\r
+ IN OUT NET_BUF *Pkt,\r
+ IN EFI_NET_SESSION_DATA *Session\r
+ )\r
+{\r
+ IP6_ICMP_ERROR_HEAD *IcmpHdr;\r
+ EFI_IP6_HEADER *IpHdr;\r
+ UINT8 IcmpErr;\r
+ UINT8 *PayLoadHdr;\r
+ UINT8 Type;\r
+ UINT8 Code;\r
+ UINT8 NextHeader;\r
+ UINT32 TrimBytes;\r
+ BOOLEAN Flag;\r
+\r
+ ASSERT (IpIo != NULL);\r
+ ASSERT (Pkt != NULL);\r
+ ASSERT (Session != NULL);\r
+ ASSERT (IpIo->IpVersion == IP_VERSION_6);\r
+\r
+ //\r
+ // Check the ICMPv6 packet length.\r
+ //\r
+ if (Pkt->TotalSize < sizeof (IP6_ICMP_ERROR_HEAD)) {\r
+\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ IcmpHdr = NET_PROTO_HDR (Pkt, IP6_ICMP_ERROR_HEAD);\r
+ Type = IcmpHdr->Head.Type;\r
+ Code = IcmpHdr->Head.Code;\r
+\r
+ //\r
+ // Analyze the ICMPv6 Error in this ICMPv6 packet\r
+ //\r
+ switch (Type) {\r
+ case ICMP_V6_DEST_UNREACHABLE:\r
+ switch (Code) {\r
+ case ICMP_V6_NO_ROUTE_TO_DEST:\r
+ case ICMP_V6_BEYOND_SCOPE:\r
+ case ICMP_V6_ROUTE_REJECTED:\r
+ IcmpErr = ICMP6_ERR_UNREACH_NET;\r
+\r
+ break;\r
+\r
+ case ICMP_V6_COMM_PROHIBITED:\r
+ case ICMP_V6_ADDR_UNREACHABLE:\r
+ case ICMP_V6_SOURCE_ADDR_FAILED:\r
+ IcmpErr = ICMP6_ERR_UNREACH_HOST;\r
+\r
+ break;\r
+\r
+ case ICMP_V6_PORT_UNREACHABLE:\r
+ IcmpErr = ICMP6_ERR_UNREACH_PORT;\r
+\r
+ break;\r
+\r
+ default:\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ break;\r
+\r
+ case ICMP_V6_PACKET_TOO_BIG:\r
+ if (Code >= 1) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ IcmpErr = ICMP6_ERR_PACKAGE_TOOBIG;\r
+\r
+ break;\r
+\r
+ case ICMP_V6_TIME_EXCEEDED:\r
+ if (Code > 1) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ IcmpErr = (UINT8) (ICMP6_ERR_TIMXCEED_HOPLIMIT + Code);\r
+\r
+ break;\r
+\r
+ case ICMP_V6_PARAMETER_PROBLEM:\r
+ if (Code > 3) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ IcmpErr = (UINT8) (ICMP6_ERR_PARAMPROB_HEADER + Code);\r
+\r
+ break;\r
+\r
+ default:\r
+\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Notify user the ICMPv6 packet only containing payload except\r
+ // IPv6 basic header, extension header and ICMP header\r
+ //\r
+\r
+ IpHdr = (EFI_IP6_HEADER *) (&IcmpHdr->IpHead);\r
+ NextHeader = IpHdr->NextHeader;\r
+ PayLoadHdr = (UINT8 *) ((UINT8 *) IcmpHdr + sizeof (IP6_ICMP_ERROR_HEAD));\r
+ Flag = TRUE;\r
+\r
+ do {\r
+ switch (NextHeader) {\r
+ case EFI_IP_PROTO_UDP:\r
+ case EFI_IP_PROTO_TCP:\r
+ case EFI_IP_PROTO_ICMP:\r
+ case IP6_NO_NEXT_HEADER:\r
+ Flag = FALSE;\r
+\r
+ break;\r
+\r
+ case IP6_HOP_BY_HOP:\r
+ case IP6_DESTINATION:\r
+ //\r
+ // The Hdr Ext Len is 8-bit unsigned integer in 8-octet units, not including\r
+ // the first 8 octets.\r
+ //\r
+ NextHeader = *(PayLoadHdr);\r
+ PayLoadHdr = (UINT8 *) (PayLoadHdr + (*(PayLoadHdr + 1) + 1) * 8);\r
+\r
+ break;\r
+\r
+ case IP6_FRAGMENT:\r
+ //\r
+ // The Fragment Header Length is 8 octets.\r
+ //\r
+ NextHeader = *(PayLoadHdr);\r
+ PayLoadHdr = (UINT8 *) (PayLoadHdr + 8);\r
+\r
+ break;\r
+\r
+ default:\r
+\r
+ return EFI_ABORTED;\r
+ }\r
+ } while (Flag);\r
+\r
+ TrimBytes = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);\r
+\r
+ NetbufTrim (Pkt, TrimBytes, TRUE);\r
+\r
+ //\r
+ // If the input packet has invalid format, and TrimBytes is larger than\r
+ // the packet size, the NetbufTrim might trim the packet to zero.\r
+ //\r
+ if (Pkt->TotalSize != 0) {\r
+ IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ This function handles ICMP packets.\r
+\r
+ @param[in] IpIo Pointer to the IP_IO instance.\r
+ @param[in, out] Pkt Pointer to the ICMP packet.\r
+ @param[in] Session Pointer to the net session of this ICMP packet.\r
+\r
+ @retval EFI_SUCCESS The ICMP packet is handled successfully.\r
+ @retval EFI_ABORTED This type of ICMP packet is not supported.\r
+ @retval EFI_UNSUPPORTED The IP protocol version in IP_IO is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+IpIoIcmpHandler (\r
+ IN IP_IO *IpIo,\r
+ IN OUT NET_BUF *Pkt,\r
+ IN EFI_NET_SESSION_DATA *Session\r
+ )\r
+{\r
+\r
+ if (IpIo->IpVersion == IP_VERSION_4) {\r
+\r
+ return IpIoIcmpv4Handler (IpIo, Pkt, Session);\r
+\r
+ } else if (IpIo->IpVersion == IP_VERSION_6) {\r
+\r
+ return IpIoIcmpv6Handler (IpIo, Pkt, Session);\r
+\r
+ } else {\r
+\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+}\r
+\r
\r
/**\r
- Ext free function for net buffer. This function is\r
- called when the net buffer is freed. It is used to\r
+ Free function for receive token of IP_IO. It is used to\r
signal the recycle event to notify IP to recycle the\r
data buffer.\r
\r
- @param Event The event to be signaled.\r
-\r
- @return None.\r
+ @param[in] Event The event to be signaled.\r
\r
**/\r
-STATIC\r
VOID\r
+EFIAPI\r
IpIoExtFree (\r
IN VOID *Event\r
)\r
Create a send entry to wrap a packet before sending\r
out it through IP.\r
\r
- @param IpIo Pointer to the IP_IO instance.\r
- @param Pkt Pointer to the packet.\r
- @param Sender Pointer to the IP sender.\r
- @param NotifyData Pointer to the notify data.\r
- @param Dest Pointer to the destination IP address.\r
- @param Override Pointer to the overriden IP_IO data.\r
+ @param[in, out] IpIo Pointer to the IP_IO instance.\r
+ @param[in, out] Pkt Pointer to the packet.\r
+ @param[in] Sender Pointer to the IP sender.\r
+ @param[in] Context Pointer to the context.\r
+ @param[in] NotifyData Pointer to the notify data.\r
+ @param[in] Dest Pointer to the destination IP address.\r
+ @param[in] Override Pointer to the overriden IP_IO data.\r
\r
- @return Pointer to the data structure created to wrap the packet. If NULL,\r
- @return resource limit occurred.\r
+ @return Pointer to the data structure created to wrap the packet. If any error occurs,\r
+ then return NULL.\r
\r
**/\r
-STATIC\r
IP_IO_SEND_ENTRY *\r
IpIoCreateSndEntry (\r
- IN IP_IO *IpIo,\r
- IN NET_BUF *Pkt,\r
- IN EFI_IP4_PROTOCOL *Sender,\r
- IN VOID *Context OPTIONAL,\r
- IN VOID *NotifyData OPTIONAL,\r
- IN IP4_ADDR Dest,\r
- IN IP_IO_OVERRIDE *Override\r
+ IN OUT IP_IO *IpIo,\r
+ IN OUT NET_BUF *Pkt,\r
+ IN IP_IO_IP_PROTOCOL Sender,\r
+ IN VOID *Context OPTIONAL,\r
+ IN VOID *NotifyData OPTIONAL,\r
+ IN EFI_IP_ADDRESS *Dest OPTIONAL,\r
+ IN IP_IO_OVERRIDE *Override\r
)\r
{\r
IP_IO_SEND_ENTRY *SndEntry;\r
- EFI_IP4_COMPLETION_TOKEN *SndToken;\r
- EFI_IP4_TRANSMIT_DATA *TxData;\r
+ EFI_EVENT Event;\r
EFI_STATUS Status;\r
- EFI_IP4_OVERRIDE_DATA *OverrideData;\r
- volatile UINT32 Index;\r
+ NET_FRAGMENT *ExtFragment;\r
+ UINT32 FragmentCount;\r
+ IP_IO_OVERRIDE *OverrideData;\r
+ IP_IO_IP_TX_DATA *TxData;\r
+ EFI_IP4_TRANSMIT_DATA *Ip4TxData;\r
+ EFI_IP6_TRANSMIT_DATA *Ip6TxData;\r
+\r
+ if ((IpIo->IpVersion != IP_VERSION_4) && (IpIo->IpVersion != IP_VERSION_6)) {\r
+ return NULL;\r
+ }\r
+\r
+ Event = NULL;\r
+ TxData = NULL;\r
+ OverrideData = NULL;\r
\r
//\r
// Allocate resource for SndEntry\r
//\r
- SndEntry = NetAllocatePool (sizeof (IP_IO_SEND_ENTRY));\r
+ SndEntry = AllocatePool (sizeof (IP_IO_SEND_ENTRY));\r
if (NULL == SndEntry) {\r
return NULL;\r
}\r
\r
- //\r
- // Allocate resource for SndToken\r
- //\r
- SndToken = NetAllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN));\r
- if (NULL == SndToken) {\r
- goto ReleaseSndEntry;\r
- }\r
-\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_SIGNAL,\r
- NET_TPL_EVENT,\r
+ TPL_NOTIFY,\r
IpIoTransmitHandler,\r
SndEntry,\r
- &(SndToken->Event)\r
+ &Event\r
);\r
if (EFI_ERROR (Status)) {\r
- goto ReleaseSndToken;\r
+ goto ON_ERROR;\r
}\r
\r
+ FragmentCount = Pkt->BlockOpNum;\r
+\r
//\r
// Allocate resource for TxData\r
//\r
- TxData = NetAllocatePool (\r
- sizeof (EFI_IP4_TRANSMIT_DATA) +\r
- sizeof (EFI_IP4_FRAGMENT_DATA) * (Pkt->BlockOpNum - 1)\r
+ TxData = (IP_IO_IP_TX_DATA *) AllocatePool (\r
+ sizeof (IP_IO_IP_TX_DATA) + sizeof (NET_FRAGMENT) * (FragmentCount - 1)\r
);\r
\r
if (NULL == TxData) {\r
- goto ReleaseEvent;\r
+ goto ON_ERROR;\r
}\r
\r
+ //\r
+ // Build a fragment table to contain the fragments in the packet.\r
+ //\r
+ if (IpIo->IpVersion == IP_VERSION_4) {\r
+ ExtFragment = (NET_FRAGMENT *) TxData->Ip4TxData.FragmentTable;\r
+ } else {\r
+ ExtFragment = (NET_FRAGMENT *) TxData->Ip6TxData.FragmentTable;\r
+ }\r
+\r
+ NetbufBuildExt (Pkt, ExtFragment, &FragmentCount);\r
+\r
+\r
//\r
// Allocate resource for OverrideData if needed\r
//\r
- OverrideData = NULL;\r
if (NULL != Override) {\r
\r
- OverrideData = NetAllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA));\r
+ OverrideData = AllocateCopyPool (sizeof (IP_IO_OVERRIDE), Override);\r
if (NULL == OverrideData) {\r
- goto ReleaseResource;\r
+ goto ON_ERROR;\r
}\r
- //\r
- // Set the fields of OverrideData\r
- //\r
- CopyMem (OverrideData, Override, sizeof (*OverrideData));\r
}\r
\r
//\r
- // Set the fields of TxData\r
+ // Set other fields of TxData except the fragment table\r
//\r
- NetCopyMem (&TxData->DestinationAddress, &Dest, sizeof (EFI_IPv4_ADDRESS));\r
- TxData->OverrideData = OverrideData;\r
- TxData->OptionsLength = 0;\r
- TxData->OptionsBuffer = NULL;\r
- TxData->TotalDataLength = Pkt->TotalSize;\r
- TxData->FragmentCount = Pkt->BlockOpNum;\r
+ if (IpIo->IpVersion == IP_VERSION_4) {\r
\r
+ Ip4TxData = &TxData->Ip4TxData;\r
\r
- for (Index = 0; Index < Pkt->BlockOpNum; Index++) {\r
- TxData->FragmentTable[Index].FragmentBuffer = Pkt->BlockOp[Index].Head;\r
- TxData->FragmentTable[Index].FragmentLength = Pkt->BlockOp[Index].Size;\r
- }\r
+ IP4_COPY_ADDRESS (&Ip4TxData->DestinationAddress, Dest);\r
\r
- //\r
- // Set the fields of SndToken\r
- //\r
- SndToken->Packet.TxData = TxData;\r
+ Ip4TxData->OverrideData = &OverrideData->Ip4OverrideData;\r
+ Ip4TxData->OptionsLength = 0;\r
+ Ip4TxData->OptionsBuffer = NULL;\r
+ Ip4TxData->TotalDataLength = Pkt->TotalSize;\r
+ Ip4TxData->FragmentCount = FragmentCount;\r
+\r
+ //\r
+ // Set the fields of SndToken\r
+ //\r
+ SndEntry->SndToken.Ip4Token.Event = Event;\r
+ SndEntry->SndToken.Ip4Token.Packet.TxData = Ip4TxData;\r
+ } else {\r
+\r
+ Ip6TxData = &TxData->Ip6TxData;\r
+\r
+ if (Dest != NULL) {\r
+ CopyMem (&Ip6TxData->DestinationAddress, Dest, sizeof (EFI_IPv6_ADDRESS));\r
+ } else {\r
+ ZeroMem (&Ip6TxData->DestinationAddress, sizeof (EFI_IPv6_ADDRESS));\r
+ }\r
+\r
+ Ip6TxData->OverrideData = &OverrideData->Ip6OverrideData;\r
+ Ip6TxData->DataLength = Pkt->TotalSize;\r
+ Ip6TxData->FragmentCount = FragmentCount;\r
+ Ip6TxData->ExtHdrsLength = 0;\r
+ Ip6TxData->ExtHdrs = NULL;\r
+\r
+ //\r
+ // Set the fields of SndToken\r
+ //\r
+ SndEntry->SndToken.Ip6Token.Event = Event;\r
+ SndEntry->SndToken.Ip6Token.Packet.TxData = Ip6TxData;\r
+ }\r
\r
//\r
// Set the fields of SndEntry\r
//\r
SndEntry->IpIo = IpIo;\r
- SndEntry->Ip = Sender;\r
+ SndEntry->Ip = Sender;\r
SndEntry->Context = Context;\r
SndEntry->NotifyData = NotifyData;\r
\r
SndEntry->Pkt = Pkt;\r
NET_GET_REF (Pkt);\r
\r
- SndEntry->SndToken = SndToken;\r
-\r
- NetListInsertTail (&IpIo->PendingSndList, &SndEntry->Entry);\r
+ InsertTailList (&IpIo->PendingSndList, &SndEntry->Entry);\r
\r
return SndEntry;\r
\r
-ReleaseResource:\r
- NetFreePool (TxData);\r
+ON_ERROR:\r
+\r
+ if (OverrideData != NULL) {\r
+ FreePool (OverrideData);\r
+ }\r
\r
-ReleaseEvent:\r
- gBS->CloseEvent (SndToken->Event);\r
+ if (TxData != NULL) {\r
+ FreePool (TxData);\r
+ }\r
\r
-ReleaseSndToken:\r
- NetFreePool (SndToken);\r
+ if (SndEntry != NULL) {\r
+ FreePool (SndEntry);\r
+ }\r
\r
-ReleaseSndEntry:\r
- NetFreePool (SndEntry);\r
+ if (Event != NULL) {\r
+ gBS->CloseEvent (Event);\r
+ }\r
\r
return NULL;\r
}\r
/**\r
Destroy the SndEntry.\r
\r
- @param SndEntry Pointer to the send entry to be destroyed.\r
+ This function pairs with IpIoCreateSndEntry().\r
\r
- @return None.\r
+ @param[in] SndEntry Pointer to the send entry to be destroyed.\r
\r
**/\r
-STATIC\r
VOID\r
IpIoDestroySndEntry (\r
IN IP_IO_SEND_ENTRY *SndEntry\r
)\r
{\r
- EFI_IP4_TRANSMIT_DATA *TxData;\r
+ EFI_EVENT Event;\r
+ IP_IO_IP_TX_DATA *TxData;\r
+ IP_IO_OVERRIDE *Override;\r
+\r
+ if (SndEntry->IpIo->IpVersion == IP_VERSION_4) {\r
+ Event = SndEntry->SndToken.Ip4Token.Event;\r
+ TxData = (IP_IO_IP_TX_DATA *) SndEntry->SndToken.Ip4Token.Packet.TxData;\r
+ Override = (IP_IO_OVERRIDE *) TxData->Ip4TxData.OverrideData;\r
+ } else if (SndEntry->IpIo->IpVersion == IP_VERSION_6) {\r
+ Event = SndEntry->SndToken.Ip6Token.Event;\r
+ TxData = (IP_IO_IP_TX_DATA *) SndEntry->SndToken.Ip6Token.Packet.TxData;\r
+ Override = (IP_IO_OVERRIDE *) TxData->Ip6TxData.OverrideData;\r
+ } else {\r
+ return ;\r
+ }\r
\r
- TxData = SndEntry->SndToken->Packet.TxData;\r
+ gBS->CloseEvent (Event);\r
\r
- if (NULL != TxData->OverrideData) {\r
- NetFreePool (TxData->OverrideData);\r
+ FreePool (TxData);\r
+\r
+ if (NULL != Override) {\r
+ FreePool (Override);\r
}\r
\r
- NetFreePool (TxData);\r
NetbufFree (SndEntry->Pkt);\r
- gBS->CloseEvent (SndEntry->SndToken->Event);\r
\r
- NetFreePool (SndEntry->SndToken);\r
- NetListRemoveEntry (&SndEntry->Entry);\r
+ RemoveEntryList (&SndEntry->Entry);\r
\r
- NetFreePool (SndEntry);\r
+ FreePool (SndEntry);\r
}\r
\r
\r
/**\r
Notify function for IP transmit token.\r
\r
- @param Context The context passed in by the event notifier.\r
-\r
- @return None.\r
+ @param[in] Context The context passed in by the event notifier.\r
\r
**/\r
-STATIC\r
VOID\r
EFIAPI\r
IpIoTransmitHandlerDpc (\r
{\r
IP_IO *IpIo;\r
IP_IO_SEND_ENTRY *SndEntry;\r
+ EFI_STATUS Status;\r
\r
SndEntry = (IP_IO_SEND_ENTRY *) Context;\r
\r
IpIo = SndEntry->IpIo;\r
\r
- if (IpIo->PktSentNotify && SndEntry->NotifyData) {\r
+ if (IpIo->IpVersion == IP_VERSION_4) {\r
+ Status = SndEntry->SndToken.Ip4Token.Status;\r
+ } else if (IpIo->IpVersion == IP_VERSION_6){\r
+ Status = SndEntry->SndToken.Ip6Token.Status;\r
+ } else {\r
+ return ;\r
+ }\r
+\r
+ if ((IpIo->PktSentNotify != NULL) && (SndEntry->NotifyData != NULL)) {\r
IpIo->PktSentNotify (\r
- SndEntry->SndToken->Status,\r
+ Status,\r
SndEntry->Context,\r
SndEntry->Ip,\r
SndEntry->NotifyData\r
IpIoDestroySndEntry (SndEntry);\r
}\r
\r
+\r
/**\r
Notify function for IP transmit token.\r
\r
- @param Event The event signaled.\r
- @param Context The context passed in by the event notifier.\r
-\r
- @return None.\r
+ @param[in] Event The event signaled.\r
+ @param[in] Context The context passed in by the event notifier.\r
\r
**/\r
-\r
-STATIC\r
VOID\r
EFIAPI\r
IpIoTransmitHandler (\r
//\r
// Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK\r
//\r
- NetLibQueueDpc (TPL_CALLBACK, IpIoTransmitHandlerDpc, Context);\r
+ QueueDpc (TPL_CALLBACK, IpIoTransmitHandlerDpc, Context);\r
}\r
\r
\r
/**\r
The dummy handler for the dummy IP receive token.\r
\r
- @param Context The context passed in by the event notifier.\r
-\r
- @return None.\r
+ @param[in] Context The context passed in by the event notifier.\r
\r
**/\r
-STATIC\r
VOID\r
EFIAPI\r
IpIoDummyHandlerDpc (\r
)\r
{\r
IP_IO_IP_INFO *IpInfo;\r
- EFI_IP4_COMPLETION_TOKEN *DummyToken;\r
+ EFI_STATUS Status;\r
+ EFI_EVENT RecycleEvent;\r
\r
IpInfo = (IP_IO_IP_INFO *) Context;\r
- DummyToken = &(IpInfo->DummyRcvToken);\r
\r
- if (EFI_ABORTED == DummyToken->Status) {\r
+ if ((IpInfo->IpVersion != IP_VERSION_4) && (IpInfo->IpVersion != IP_VERSION_6)) {\r
+ return ;\r
+ }\r
+\r
+ RecycleEvent = NULL;\r
+\r
+ if (IpInfo->IpVersion == IP_VERSION_4) {\r
+ Status = IpInfo->DummyRcvToken.Ip4Token.Status;\r
+\r
+ if (IpInfo->DummyRcvToken.Ip4Token.Packet.RxData != NULL) {\r
+ RecycleEvent = IpInfo->DummyRcvToken.Ip4Token.Packet.RxData->RecycleSignal;\r
+ }\r
+ } else {\r
+ Status = IpInfo->DummyRcvToken.Ip6Token.Status;\r
+\r
+ if (IpInfo->DummyRcvToken.Ip6Token.Packet.RxData != NULL) {\r
+ RecycleEvent = IpInfo->DummyRcvToken.Ip6Token.Packet.RxData->RecycleSignal;\r
+ }\r
+ }\r
+\r
+\r
+\r
+ if (EFI_ABORTED == Status) {\r
//\r
// The reception is actively aborted by the consumer, directly return.\r
//\r
return;\r
- } else if (EFI_SUCCESS == DummyToken->Status) {\r
- ASSERT (DummyToken->Packet.RxData);\r
+ } else if (EFI_SUCCESS == Status) {\r
+ //\r
+ // Recycle the RxData.\r
+ //\r
+ ASSERT (RecycleEvent != NULL);\r
\r
- gBS->SignalEvent (DummyToken->Packet.RxData->RecycleSignal);\r
+ gBS->SignalEvent (RecycleEvent);\r
}\r
\r
- IpInfo->Ip->Receive (IpInfo->Ip, DummyToken);\r
+ //\r
+ // Continue the receive.\r
+ //\r
+ if (IpInfo->IpVersion == IP_VERSION_4) {\r
+ IpInfo->Ip.Ip4->Receive (\r
+ IpInfo->Ip.Ip4,\r
+ &IpInfo->DummyRcvToken.Ip4Token\r
+ );\r
+ } else {\r
+ IpInfo->Ip.Ip6->Receive (\r
+ IpInfo->Ip.Ip6,\r
+ &IpInfo->DummyRcvToken.Ip6Token\r
+ );\r
+ }\r
}\r
\r
\r
/**\r
- Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK.\r
+ This function add IpIoDummyHandlerDpc to the end of the DPC queue.\r
\r
- @param Event The event signaled.\r
- @param Context The context passed in by the event notifier.\r
-\r
- @return None.\r
+ @param[in] Event The event signaled.\r
+ @param[in] Context The context passed in by the event notifier.\r
\r
**/\r
-STATIC\r
VOID\r
EFIAPI\r
IpIoDummyHandler (\r
//\r
// Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK\r
//\r
- NetLibQueueDpc (TPL_CALLBACK, IpIoDummyHandlerDpc, Context);\r
+ QueueDpc (TPL_CALLBACK, IpIoDummyHandlerDpc, Context);\r
}\r
\r
\r
Notify function for the IP receive token, used to process\r
the received IP packets.\r
\r
- @param Context The context passed in by the event notifier.\r
-\r
- @return None.\r
+ @param[in] Context The context passed in by the event notifier.\r
\r
**/\r
-STATIC\r
VOID\r
EFIAPI\r
IpIoListenHandlerDpc (\r
{\r
IP_IO *IpIo;\r
EFI_STATUS Status;\r
- EFI_IP4_RECEIVE_DATA *RxData;\r
- EFI_IP4_PROTOCOL *Ip;\r
+ IP_IO_IP_RX_DATA *RxData;\r
EFI_NET_SESSION_DATA Session;\r
NET_BUF *Pkt;\r
\r
- IpIo = (IP_IO *) Context;\r
+ IpIo = (IP_IO *) Context;\r
\r
- Ip = IpIo->Ip;\r
- Status = IpIo->RcvToken.Status;\r
- RxData = IpIo->RcvToken.Packet.RxData;\r
+ if (IpIo->IpVersion == IP_VERSION_4) {\r
+ Status = IpIo->RcvToken.Ip4Token.Status;\r
+ RxData = (IP_IO_IP_RX_DATA *) IpIo->RcvToken.Ip4Token.Packet.RxData;\r
+ } else if (IpIo->IpVersion == IP_VERSION_6) {\r
+ Status = IpIo->RcvToken.Ip6Token.Status;\r
+ RxData = (IP_IO_IP_RX_DATA *) IpIo->RcvToken.Ip6Token.Packet.RxData;\r
+ } else {\r
+ return;\r
+ }\r
\r
if (EFI_ABORTED == Status) {\r
//\r
return;\r
}\r
\r
- if (((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) || (NULL == RxData)) {\r
+ if ((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) {\r
//\r
- // Only process the normal packets and the icmp error packets, if RxData is NULL\r
- // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although\r
- // this should be a bug of the low layer (IP).\r
+ // Only process the normal packets and the icmp error packets.\r
//\r
+ if (RxData != NULL) {\r
+ goto CleanUp;\r
+ } else {\r
+ goto Resume;\r
+ }\r
+ }\r
+\r
+ //\r
+ // if RxData is NULL with Status == EFI_SUCCESS or EFI_ICMP_ERROR, this should be a code issue in the low layer (IP).\r
+ //\r
+ ASSERT (RxData != NULL);\r
+ if (RxData == NULL) {\r
goto Resume;\r
}\r
\r
goto CleanUp;\r
}\r
\r
- if ((EFI_IP4 (RxData->Header->SourceAddress) != 0) &&\r
- !Ip4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), 0)) {\r
+ if (IpIo->IpVersion == IP_VERSION_4) {\r
+ ASSERT (RxData->Ip4RxData.Header != NULL);\r
+ if (IP4_IS_LOCAL_BROADCAST (EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress))) {\r
+ //\r
+ // The source address is a broadcast address, discard it.\r
+ //\r
+ goto CleanUp;\r
+ }\r
+ if ((EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress) != 0) &&\r
+ (IpIo->SubnetMask != 0) &&\r
+ IP4_NET_EQUAL (IpIo->StationIp, EFI_NTOHL (((EFI_IP4_RECEIVE_DATA *) RxData)->Header->SourceAddress), IpIo->SubnetMask) &&\r
+ !NetIp4IsUnicast (EFI_NTOHL (((EFI_IP4_RECEIVE_DATA *) RxData)->Header->SourceAddress), IpIo->SubnetMask)) {\r
+ //\r
+ // The source address doesn't match StationIp and it's not a unicast IP address, discard it.\r
+ //\r
+ goto CleanUp;\r
+ }\r
+\r
+ if (RxData->Ip4RxData.DataLength == 0) {\r
+ //\r
+ // Discard zero length data payload packet.\r
+ //\r
+ goto CleanUp;\r
+ }\r
+\r
//\r
- // The source address is not zero and it's not a unicast IP address, discard it.\r
+ // The fragment should always be valid for non-zero length packet.\r
//\r
- goto CleanUp;\r
- }\r
+ ASSERT (RxData->Ip4RxData.FragmentCount != 0);\r
\r
- //\r
- // Create a netbuffer representing packet\r
- //\r
- Pkt = NetbufFromExt (\r
- (NET_FRAGMENT *) RxData->FragmentTable,\r
- RxData->FragmentCount,\r
- 0,\r
- 0,\r
- IpIoExtFree,\r
- RxData->RecycleSignal\r
- );\r
- if (NULL == Pkt) {\r
- goto CleanUp;\r
- }\r
+ //\r
+ // Create a netbuffer representing IPv4 packet\r
+ //\r
+ Pkt = NetbufFromExt (\r
+ (NET_FRAGMENT *) RxData->Ip4RxData.FragmentTable,\r
+ RxData->Ip4RxData.FragmentCount,\r
+ 0,\r
+ 0,\r
+ IpIoExtFree,\r
+ RxData->Ip4RxData.RecycleSignal\r
+ );\r
+ if (NULL == Pkt) {\r
+ goto CleanUp;\r
+ }\r
\r
- //\r
- // Create a net session\r
- //\r
- Session.Source = EFI_IP4 (RxData->Header->SourceAddress);\r
- Session.Dest = EFI_IP4 (RxData->Header->DestinationAddress);\r
- Session.IpHdr = RxData->Header;\r
+ //\r
+ // Create a net session\r
+ //\r
+ Session.Source.Addr[0] = EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress);\r
+ Session.Dest.Addr[0] = EFI_IP4 (RxData->Ip4RxData.Header->DestinationAddress);\r
+ Session.IpHdr.Ip4Hdr = RxData->Ip4RxData.Header;\r
+ Session.IpHdrLen = RxData->Ip4RxData.HeaderLength;\r
+ Session.IpVersion = IP_VERSION_4;\r
+ } else {\r
+ ASSERT (RxData->Ip6RxData.Header != NULL);\r
+ if (!NetIp6IsValidUnicast(&RxData->Ip6RxData.Header->SourceAddress)) {\r
+ goto CleanUp;\r
+ }\r
+\r
+ if (RxData->Ip6RxData.DataLength == 0) {\r
+ //\r
+ // Discard zero length data payload packet.\r
+ //\r
+ goto CleanUp;\r
+ }\r
+\r
+ //\r
+ // The fragment should always be valid for non-zero length packet.\r
+ //\r
+ ASSERT (RxData->Ip6RxData.FragmentCount != 0);\r
+\r
+ //\r
+ // Create a netbuffer representing IPv6 packet\r
+ //\r
+ Pkt = NetbufFromExt (\r
+ (NET_FRAGMENT *) RxData->Ip6RxData.FragmentTable,\r
+ RxData->Ip6RxData.FragmentCount,\r
+ 0,\r
+ 0,\r
+ IpIoExtFree,\r
+ RxData->Ip6RxData.RecycleSignal\r
+ );\r
+ if (NULL == Pkt) {\r
+ goto CleanUp;\r
+ }\r
+\r
+ //\r
+ // Create a net session\r
+ //\r
+ CopyMem (\r
+ &Session.Source,\r
+ &RxData->Ip6RxData.Header->SourceAddress,\r
+ sizeof(EFI_IPv6_ADDRESS)\r
+ );\r
+ CopyMem (\r
+ &Session.Dest,\r
+ &RxData->Ip6RxData.Header->DestinationAddress,\r
+ sizeof(EFI_IPv6_ADDRESS)\r
+ );\r
+ Session.IpHdr.Ip6Hdr = RxData->Ip6RxData.Header;\r
+ Session.IpHdrLen = RxData->Ip6RxData.HeaderLength;\r
+ Session.IpVersion = IP_VERSION_6;\r
+ }\r
\r
if (EFI_SUCCESS == Status) {\r
\r
- IpIo->PktRcvdNotify (EFI_SUCCESS, (ICMP_ERROR) 0, &Session, Pkt, IpIo->RcvdContext);\r
+ IpIo->PktRcvdNotify (EFI_SUCCESS, 0, &Session, Pkt, IpIo->RcvdContext);\r
} else {\r
//\r
// Status is EFI_ICMP_ERROR\r
goto Resume;\r
\r
CleanUp:\r
- gBS->SignalEvent (RxData->RecycleSignal);\r
+\r
+ if (IpIo->IpVersion == IP_VERSION_4){\r
+ gBS->SignalEvent (RxData->Ip4RxData.RecycleSignal);\r
+ } else {\r
+ gBS->SignalEvent (RxData->Ip6RxData.RecycleSignal);\r
+ }\r
\r
Resume:\r
- Ip->Receive (Ip, &(IpIo->RcvToken));\r
-}\r
\r
+ if (IpIo->IpVersion == IP_VERSION_4){\r
+ IpIo->Ip.Ip4->Receive (IpIo->Ip.Ip4, &(IpIo->RcvToken.Ip4Token));\r
+ } else {\r
+ IpIo->Ip.Ip6->Receive (IpIo->Ip.Ip6, &(IpIo->RcvToken.Ip6Token));\r
+ }\r
+}\r
\r
/**\r
- Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK\r
+ This function add IpIoListenHandlerDpc to the end of the DPC queue.\r
\r
- @param Event The event signaled.\r
- @param Context The context passed in by the event notifier.\r
-\r
- @return None.\r
+ @param[in] Event The event signaled.\r
+ @param[in] Context The context passed in by the event notifier.\r
\r
**/\r
-STATIC\r
VOID\r
EFIAPI\r
IpIoListenHandler (\r
//\r
// Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK\r
//\r
- NetLibQueueDpc (TPL_CALLBACK, IpIoListenHandlerDpc, Context);\r
+ QueueDpc (TPL_CALLBACK, IpIoListenHandlerDpc, Context);\r
}\r
\r
\r
/**\r
Create a new IP_IO instance.\r
\r
- @param Image The image handle of an IP_IO consumer protocol.\r
- @param Controller The controller handle of an IP_IO consumer protocol\r
- installed on.\r
+ If IpVersion is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
+\r
+ This function uses IP4/IP6 service binding protocol in Controller to create\r
+ an IP4/IP6 child (aka IP4/IP6 instance).\r
\r
- @return Pointer to a newly created IP_IO instance.\r
+ @param[in] Image The image handle of the driver or application that\r
+ consumes IP_IO.\r
+ @param[in] Controller The controller handle that has IP4 or IP6 service\r
+ binding protocol installed.\r
+ @param[in] IpVersion The version of the IP protocol to use, either\r
+ IPv4 or IPv6.\r
+\r
+ @return Pointer to a newly created IP_IO instance, or NULL if failed.\r
\r
**/\r
IP_IO *\r
+EFIAPI\r
IpIoCreate (\r
IN EFI_HANDLE Image,\r
- IN EFI_HANDLE Controller\r
+ IN EFI_HANDLE Controller,\r
+ IN UINT8 IpVersion\r
)\r
{\r
EFI_STATUS Status;\r
IP_IO *IpIo;\r
+ EFI_EVENT Event;\r
\r
- IpIo = NetAllocateZeroPool (sizeof (IP_IO));\r
+ ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
+\r
+ IpIo = AllocateZeroPool (sizeof (IP_IO));\r
if (NULL == IpIo) {\r
return NULL;\r
}\r
\r
- NetListInit (&(IpIo->PendingSndList));\r
- NetListInit (&(IpIo->IpList));\r
+ InitializeListHead (&(IpIo->PendingSndList));\r
+ InitializeListHead (&(IpIo->IpList));\r
IpIo->Controller = Controller;\r
IpIo->Image = Image;\r
+ IpIo->IpVersion = IpVersion;\r
+ Event = NULL;\r
\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_SIGNAL,\r
- NET_TPL_EVENT,\r
+ TPL_NOTIFY,\r
IpIoListenHandler,\r
IpIo,\r
- &(IpIo->RcvToken.Event)\r
+ &Event\r
);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseIpIo;\r
}\r
\r
+ if (IpVersion == IP_VERSION_4) {\r
+ IpIo->RcvToken.Ip4Token.Event = Event;\r
+ } else {\r
+ IpIo->RcvToken.Ip6Token.Event = Event;\r
+ }\r
+\r
//\r
// Create an IP child and open IP protocol\r
//\r
Controller,\r
Image,\r
&IpIo->ChildHandle,\r
- (VOID **)&(IpIo->Ip)\r
+ IpVersion,\r
+ (VOID **) & (IpIo->Ip)\r
);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseIpIo;\r
\r
ReleaseIpIo:\r
\r
- if (NULL != IpIo->RcvToken.Event) {\r
- gBS->CloseEvent (IpIo->RcvToken.Event);\r
+ if (Event != NULL) {\r
+ gBS->CloseEvent (Event);\r
}\r
\r
- NetFreePool (IpIo);\r
+ gBS->FreePool (IpIo);\r
\r
return NULL;\r
}\r
/**\r
Open an IP_IO instance for use.\r
\r
- @param IpIo Pointer to an IP_IO instance that needs to open.\r
- @param OpenData The configuration data for the IP_IO instance.\r
+ If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
\r
- @retval EFI_SUCCESS The IP_IO instance opened with OpenData\r
- successfully.\r
- @retval other Error condition occurred.\r
+ This function is called after IpIoCreate(). It is used for configuring the IP\r
+ instance and register the callbacks and their context data for sending and\r
+ receiving IP packets.\r
+\r
+ @param[in, out] IpIo Pointer to an IP_IO instance that needs\r
+ to open.\r
+ @param[in] OpenData The configuration data and callbacks for\r
+ the IP_IO instance.\r
+\r
+ @retval EFI_SUCCESS The IP_IO instance opened with OpenData\r
+ successfully.\r
+ @retval EFI_ACCESS_DENIED The IP_IO instance is configured, avoid to\r
+ reopen it.\r
+ @retval EFI_UNSUPPORTED IPv4 RawData mode is no supported.\r
+ @retval EFI_INVALID_PARAMETER Invalid input parameter.\r
+ @retval Others Error condition occurred.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
IpIoOpen (\r
- IN IP_IO *IpIo,\r
- IN IP_IO_OPEN_DATA *OpenData\r
+ IN OUT IP_IO *IpIo,\r
+ IN IP_IO_OPEN_DATA *OpenData\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_IP4_PROTOCOL *Ip;\r
+ UINT8 IpVersion;\r
+\r
+ if (IpIo == NULL || OpenData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
if (IpIo->IsConfigured) {\r
return EFI_ACCESS_DENIED;\r
}\r
\r
- Ip = IpIo->Ip;\r
+ IpVersion = IpIo->IpVersion;\r
+\r
+ ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
\r
//\r
// configure ip\r
//\r
- Status = Ip->Configure (Ip, &OpenData->IpConfigData);\r
+ if (IpVersion == IP_VERSION_4){\r
+ //\r
+ // RawData mode is no supported.\r
+ //\r
+ ASSERT (!OpenData->IpConfigData.Ip4CfgData.RawData);\r
+ if (OpenData->IpConfigData.Ip4CfgData.RawData) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (!OpenData->IpConfigData.Ip4CfgData.UseDefaultAddress) {\r
+ IpIo->StationIp = EFI_NTOHL (OpenData->IpConfigData.Ip4CfgData.StationAddress);\r
+ IpIo->SubnetMask = EFI_NTOHL (OpenData->IpConfigData.Ip4CfgData.SubnetMask);\r
+ }\r
+\r
+ Status = IpIo->Ip.Ip4->Configure (\r
+ IpIo->Ip.Ip4,\r
+ &OpenData->IpConfigData.Ip4CfgData\r
+ );\r
+ } else {\r
+\r
+ Status = IpIo->Ip.Ip6->Configure (\r
+ IpIo->Ip.Ip6,\r
+ &OpenData->IpConfigData.Ip6CfgData\r
+ );\r
+ }\r
+\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
//\r
- // bugbug: to delete the default route entry in this Ip, if it is:\r
- // (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified\r
- // its code\r
+ // @bug To delete the default route entry in this Ip, if it is:\r
+ // @bug (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified\r
+ // @bug its code\r
//\r
- Status = Ip->Routes (Ip, TRUE, &mZeroIp4Addr, &mZeroIp4Addr, &mZeroIp4Addr);\r
+ if (IpVersion == IP_VERSION_4){\r
+ Status = IpIo->Ip.Ip4->Routes (\r
+ IpIo->Ip.Ip4,\r
+ TRUE,\r
+ &mZeroIp4Addr,\r
+ &mZeroIp4Addr,\r
+ &mZeroIp4Addr\r
+ );\r
\r
- if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {\r
- return Status;\r
+ if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {\r
+ return Status;\r
+ }\r
}\r
\r
IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;\r
IpIo->RcvdContext = OpenData->RcvdContext;\r
IpIo->SndContext = OpenData->SndContext;\r
\r
- IpIo->Protocol = OpenData->IpConfigData.DefaultProtocol;\r
+ if (IpVersion == IP_VERSION_4){\r
+ IpIo->Protocol = OpenData->IpConfigData.Ip4CfgData.DefaultProtocol;\r
\r
- //\r
- // start to listen incoming packet\r
- //\r
- Status = Ip->Receive (Ip, &(IpIo->RcvToken));\r
- if (EFI_ERROR (Status)) {\r
- Ip->Configure (Ip, NULL);\r
- goto ErrorExit;\r
+ //\r
+ // start to listen incoming packet\r
+ //\r
+ Status = IpIo->Ip.Ip4->Receive (\r
+ IpIo->Ip.Ip4,\r
+ &(IpIo->RcvToken.Ip4Token)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ IpIo->Ip.Ip4->Configure (IpIo->Ip.Ip4, NULL);\r
+ return Status;\r
+ }\r
+\r
+ } else {\r
+\r
+ IpIo->Protocol = OpenData->IpConfigData.Ip6CfgData.DefaultProtocol;\r
+ Status = IpIo->Ip.Ip6->Receive (\r
+ IpIo->Ip.Ip6,\r
+ &(IpIo->RcvToken.Ip6Token)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ IpIo->Ip.Ip6->Configure (IpIo->Ip.Ip6, NULL);\r
+ return Status;\r
+ }\r
}\r
\r
IpIo->IsConfigured = TRUE;\r
- NetListInsertTail (&mActiveIpIoList, &IpIo->Entry);\r
-\r
-ErrorExit:\r
+ InsertTailList (&mActiveIpIoList, &IpIo->Entry);\r
\r
return Status;\r
}\r
/**\r
Stop an IP_IO instance.\r
\r
- @param IpIo Pointer to the IP_IO instance that needs to stop.\r
+ If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
+\r
+ This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all\r
+ the pending send/receive tokens will be canceled.\r
+\r
+ @param[in, out] IpIo Pointer to the IP_IO instance that needs to stop.\r
\r
- @retval EFI_SUCCESS The IP_IO instance stopped successfully.\r
- @retval other Error condition occurred.\r
+ @retval EFI_SUCCESS The IP_IO instance stopped successfully.\r
+ @retval EFI_INVALID_PARAMETER Invalid input parameter.\r
+ @retval Others Error condition occurred.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
IpIoStop (\r
- IN IP_IO *IpIo\r
+ IN OUT IP_IO *IpIo\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_IP4_PROTOCOL *Ip;\r
IP_IO_IP_INFO *IpInfo;\r
+ UINT8 IpVersion;\r
+\r
+ if (IpIo == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
if (!IpIo->IsConfigured) {\r
return EFI_SUCCESS;\r
}\r
\r
+ IpVersion = IpIo->IpVersion;\r
+\r
+ ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
+\r
//\r
// Remove the IpIo from the active IpIo list.\r
//\r
- NetListRemoveEntry (&IpIo->Entry);\r
-\r
- Ip = IpIo->Ip;\r
+ RemoveEntryList (&IpIo->Entry);\r
\r
//\r
// Configure NULL Ip\r
//\r
- Status = Ip->Configure (Ip, NULL);\r
+ if (IpVersion == IP_VERSION_4) {\r
+ Status = IpIo->Ip.Ip4->Configure (IpIo->Ip.Ip4, NULL);\r
+ } else {\r
+ Status = IpIo->Ip.Ip6->Configure (IpIo->Ip.Ip6, NULL);\r
+ }\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
// Detroy the Ip List used by IpIo\r
//\r
\r
- while (!NetListIsEmpty (&(IpIo->IpList))) {\r
+ while (!IsListEmpty (&(IpIo->IpList))) {\r
IpInfo = NET_LIST_HEAD (&(IpIo->IpList), IP_IO_IP_INFO, Entry);\r
\r
IpIoRemoveIp (IpIo, IpInfo);\r
}\r
\r
//\r
- // All pending snd tokens should be flushed by reseting the IP instances.\r
+ // All pending send tokens should be flushed by resetting the IP instances.\r
//\r
- ASSERT (NetListIsEmpty (&IpIo->PendingSndList));\r
+ ASSERT (IsListEmpty (&IpIo->PendingSndList));\r
\r
//\r
// Close the receive event.\r
//\r
- gBS->CloseEvent (IpIo->RcvToken.Event);\r
+ if (IpVersion == IP_VERSION_4){\r
+ gBS->CloseEvent (IpIo->RcvToken.Ip4Token.Event);\r
+ } else {\r
+ gBS->CloseEvent (IpIo->RcvToken.Ip6Token.Event);\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
/**\r
Destroy an IP_IO instance.\r
\r
- @param IpIo Pointer to the IP_IO instance that needs to\r
- destroy.\r
+ This function is paired with IpIoCreate(). The IP_IO will be closed first.\r
+ Resource will be freed afterwards. See IpIoCloseProtocolDestroyIpChild().\r
+\r
+ @param[in, out] IpIo Pointer to the IP_IO instance that needs to be\r
+ destroyed.\r
\r
- @retval EFI_SUCCESS The IP_IO instance destroyed successfully.\r
- @retval other Error condition occurred.\r
+ @retval EFI_SUCCESS The IP_IO instance destroyed successfully.\r
+ @retval Others Error condition occurred.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
IpIoDestroy (\r
- IN IP_IO *IpIo\r
+ IN OUT IP_IO *IpIo\r
)\r
{\r
+ EFI_STATUS Status;\r
+\r
//\r
// Stop the IpIo.\r
//\r
- IpIoStop (IpIo);\r
+ Status = IpIoStop (IpIo);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
//\r
// Close the IP protocol and destroy the child.\r
//\r
- IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpIo->ChildHandle);\r
+ Status = IpIoCloseProtocolDestroyIpChild (\r
+ IpIo->Controller,\r
+ IpIo->Image,\r
+ IpIo->ChildHandle,\r
+ IpIo->IpVersion\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
- NetFreePool (IpIo);\r
+ gBS->FreePool (IpIo);\r
\r
return EFI_SUCCESS;\r
}\r
/**\r
Send out an IP packet.\r
\r
- @param IpIo Pointer to an IP_IO instance used for sending IP\r
- packet.\r
- @param Pkt Pointer to the IP packet to be sent.\r
- @param Sender The IP protocol instance used for sending.\r
- @param NotifyData\r
- @param Dest The destination IP address to send this packet to.\r
- @param OverrideData The data to override some configuration of the IP\r
- instance used for sending.\r
-\r
- @retval EFI_SUCCESS The operation is completed successfully.\r
- @retval EFI_NOT_STARTED The IpIo is not configured.\r
- @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
+ This function is called after IpIoOpen(). The data to be sent is wrapped in\r
+ Pkt. The IP instance wrapped in IpIo is used for sending by default but can be\r
+ overriden by Sender. Other sending configs, like source address and gateway\r
+ address etc., are specified in OverrideData.\r
+\r
+ @param[in, out] IpIo Pointer to an IP_IO instance used for sending IP\r
+ packet.\r
+ @param[in, out] Pkt Pointer to the IP packet to be sent.\r
+ @param[in] Sender The IP protocol instance used for sending.\r
+ @param[in] Context Optional context data.\r
+ @param[in] NotifyData Optional notify data.\r
+ @param[in] Dest The destination IP address to send this packet to.\r
+ This parameter is optional when using IPv6.\r
+ @param[in] OverrideData The data to override some configuration of the IP\r
+ instance used for sending.\r
+\r
+ @retval EFI_SUCCESS The operation is completed successfully.\r
+ @retval EFI_INVALID_PARAMETER The input parameter is not correct.\r
+ @retval EFI_NOT_STARTED The IpIo is not configured.\r
+ @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
+ @retval Others Error condition occurred.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
IpIoSend (\r
- IN IP_IO *IpIo,\r
- IN NET_BUF *Pkt,\r
- IN IP_IO_IP_INFO *Sender,\r
- IN VOID *Context OPTIONAL,\r
- IN VOID *NotifyData OPTIONAL,\r
- IN IP4_ADDR Dest,\r
- IN IP_IO_OVERRIDE *OverrideData\r
+ IN OUT IP_IO *IpIo,\r
+ IN OUT NET_BUF *Pkt,\r
+ IN IP_IO_IP_INFO *Sender OPTIONAL,\r
+ IN VOID *Context OPTIONAL,\r
+ IN VOID *NotifyData OPTIONAL,\r
+ IN EFI_IP_ADDRESS *Dest OPTIONAL,\r
+ IN IP_IO_OVERRIDE *OverrideData OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_IP4_PROTOCOL *Ip;\r
+ IP_IO_IP_PROTOCOL Ip;\r
IP_IO_SEND_ENTRY *SndEntry;\r
\r
+ if ((IpIo == NULL) || (Pkt == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((IpIo->IpVersion == IP_VERSION_4) && (Dest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
if (!IpIo->IsConfigured) {\r
return EFI_NOT_STARTED;\r
}\r
//\r
// Send this Packet\r
//\r
- Status = Ip->Transmit (Ip, SndEntry->SndToken);\r
+ if (IpIo->IpVersion == IP_VERSION_4){\r
+ Status = Ip.Ip4->Transmit (\r
+ Ip.Ip4,\r
+ &SndEntry->SndToken.Ip4Token\r
+ );\r
+ } else {\r
+ Status = Ip.Ip6->Transmit (\r
+ Ip.Ip6,\r
+ &SndEntry->SndToken.Ip6Token\r
+ );\r
+ }\r
+\r
if (EFI_ERROR (Status)) {\r
IpIoDestroySndEntry (SndEntry);\r
}\r
/**\r
Cancel the IP transmit token which wraps this Packet.\r
\r
- @param IpIo Pointer to the IP_IO instance.\r
- @param Packet Pointer to the packet to cancel.\r
+ If IpIo is NULL, then ASSERT().\r
+ If Packet is NULL, then ASSERT().\r
\r
- @return N/A.\r
+ @param[in] IpIo Pointer to the IP_IO instance.\r
+ @param[in] Packet Pointer to the packet of NET_BUF to cancel.\r
\r
**/\r
VOID\r
+EFIAPI\r
IpIoCancelTxToken (\r
IN IP_IO *IpIo,\r
IN VOID *Packet\r
)\r
{\r
- NET_LIST_ENTRY *Node;\r
+ LIST_ENTRY *Node;\r
IP_IO_SEND_ENTRY *SndEntry;\r
- EFI_IP4_PROTOCOL *Ip;\r
+ IP_IO_IP_PROTOCOL Ip;\r
\r
- ASSERT (IpIo && Packet);\r
+ ASSERT ((IpIo != NULL) && (Packet != NULL));\r
\r
NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {\r
\r
if (SndEntry->Pkt == Packet) {\r
\r
Ip = SndEntry->Ip;\r
- Ip->Cancel (Ip, SndEntry->SndToken);\r
+\r
+ if (IpIo->IpVersion == IP_VERSION_4) {\r
+ Ip.Ip4->Cancel (\r
+ Ip.Ip4,\r
+ &SndEntry->SndToken.Ip4Token\r
+ );\r
+ } else {\r
+ Ip.Ip6->Cancel (\r
+ Ip.Ip6,\r
+ &SndEntry->SndToken.Ip6Token\r
+ );\r
+ }\r
\r
break;\r
}\r
/**\r
Add a new IP instance for sending data.\r
\r
- @param IpIo Pointer to a IP_IO instance to add a new IP\r
- instance for sending purpose.\r
+ If IpIo is NULL, then ASSERT().\r
+ If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
+\r
+ The function is used to add the IP_IO to the IP_IO sending list. The caller\r
+ can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send\r
+ data.\r
\r
- @return Pointer to the created IP_IO_IP_INFO structure, NULL is failed.\r
+ @param[in, out] IpIo Pointer to a IP_IO instance to add a new IP\r
+ instance for sending purpose.\r
+\r
+ @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.\r
\r
**/\r
IP_IO_IP_INFO *\r
+EFIAPI\r
IpIoAddIp (\r
- IN IP_IO *IpIo\r
+ IN OUT IP_IO *IpIo\r
)\r
{\r
EFI_STATUS Status;\r
IP_IO_IP_INFO *IpInfo;\r
+ EFI_EVENT Event;\r
\r
- ASSERT (IpIo);\r
+ ASSERT (IpIo != NULL);\r
+ ASSERT ((IpIo->IpVersion == IP_VERSION_4) || (IpIo->IpVersion == IP_VERSION_6));\r
\r
- IpInfo = NetAllocatePool (sizeof (IP_IO_IP_INFO));\r
+ IpInfo = AllocatePool (sizeof (IP_IO_IP_INFO));\r
if (IpInfo == NULL) {\r
- return IpInfo;\r
+ return NULL;\r
}\r
\r
//\r
// Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP\r
// instance.\r
//\r
- NetListInit (&IpInfo->Entry);\r
+ InitializeListHead (&IpInfo->Entry);\r
IpInfo->ChildHandle = NULL;\r
- IpInfo->Addr = 0;\r
- IpInfo->SubnetMask = 0;\r
- IpInfo->RefCnt = 1;\r
+ ZeroMem (&IpInfo->Addr, sizeof (IpInfo->Addr));\r
+ ZeroMem (&IpInfo->PreMask, sizeof (IpInfo->PreMask));\r
+\r
+ IpInfo->RefCnt = 1;\r
+ IpInfo->IpVersion = IpIo->IpVersion;\r
\r
//\r
- // Create the IP instance and open the Ip4 protocol.\r
+ // Create the IP instance and open the IP protocol.\r
//\r
Status = IpIoCreateIpChildOpenProtocol (\r
IpIo->Controller,\r
IpIo->Image,\r
&IpInfo->ChildHandle,\r
+ IpInfo->IpVersion,\r
(VOID **) &IpInfo->Ip\r
);\r
if (EFI_ERROR (Status)) {\r
//\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_SIGNAL,\r
- NET_TPL_EVENT,\r
+ TPL_NOTIFY,\r
IpIoDummyHandler,\r
IpInfo,\r
- &IpInfo->DummyRcvToken.Event\r
+ &Event\r
);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseIpChild;\r
}\r
\r
+ if (IpInfo->IpVersion == IP_VERSION_4) {\r
+ IpInfo->DummyRcvToken.Ip4Token.Event = Event;\r
+ } else {\r
+ IpInfo->DummyRcvToken.Ip6Token.Event = Event;\r
+ }\r
+\r
//\r
// Link this IpInfo into the IpIo.\r
//\r
- NetListInsertTail (&IpIo->IpList, &IpInfo->Entry);\r
+ InsertTailList (&IpIo->IpList, &IpInfo->Entry);\r
\r
return IpInfo;\r
\r
IpIoCloseProtocolDestroyIpChild (\r
IpIo->Controller,\r
IpIo->Image,\r
- IpInfo->ChildHandle\r
+ IpInfo->ChildHandle,\r
+ IpInfo->IpVersion\r
);\r
\r
ReleaseIpInfo:\r
\r
- NetFreePool (IpInfo);\r
+ gBS->FreePool (IpInfo);\r
\r
return NULL;\r
}\r
\r
\r
/**\r
- Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData\r
+ Configure the IP instance of this IpInfo and start the receiving if IpConfigData\r
is not NULL.\r
\r
- @param IpInfo Pointer to the IP_IO_IP_INFO instance.\r
- @param Ip4ConfigData The IP4 configure data used to configure the ip\r
- instance, if NULL the ip instance is reseted. If\r
- UseDefaultAddress is set to TRUE, and the configure\r
- operation succeeds, the default address information\r
- is written back in this Ip4ConfigData.\r
+ If IpInfo is NULL, then ASSERT().\r
+ If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
+\r
+ @param[in, out] IpInfo Pointer to the IP_IO_IP_INFO instance.\r
+ @param[in, out] IpConfigData The IP configure data used to configure the IP\r
+ instance, if NULL the IP instance is reset. If\r
+ UseDefaultAddress is set to TRUE, and the configure\r
+ operation succeeds, the default address information\r
+ is written back in this IpConfigData.\r
\r
- @retval EFI_STATUS The status returned by IP4->Configure or\r
- IP4->Receive.\r
+ @retval EFI_SUCCESS The IP instance of this IpInfo is configured successfully\r
+ or no need to reconfigure it.\r
+ @retval Others Configuration fails.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
IpIoConfigIp (\r
- IN IP_IO_IP_INFO *IpInfo,\r
- IN OUT EFI_IP4_CONFIG_DATA *Ip4ConfigData OPTIONAL\r
+ IN OUT IP_IO_IP_INFO *IpInfo,\r
+ IN OUT VOID *IpConfigData OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_IP4_PROTOCOL *Ip;\r
+ IP_IO_IP_PROTOCOL Ip;\r
+ UINT8 IpVersion;\r
EFI_IP4_MODE_DATA Ip4ModeData;\r
+ EFI_IP6_MODE_DATA Ip6ModeData;\r
\r
- ASSERT (IpInfo);\r
+ ASSERT (IpInfo != NULL);\r
\r
if (IpInfo->RefCnt > 1) {\r
//\r
// This IP instance is shared, don't reconfigure it until it has only one\r
// consumer. Currently, only the tcp children cloned from their passive parent\r
- // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,\r
+ // will share the same IP. So this cases only happens while IpConfigData is NULL,\r
// let the last consumer clean the IP instance.\r
//\r
return EFI_SUCCESS;\r
}\r
\r
+ IpVersion = IpInfo->IpVersion;\r
+ ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
+\r
Ip = IpInfo->Ip;\r
\r
- Status = Ip->Configure (Ip, Ip4ConfigData);\r
+ if (IpInfo->IpVersion == IP_VERSION_4) {\r
+ Status = Ip.Ip4->Configure (Ip.Ip4, IpConfigData);\r
+ } else {\r
+ Status = Ip.Ip6->Configure (Ip.Ip6, IpConfigData);\r
+ }\r
+\r
if (EFI_ERROR (Status)) {\r
- goto OnExit;\r
+ return Status;\r
}\r
\r
- if (Ip4ConfigData != NULL) {\r
+ if (IpConfigData != NULL) {\r
+ if (IpInfo->IpVersion == IP_VERSION_4) {\r
+\r
+ if (((EFI_IP4_CONFIG_DATA *) IpConfigData)->UseDefaultAddress) {\r
+ Status = Ip.Ip4->GetModeData (\r
+ Ip.Ip4,\r
+ &Ip4ModeData,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Ip.Ip4->Configure (Ip.Ip4, NULL);\r
+ return Status;\r
+ }\r
+\r
+ IP4_COPY_ADDRESS (&((EFI_IP4_CONFIG_DATA*) IpConfigData)->StationAddress, &Ip4ModeData.ConfigData.StationAddress);\r
+ IP4_COPY_ADDRESS (&((EFI_IP4_CONFIG_DATA*) IpConfigData)->SubnetMask, &Ip4ModeData.ConfigData.SubnetMask);\r
+ }\r
\r
- if (Ip4ConfigData->UseDefaultAddress) {\r
- Ip->GetModeData (Ip, &Ip4ModeData, NULL, NULL);\r
+ CopyMem (\r
+ &IpInfo->Addr.Addr,\r
+ &((EFI_IP4_CONFIG_DATA *) IpConfigData)->StationAddress,\r
+ sizeof (IP4_ADDR)\r
+ );\r
+ CopyMem (\r
+ &IpInfo->PreMask.SubnetMask,\r
+ &((EFI_IP4_CONFIG_DATA *) IpConfigData)->SubnetMask,\r
+ sizeof (IP4_ADDR)\r
+ );\r
+\r
+ Status = Ip.Ip4->Receive (\r
+ Ip.Ip4,\r
+ &IpInfo->DummyRcvToken.Ip4Token\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Ip.Ip4->Configure (Ip.Ip4, NULL);\r
+ }\r
+ } else {\r
+ Status = Ip.Ip6->GetModeData (\r
+ Ip.Ip6,\r
+ &Ip6ModeData,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Ip.Ip6->Configure (Ip.Ip6, NULL);\r
+ return Status;\r
+ }\r
\r
- Ip4ConfigData->StationAddress = Ip4ModeData.ConfigData.StationAddress;\r
- Ip4ConfigData->SubnetMask = Ip4ModeData.ConfigData.SubnetMask;\r
- }\r
+ if (Ip6ModeData.IsConfigured) {\r
+ CopyMem (\r
+ &((EFI_IP6_CONFIG_DATA *) IpConfigData)->StationAddress,\r
+ &Ip6ModeData.ConfigData.StationAddress,\r
+ sizeof (EFI_IPv6_ADDRESS)\r
+ );\r
\r
- NetCopyMem (&IpInfo->Addr, &Ip4ConfigData->StationAddress, sizeof (IP4_ADDR));\r
- NetCopyMem (&IpInfo->SubnetMask, &Ip4ConfigData->SubnetMask, sizeof (IP4_ADDR));\r
+ if (Ip6ModeData.AddressList != NULL) {\r
+ FreePool (Ip6ModeData.AddressList);\r
+ }\r
\r
- Status = Ip->Receive (Ip, &IpInfo->DummyRcvToken);\r
- if (EFI_ERROR (Status)) {\r
- Ip->Configure (Ip, NULL);\r
+ if (Ip6ModeData.GroupTable != NULL) {\r
+ FreePool (Ip6ModeData.GroupTable);\r
+ }\r
+\r
+ if (Ip6ModeData.RouteTable != NULL) {\r
+ FreePool (Ip6ModeData.RouteTable);\r
+ }\r
+\r
+ if (Ip6ModeData.NeighborCache != NULL) {\r
+ FreePool (Ip6ModeData.NeighborCache);\r
+ }\r
+\r
+ if (Ip6ModeData.PrefixTable != NULL) {\r
+ FreePool (Ip6ModeData.PrefixTable);\r
+ }\r
+\r
+ if (Ip6ModeData.IcmpTypeList != NULL) {\r
+ FreePool (Ip6ModeData.IcmpTypeList);\r
+ }\r
+\r
+ } else {\r
+ Status = EFI_NO_MAPPING;\r
+ return Status;\r
+ }\r
+\r
+ CopyMem (\r
+ &IpInfo->Addr,\r
+ &Ip6ModeData.ConfigData.StationAddress,\r
+ sizeof (EFI_IPv6_ADDRESS)\r
+ );\r
+\r
+ Status = Ip.Ip6->Receive (\r
+ Ip.Ip6,\r
+ &IpInfo->DummyRcvToken.Ip6Token\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Ip.Ip6->Configure (Ip.Ip6, NULL);\r
+ }\r
}\r
} else {\r
-\r
//\r
- // The IP instance is reseted, set the stored Addr and SubnetMask to zero.\r
+ // The IP instance is reset, set the stored Addr and SubnetMask to zero.\r
//\r
- IpInfo->Addr = 0;\r
- IpInfo->SubnetMask =0;\r
+ ZeroMem (&IpInfo->Addr, sizeof (IpInfo->Addr));\r
+ ZeroMem (&IpInfo->PreMask, sizeof (IpInfo->PreMask));\r
}\r
\r
-OnExit:\r
-\r
return Status;\r
}\r
\r
Destroy an IP instance maintained in IpIo->IpList for\r
sending purpose.\r
\r
- @param IpIo Pointer to the IP_IO instance.\r
- @param IpInfo Pointer to the IpInfo to be removed.\r
+ If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
\r
- @return None.\r
+ This function pairs with IpIoAddIp(). The IpInfo is previously created by\r
+ IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance\r
+ will be dstroyed if the RefCnt is zero.\r
+\r
+ @param[in] IpIo Pointer to the IP_IO instance.\r
+ @param[in] IpInfo Pointer to the IpInfo to be removed.\r
\r
**/\r
VOID\r
+EFIAPI\r
IpIoRemoveIp (\r
- IN IP_IO *IpIo,\r
- IN IP_IO_IP_INFO *IpInfo\r
+ IN IP_IO *IpIo,\r
+ IN IP_IO_IP_INFO *IpInfo\r
)\r
{\r
+\r
+ UINT8 IpVersion;\r
+\r
+ if (IpIo == NULL || IpInfo == NULL) {\r
+ return;\r
+ }\r
+\r
ASSERT (IpInfo->RefCnt > 0);\r
\r
NET_PUT_REF (IpInfo);\r
return;\r
}\r
\r
- NetListRemoveEntry (&IpInfo->Entry);\r
+ IpVersion = IpIo->IpVersion;\r
\r
- IpInfo->Ip->Configure (IpInfo->Ip, NULL);\r
+ ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
\r
- IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpInfo->ChildHandle);\r
+ RemoveEntryList (&IpInfo->Entry);\r
\r
- gBS->CloseEvent (IpInfo->DummyRcvToken.Event);\r
+ if (IpVersion == IP_VERSION_4){\r
+ IpInfo->Ip.Ip4->Configure (\r
+ IpInfo->Ip.Ip4,\r
+ NULL\r
+ );\r
+ IpIoCloseProtocolDestroyIpChild (\r
+ IpIo->Controller,\r
+ IpIo->Image,\r
+ IpInfo->ChildHandle,\r
+ IP_VERSION_4\r
+ );\r
+\r
+ gBS->CloseEvent (IpInfo->DummyRcvToken.Ip4Token.Event);\r
+\r
+ } else {\r
\r
- NetFreePool (IpInfo);\r
+ IpInfo->Ip.Ip6->Configure (\r
+ IpInfo->Ip.Ip6,\r
+ NULL\r
+ );\r
+\r
+ IpIoCloseProtocolDestroyIpChild (\r
+ IpIo->Controller,\r
+ IpIo->Image,\r
+ IpInfo->ChildHandle,\r
+ IP_VERSION_6\r
+ );\r
+\r
+ gBS->CloseEvent (IpInfo->DummyRcvToken.Ip6Token.Event);\r
+ }\r
+\r
+ FreePool (IpInfo);\r
}\r
\r
\r
/**\r
Find the first IP protocol maintained in IpIo whose local\r
- address is the same with Src.\r
+ address is the same as Src.\r
+\r
+ This function is called when the caller needs the IpIo to send data to the\r
+ specified Src. The IpIo was added previously by IpIoAddIp().\r
\r
- @param IpIo Pointer to the pointer of the IP_IO instance.\r
- @param Src The local IP address.\r
+ @param[in, out] IpIo Pointer to the pointer of the IP_IO instance.\r
+ @param[in] IpVersion The version of the IP protocol to use, either\r
+ IPv4 or IPv6.\r
+ @param[in] Src The local IP address.\r
\r
@return Pointer to the IP protocol can be used for sending purpose and its local\r
- @return address is the same with Src.\r
+ address is the same with Src. NULL if failed.\r
\r
**/\r
IP_IO_IP_INFO *\r
+EFIAPI\r
IpIoFindSender (\r
- IN OUT IP_IO **IpIo,\r
- IN IP4_ADDR Src\r
+ IN OUT IP_IO **IpIo,\r
+ IN UINT8 IpVersion,\r
+ IN EFI_IP_ADDRESS *Src\r
)\r
{\r
- NET_LIST_ENTRY *IpIoEntry;\r
+ LIST_ENTRY *IpIoEntry;\r
IP_IO *IpIoPtr;\r
- NET_LIST_ENTRY *IpInfoEntry;\r
+ LIST_ENTRY *IpInfoEntry;\r
IP_IO_IP_INFO *IpInfo;\r
\r
+ if (IpIo == NULL || Src == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ if ((IpVersion != IP_VERSION_4) && (IpVersion != IP_VERSION_6)) {\r
+ return NULL;\r
+ }\r
+\r
NET_LIST_FOR_EACH (IpIoEntry, &mActiveIpIoList) {\r
IpIoPtr = NET_LIST_USER_STRUCT (IpIoEntry, IP_IO, Entry);\r
\r
- if ((*IpIo != NULL) && (*IpIo != IpIoPtr)) {\r
+ if (((*IpIo != NULL) && (*IpIo != IpIoPtr)) || (IpIoPtr->IpVersion != IpVersion)) {\r
continue;\r
}\r
\r
NET_LIST_FOR_EACH (IpInfoEntry, &IpIoPtr->IpList) {\r
IpInfo = NET_LIST_USER_STRUCT (IpInfoEntry, IP_IO_IP_INFO, Entry);\r
+ if (IpInfo->IpVersion == IP_VERSION_4){\r
+\r
+ if (EFI_IP4_EQUAL (&IpInfo->Addr.v4, &Src->v4)) {\r
+ *IpIo = IpIoPtr;\r
+ return IpInfo;\r
+ }\r
+\r
+ } else {\r
\r
- if (IpInfo->Addr == Src) {\r
- *IpIo = IpIoPtr;\r
- return IpInfo;\r
+ if (EFI_IP6_EQUAL (&IpInfo->Addr.v6, &Src->v6)) {\r
+ *IpIo = IpIoPtr;\r
+ return IpInfo;\r
+ }\r
}\r
}\r
}\r
\r
\r
/**\r
- Get the ICMP error map information, the ErrorStatus will be returned.\r
- The IsHard and Notify are optional. If they are not NULL, this rouine will\r
- fill them.\r
- We move IcmpErrMap[] to local variable to enable EBC build.\r
+ Get the ICMP error map information.\r
\r
- @param IcmpError IcmpError Type\r
- @param IsHard Whether it is a hard error\r
- @param Notify Whether it need to notify SockError\r
+ The ErrorStatus will be returned. The IsHard and Notify are optional. If they\r
+ are not NULL, this routine will fill them.\r
\r
- @return ICMP Error Status\r
+ @param[in] IcmpError IcmpError Type.\r
+ @param[in] IpVersion The version of the IP protocol to use,\r
+ either IPv4 or IPv6.\r
+ @param[out] IsHard If TRUE, indicates that it is a hard error.\r
+ @param[out] Notify If TRUE, SockError needs to be notified.\r
+\r
+ @retval EFI_UNSUPPORTED Unrecognizable ICMP error code.\r
+ @return ICMP Error Status, such as EFI_NETWORK_UNREACHABLE.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
IpIoGetIcmpErrStatus (\r
- IN ICMP_ERROR IcmpError,\r
- OUT BOOLEAN *IsHard, OPTIONAL\r
- OUT BOOLEAN *Notify OPTIONAL\r
+ IN UINT8 IcmpError,\r
+ IN UINT8 IpVersion,\r
+ OUT BOOLEAN *IsHard OPTIONAL,\r
+ OUT BOOLEAN *Notify OPTIONAL\r
)\r
{\r
- ASSERT ((IcmpError >= ICMP_ERR_UNREACH_NET) && (IcmpError <= ICMP_ERR_PARAMPROB));\r
+ if (IpVersion == IP_VERSION_4 ) {\r
+ ASSERT (IcmpError <= ICMP_ERR_PARAMPROB);\r
\r
- if (IsHard != NULL) {\r
- *IsHard = mIcmpErrMap[IcmpError].IsHard;\r
- }\r
+ if (IsHard != NULL) {\r
+ *IsHard = mIcmpErrMap[IcmpError].IsHard;\r
+ }\r
+\r
+ if (Notify != NULL) {\r
+ *Notify = mIcmpErrMap[IcmpError].Notify;\r
+ }\r
+\r
+ switch (IcmpError) {\r
+ case ICMP_ERR_UNREACH_NET:\r
+ return EFI_NETWORK_UNREACHABLE;\r
+\r
+ case ICMP_ERR_TIMXCEED_INTRANS:\r
+ case ICMP_ERR_TIMXCEED_REASS:\r
+ case ICMP_ERR_UNREACH_HOST:\r
+ return EFI_HOST_UNREACHABLE;\r
+\r
+ case ICMP_ERR_UNREACH_PROTOCOL:\r
+ return EFI_PROTOCOL_UNREACHABLE;\r
+\r
+ case ICMP_ERR_UNREACH_PORT:\r
+ return EFI_PORT_UNREACHABLE;\r
+\r
+ case ICMP_ERR_MSGSIZE:\r
+ case ICMP_ERR_UNREACH_SRCFAIL:\r
+ case ICMP_ERR_QUENCH:\r
+ case ICMP_ERR_PARAMPROB:\r
+ return EFI_ICMP_ERROR;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ } else if (IpVersion == IP_VERSION_6) {\r
\r
- if (Notify != NULL) {\r
- *Notify = mIcmpErrMap[IcmpError].Notify;\r
+ ASSERT (IcmpError <= ICMP6_ERR_PARAMPROB_IPV6OPTION);\r
+\r
+ if (IsHard != NULL) {\r
+ *IsHard = mIcmp6ErrMap[IcmpError].IsHard;\r
+ }\r
+\r
+ if (Notify != NULL) {\r
+ *Notify = mIcmp6ErrMap[IcmpError].Notify;\r
+ }\r
+\r
+ switch (IcmpError) {\r
+ case ICMP6_ERR_UNREACH_NET:\r
+ return EFI_NETWORK_UNREACHABLE;\r
+\r
+ case ICMP6_ERR_UNREACH_HOST:\r
+ case ICMP6_ERR_TIMXCEED_HOPLIMIT:\r
+ case ICMP6_ERR_TIMXCEED_REASS:\r
+ return EFI_HOST_UNREACHABLE;\r
+\r
+ case ICMP6_ERR_UNREACH_PROTOCOL:\r
+ return EFI_PROTOCOL_UNREACHABLE;\r
+\r
+ case ICMP6_ERR_UNREACH_PORT:\r
+ return EFI_PORT_UNREACHABLE;\r
+\r
+ case ICMP6_ERR_PACKAGE_TOOBIG:\r
+ case ICMP6_ERR_PARAMPROB_HEADER:\r
+ case ICMP6_ERR_PARAMPROB_NEXHEADER:\r
+ case ICMP6_ERR_PARAMPROB_IPV6OPTION:\r
+ return EFI_ICMP_ERROR;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ } else {\r
+ //\r
+ // Should never be here\r
+ //\r
+ ASSERT (FALSE);\r
+ return EFI_UNSUPPORTED;\r
}\r
+}\r
\r
- switch (IcmpError) {\r
- case ICMP_ERR_UNREACH_NET:\r
- return EFI_NETWORK_UNREACHABLE;\r
\r
- case ICMP_ERR_TIMXCEED_INTRANS:\r
- case ICMP_ERR_TIMXCEED_REASS:\r
- case ICMP_ERR_UNREACH_HOST:\r
- return EFI_HOST_UNREACHABLE;\r
+/**\r
+ Refresh the remote peer's Neighbor Cache entries.\r
+\r
+ This function is called when the caller needs the IpIo to refresh the existing\r
+ IPv6 neighbor cache entries since the neighbor is considered reachable by the\r
+ node has recently received a confirmation that packets sent recently to the\r
+ neighbor were received by its IP layer.\r
+\r
+ @param[in] IpIo Pointer to an IP_IO instance\r
+ @param[in] Neighbor The IP address of the neighbor\r
+ @param[in] Timeout Time in 100-ns units that this entry will\r
+ remain in the neighbor cache. A value of\r
+ zero means that the entry is permanent.\r
+ A value of non-zero means that the entry is\r
+ dynamic and will be deleted after Timeout.\r
+\r
+ @retval EFI_SUCCESS The operation is completed successfully.\r
+ @retval EFI_NOT_STARTED The IpIo is not configured.\r
+ @retval EFI_INVALID_PARAMETER Neighbor Address is invalid.\r
+ @retval EFI_NOT_FOUND The neighbor cache entry is not in the\r
+ neighbor table.\r
+ @retval EFI_UNSUPPORTED IP version is IPv4, which doesn't support neighbor cache refresh.\r
+ @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
\r
- case ICMP_ERR_UNREACH_PROTOCOL:\r
- return EFI_PROTOCOL_UNREACHABLE;\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IpIoRefreshNeighbor (\r
+ IN IP_IO *IpIo,\r
+ IN EFI_IP_ADDRESS *Neighbor,\r
+ IN UINT32 Timeout\r
+ )\r
+{\r
+ EFI_IP6_PROTOCOL *Ip;\r
\r
- case ICMP_ERR_UNREACH_PORT:\r
- return EFI_PORT_UNREACHABLE;\r
+ if (!IpIo->IsConfigured) {\r
+ return EFI_NOT_STARTED;\r
+ }\r
\r
- case ICMP_ERR_MSGSIZE:\r
- case ICMP_ERR_UNREACH_SRCFAIL:\r
- case ICMP_ERR_QUENCH:\r
- case ICMP_ERR_PARAMPROB:\r
- return EFI_ICMP_ERROR;\r
+ if (IpIo->IpVersion != IP_VERSION_6) {\r
+ return EFI_UNSUPPORTED;\r
}\r
\r
- //\r
- // will never run here!\r
- //\r
- ASSERT (FALSE);\r
- return EFI_UNSUPPORTED;\r
+ Ip = IpIo->Ip.Ip6;\r
+\r
+ return Ip->Neighbors (Ip, FALSE, &Neighbor->v6, NULL, Timeout, TRUE);\r
}\r
\r