+++ /dev/null
-/** @file\r
- IpIo Library.\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 <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/DpcLib.h>\r
-\r
-\r
-GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mActiveIpIoList = {\r
- &mActiveIpIoList,\r
- &mActiveIpIoList\r
-};\r
-\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_IP4_CONFIG_DATA mIp4IoDefaultIpConfigData = {\r
- EFI_IP_PROTO_UDP,\r
- FALSE,\r
- TRUE,\r
- FALSE,\r
- FALSE,\r
- FALSE,\r
- {{0, 0, 0, 0}},\r
- {{0, 0, 0, 0}},\r
- 0,\r
- 255,\r
- FALSE,\r
- FALSE,\r
- 0,\r
- 0\r
-};\r
-\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
-\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
-\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
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- );\r
-\r
-\r
-/**\r
- This function create an IP child ,open the IP protocol, and return the opened\r
- IP protocol as Interface.\r
-\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 EFI_UNSUPPORTED Upsupported IpVersion.\r
- @retval Others The required operation failed.\r
-\r
-**/\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
- //\r
- Status = NetLibCreateServiceChild (\r
- ControllerHandle,\r
- ImageHandle,\r
- ServiceBindingGuid,\r
- ChildHandle\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Open the IP protocol installed on the *ChildHandle.\r
- //\r
- Status = gBS->OpenProtocol (\r
- *ChildHandle,\r
- IpProtocolGuid,\r
- Interface,\r
- ImageHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // On failure, destroy the IP child.\r
- //\r
- NetLibDestroyServiceChild (\r
- ControllerHandle,\r
- ImageHandle,\r
- ServiceBindingGuid,\r
- *ChildHandle\r
- );\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- This function close the previously openned IP protocol and destroy the IP child.\r
-\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 EFI_UNSUPPORTED Upsupported IpVersion.\r
- @retval Others The required operation failed.\r
-\r
-**/\r
-EFI_STATUS\r
-IpIoCloseProtocolDestroyIpChild (\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_HANDLE ImageHandle,\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
- //\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
- //\r
- return NetLibDestroyServiceChild (\r
- ControllerHandle,\r
- ImageHandle,\r
- ServiceBindingGuid,\r
- ChildHandle\r
- );\r
-}\r
-\r
-/**\r
- This function handles ICMPv4 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 ICMPv4 packet.\r
- @param[in] Session Pointer to the net session of this ICMPv4 packet.\r
-\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
-EFI_STATUS\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
- UINT8 IcmpErr;\r
- UINT8 *PayLoadHdr;\r
- UINT8 Type;\r
- UINT8 Code;\r
- UINT32 TrimBytes;\r
-\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
- }\r
-\r
- Type = IcmpHdr->Head.Type;\r
- Code = IcmpHdr->Head.Code;\r
-\r
- //\r
- // Analyze the ICMP Error in this ICMP pkt\r
- //\r
- switch (Type) {\r
- case ICMP_TYPE_UNREACH:\r
- switch (Code) {\r
- case ICMP_CODE_UNREACH_NET:\r
- case ICMP_CODE_UNREACH_HOST:\r
- case ICMP_CODE_UNREACH_PROTOCOL:\r
- case ICMP_CODE_UNREACH_PORT:\r
- case ICMP_CODE_UNREACH_SRCFAIL:\r
- IcmpErr = (UINT8) (ICMP_ERR_UNREACH_NET + Code);\r
-\r
- break;\r
-\r
- case ICMP_CODE_UNREACH_NEEDFRAG:\r
- IcmpErr = ICMP_ERR_MSGSIZE;\r
-\r
- break;\r
-\r
- case ICMP_CODE_UNREACH_NET_UNKNOWN:\r
- case ICMP_CODE_UNREACH_NET_PROHIB:\r
- case ICMP_CODE_UNREACH_TOSNET:\r
- IcmpErr = ICMP_ERR_UNREACH_NET;\r
-\r
- break;\r
-\r
- case ICMP_CODE_UNREACH_HOST_UNKNOWN:\r
- case ICMP_CODE_UNREACH_ISOLATED:\r
- case ICMP_CODE_UNREACH_HOST_PROHIB:\r
- case ICMP_CODE_UNREACH_TOSHOST:\r
- IcmpErr = ICMP_ERR_UNREACH_HOST;\r
-\r
- break;\r
-\r
- default:\r
- return EFI_ABORTED;\r
- }\r
-\r
- break;\r
-\r
- case ICMP_TYPE_TIMXCEED:\r
- if (Code > 1) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- IcmpErr = (UINT8) (Code + ICMP_ERR_TIMXCEED_INTRANS);\r
-\r
- break;\r
-\r
- case ICMP_TYPE_PARAMPROB:\r
- if (Code > 1) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- IcmpErr = ICMP_ERR_PARAMPROB;\r
-\r
- break;\r
-\r
- case ICMP_TYPE_SOURCEQUENCH:\r
- if (Code != 0) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- IcmpErr = ICMP_ERR_QUENCH;\r
-\r
- break;\r
-\r
- default:\r
- return EFI_ABORTED;\r
- }\r
-\r
- //\r
- // Notify user the ICMP pkt only containing payload except\r
- // IP and ICMP header\r
- //\r
- PayLoadHdr = (UINT8 *) ((UINT8 *) IpHdr + EFI_IP4_HEADER_LEN (IpHdr));\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 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
- 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[in] Event The event to be signaled.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-IpIoExtFree (\r
- IN VOID *Event\r
- )\r
-{\r
- gBS->SignalEvent ((EFI_EVENT) Event);\r
-}\r
-\r
-\r
-/**\r
- Create a send entry to wrap a packet before sending\r
- out it through IP.\r
-\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 any error occurs,\r
- then return NULL.\r
-\r
-**/\r
-IP_IO_SEND_ENTRY *\r
-IpIoCreateSndEntry (\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_EVENT Event;\r
- EFI_STATUS Status;\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 = AllocatePool (sizeof (IP_IO_SEND_ENTRY));\r
- if (NULL == SndEntry) {\r
- return NULL;\r
- }\r
-\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- IpIoTransmitHandler,\r
- SndEntry,\r
- &Event\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- FragmentCount = Pkt->BlockOpNum;\r
-\r
- //\r
- // Allocate resource for TxData\r
- //\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 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
- if (NULL != Override) {\r
-\r
- OverrideData = AllocateCopyPool (sizeof (IP_IO_OVERRIDE), Override);\r
- if (NULL == OverrideData) {\r
- goto ON_ERROR;\r
- }\r
- }\r
-\r
- //\r
- // Set other fields of TxData except the fragment table\r
- //\r
- if (IpIo->IpVersion == IP_VERSION_4) {\r
-\r
- Ip4TxData = &TxData->Ip4TxData;\r
-\r
- IP4_COPY_ADDRESS (&Ip4TxData->DestinationAddress, Dest);\r
-\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->Context = Context;\r
- SndEntry->NotifyData = NotifyData;\r
-\r
- SndEntry->Pkt = Pkt;\r
- NET_GET_REF (Pkt);\r
-\r
- InsertTailList (&IpIo->PendingSndList, &SndEntry->Entry);\r
-\r
- return SndEntry;\r
-\r
-ON_ERROR:\r
-\r
- if (OverrideData != NULL) {\r
- FreePool (OverrideData);\r
- }\r
-\r
- if (TxData != NULL) {\r
- FreePool (TxData);\r
- }\r
-\r
- if (SndEntry != NULL) {\r
- FreePool (SndEntry);\r
- }\r
-\r
- if (Event != NULL) {\r
- gBS->CloseEvent (Event);\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-\r
-/**\r
- Destroy the SndEntry.\r
-\r
- This function pairs with IpIoCreateSndEntry().\r
-\r
- @param[in] SndEntry Pointer to the send entry to be destroyed.\r
-\r
-**/\r
-VOID\r
-IpIoDestroySndEntry (\r
- IN IP_IO_SEND_ENTRY *SndEntry\r
- )\r
-{\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
- gBS->CloseEvent (Event);\r
-\r
- FreePool (TxData);\r
-\r
- if (NULL != Override) {\r
- FreePool (Override);\r
- }\r
-\r
- NetbufFree (SndEntry->Pkt);\r
-\r
- RemoveEntryList (&SndEntry->Entry);\r
-\r
- FreePool (SndEntry);\r
-}\r
-\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
- 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->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
- Status,\r
- SndEntry->Context,\r
- SndEntry->Ip,\r
- SndEntry->NotifyData\r
- );\r
- }\r
-\r
- IpIoDestroySndEntry (SndEntry);\r
-}\r
-\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
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- //\r
- // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK\r
- //\r
- QueueDpc (TPL_CALLBACK, IpIoTransmitHandlerDpc, Context);\r
-}\r
-\r
-\r
-/**\r
- The dummy handler for the dummy IP receive token.\r
-\r
- @param[in] Context The context passed in by the event notifier.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-IpIoDummyHandlerDpc (\r
- IN VOID *Context\r
- )\r
-{\r
- IP_IO_IP_INFO *IpInfo;\r
- EFI_STATUS Status;\r
- EFI_EVENT RecycleEvent;\r
-\r
- IpInfo = (IP_IO_IP_INFO *) Context;\r
-\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 == Status) {\r
- //\r
- // Recycle the RxData.\r
- //\r
- ASSERT (RecycleEvent != NULL);\r
-\r
- gBS->SignalEvent (RecycleEvent);\r
- }\r
-\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
- This function add IpIoDummyHandlerDpc to the end of the DPC queue.\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
-IpIoDummyHandler (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- //\r
- // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK\r
- //\r
- QueueDpc (TPL_CALLBACK, IpIoDummyHandlerDpc, Context);\r
-}\r
-\r
-\r
-/**\r
- Notify function for the IP receive token, used to process\r
- the received IP packets.\r
-\r
- @param[in] Context The context passed in by the event notifier.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-IpIoListenHandlerDpc (\r
- IN VOID *Context\r
- )\r
-{\r
- IP_IO *IpIo;\r
- EFI_STATUS Status;\r
- IP_IO_IP_RX_DATA *RxData;\r
- EFI_NET_SESSION_DATA Session;\r
- NET_BUF *Pkt;\r
-\r
- IpIo = (IP_IO *) Context;\r
-\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
- // The reception is actively aborted by the consumer, directly return.\r
- //\r
- return;\r
- }\r
-\r
- if ((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) {\r
- //\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
- if (NULL == IpIo->PktRcvdNotify) {\r
- goto CleanUp;\r
- }\r
-\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 fragment should always be valid for non-zero length packet.\r
- //\r
- ASSERT (RxData->Ip4RxData.FragmentCount != 0);\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.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, 0, &Session, Pkt, IpIo->RcvdContext);\r
- } else {\r
- //\r
- // Status is EFI_ICMP_ERROR\r
- //\r
- Status = IpIoIcmpHandler (IpIo, Pkt, &Session);\r
- if (EFI_ERROR (Status)) {\r
- NetbufFree (Pkt);\r
- }\r
- }\r
-\r
- goto Resume;\r
-\r
-CleanUp:\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
-\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
- This function add IpIoListenHandlerDpc to the end of the DPC queue.\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
-IpIoListenHandler (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- //\r
- // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK\r
- //\r
- QueueDpc (TPL_CALLBACK, IpIoListenHandlerDpc, Context);\r
-}\r
-\r
-\r
-/**\r
- Create a new IP_IO instance.\r
-\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
- @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 UINT8 IpVersion\r
- )\r
-{\r
- EFI_STATUS Status;\r
- IP_IO *IpIo;\r
- EFI_EVENT Event;\r
-\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
- 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
- TPL_NOTIFY,\r
- IpIoListenHandler,\r
- IpIo,\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
- Status = IpIoCreateIpChildOpenProtocol (\r
- Controller,\r
- Image,\r
- &IpIo->ChildHandle,\r
- IpVersion,\r
- (VOID **) & (IpIo->Ip)\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ReleaseIpIo;\r
- }\r
-\r
- return IpIo;\r
-\r
-ReleaseIpIo:\r
-\r
- if (Event != NULL) {\r
- gBS->CloseEvent (Event);\r
- }\r
-\r
- gBS->FreePool (IpIo);\r
-\r
- return NULL;\r
-}\r
-\r
-\r
-/**\r
- Open an IP_IO instance for use.\r
-\r
- If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
-\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 OUT IP_IO *IpIo,\r
- IN IP_IO_OPEN_DATA *OpenData\r
- )\r
-{\r
- EFI_STATUS Status;\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
- IpVersion = IpIo->IpVersion;\r
-\r
- ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
-\r
- //\r
- // configure ip\r
- //\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
- // @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
- 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
- }\r
- }\r
-\r
- IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;\r
- IpIo->PktSentNotify = OpenData->PktSentNotify;\r
-\r
- IpIo->RcvdContext = OpenData->RcvdContext;\r
- IpIo->SndContext = OpenData->SndContext;\r
-\r
- if (IpVersion == IP_VERSION_4){\r
- IpIo->Protocol = OpenData->IpConfigData.Ip4CfgData.DefaultProtocol;\r
-\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
- InsertTailList (&mActiveIpIoList, &IpIo->Entry);\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Stop an IP_IO instance.\r
-\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 EFI_INVALID_PARAMETER Invalid input parameter.\r
- @retval Others Error condition occurred.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IpIoStop (\r
- IN OUT IP_IO *IpIo\r
- )\r
-{\r
- EFI_STATUS Status;\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
- RemoveEntryList (&IpIo->Entry);\r
-\r
- //\r
- // Configure NULL Ip\r
- //\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
-\r
- IpIo->IsConfigured = FALSE;\r
-\r
- //\r
- // Detroy the Ip List used by IpIo\r
- //\r
-\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 send tokens should be flushed by resetting the IP instances.\r
- //\r
- ASSERT (IsListEmpty (&IpIo->PendingSndList));\r
-\r
- //\r
- // Close the receive event.\r
- //\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
-\r
-/**\r
- Destroy an IP_IO instance.\r
-\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 Others Error condition occurred.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IpIoDestroy (\r
- IN OUT IP_IO *IpIo\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Stop the IpIo.\r
- //\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
- 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
- gBS->FreePool (IpIo);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Send out an IP packet.\r
-\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 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
- 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
- Ip = (NULL == Sender) ? IpIo->Ip : Sender->Ip;\r
-\r
- //\r
- // create a new SndEntry\r
- //\r
- SndEntry = IpIoCreateSndEntry (IpIo, Pkt, Ip, Context, NotifyData, Dest, OverrideData);\r
- if (NULL == SndEntry) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Send this Packet\r
- //\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
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Cancel the IP transmit token which wraps this Packet.\r
-\r
- If IpIo is NULL, then ASSERT().\r
- If Packet is NULL, then ASSERT().\r
-\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
- LIST_ENTRY *Node;\r
- IP_IO_SEND_ENTRY *SndEntry;\r
- IP_IO_IP_PROTOCOL Ip;\r
-\r
- ASSERT ((IpIo != NULL) && (Packet != NULL));\r
-\r
- NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {\r
-\r
- SndEntry = NET_LIST_USER_STRUCT (Node, IP_IO_SEND_ENTRY, Entry);\r
-\r
- if (SndEntry->Pkt == Packet) {\r
-\r
- Ip = SndEntry->Ip;\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
-\r
-}\r
-\r
-\r
-/**\r
- Add a new IP instance for sending data.\r
-\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
- @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 OUT IP_IO *IpIo\r
- )\r
-{\r
- EFI_STATUS Status;\r
- IP_IO_IP_INFO *IpInfo;\r
- EFI_EVENT Event;\r
-\r
- ASSERT (IpIo != NULL);\r
- ASSERT ((IpIo->IpVersion == IP_VERSION_4) || (IpIo->IpVersion == IP_VERSION_6));\r
-\r
- IpInfo = AllocatePool (sizeof (IP_IO_IP_INFO));\r
- if (IpInfo == NULL) {\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
- InitializeListHead (&IpInfo->Entry);\r
- IpInfo->ChildHandle = NULL;\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 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
- goto ReleaseIpInfo;\r
- }\r
-\r
- //\r
- // Create the event for the DummyRcvToken.\r
- //\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- IpIoDummyHandler,\r
- IpInfo,\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
- InsertTailList (&IpIo->IpList, &IpInfo->Entry);\r
-\r
- return IpInfo;\r
-\r
-ReleaseIpChild:\r
-\r
- IpIoCloseProtocolDestroyIpChild (\r
- IpIo->Controller,\r
- IpIo->Image,\r
- IpInfo->ChildHandle,\r
- IpInfo->IpVersion\r
- );\r
-\r
-ReleaseIpInfo:\r
-\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 IpConfigData\r
- is not NULL.\r
-\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_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 OUT IP_IO_IP_INFO *IpInfo,\r
- IN OUT VOID *IpConfigData OPTIONAL\r
- )\r
-{\r
- EFI_STATUS Status;\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 != 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 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
- 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
- return Status;\r
- }\r
-\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
- 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
- if (Ip6ModeData.IsConfigured) {\r
- CopyMem (\r
- &((EFI_IP6_CONFIG_DATA *) IpConfigData)->StationAddress,\r
- &Ip6ModeData.ConfigData.StationAddress,\r
- sizeof (EFI_IPv6_ADDRESS)\r
- );\r
-\r
- if (Ip6ModeData.AddressList != NULL) {\r
- FreePool (Ip6ModeData.AddressList);\r
- }\r
-\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
- // The IP instance is reset, set the stored Addr and SubnetMask to zero.\r
- //\r
- ZeroMem (&IpInfo->Addr, sizeof (IpInfo->Addr));\r
- ZeroMem (&IpInfo->PreMask, sizeof (IpInfo->PreMask));\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Destroy an IP instance maintained in IpIo->IpList for\r
- sending purpose.\r
-\r
- If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().\r
-\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
- )\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
-\r
- if (IpInfo->RefCnt > 0) {\r
-\r
- return;\r
- }\r
-\r
- IpVersion = IpIo->IpVersion;\r
-\r
- ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
-\r
- RemoveEntryList (&IpInfo->Entry);\r
-\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
- 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 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[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
- 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 UINT8 IpVersion,\r
- IN EFI_IP_ADDRESS *Src\r
- )\r
-{\r
- LIST_ENTRY *IpIoEntry;\r
- IP_IO *IpIoPtr;\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)) || (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 (EFI_IP6_EQUAL (&IpInfo->Addr.v6, &Src->v6)) {\r
- *IpIo = IpIoPtr;\r
- return IpInfo;\r
- }\r
- }\r
- }\r
- }\r
-\r
- //\r
- // No match.\r
- //\r
- return NULL;\r
-}\r
-\r
-\r
-/**\r
- Get the ICMP error map information.\r
-\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
- @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 UINT8 IcmpError,\r
- IN UINT8 IpVersion,\r
- OUT BOOLEAN *IsHard OPTIONAL,\r
- OUT BOOLEAN *Notify OPTIONAL\r
- )\r
-{\r
- if (IpVersion == IP_VERSION_4 ) {\r
- ASSERT (IcmpError <= ICMP_ERR_PARAMPROB);\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
- 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
-\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
-**/\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
- if (!IpIo->IsConfigured) {\r
- return EFI_NOT_STARTED;\r
- }\r
-\r
- if (IpIo->IpVersion != IP_VERSION_6) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- Ip = IpIo->Ip.Ip6;\r
-\r
- return Ip->Neighbors (Ip, FALSE, &Neighbor->v6, NULL, Timeout, TRUE);\r
-}\r
-\r