From d33896d88d9d32d516129e92e25b80f8fddc6f7b Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Wed, 25 Apr 2018 17:23:25 +0800 Subject: Remove Core Package Remove Core Package since we will use EDK2 code from edk2 repository: https://github.com/tianocore/edk2 Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Guo Mang --- Core/NetworkPkg/Ip6Dxe/Ip6Output.c | 1091 ------------------------------------ 1 file changed, 1091 deletions(-) delete mode 100644 Core/NetworkPkg/Ip6Dxe/Ip6Output.c (limited to 'Core/NetworkPkg/Ip6Dxe/Ip6Output.c') diff --git a/Core/NetworkPkg/Ip6Dxe/Ip6Output.c b/Core/NetworkPkg/Ip6Dxe/Ip6Output.c deleted file mode 100644 index 8330e37935..0000000000 --- a/Core/NetworkPkg/Ip6Dxe/Ip6Output.c +++ /dev/null @@ -1,1091 +0,0 @@ -/** @file - The internal functions and routines to transmit the IP6 packet. - - Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
- - This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "Ip6Impl.h" - -UINT32 mIp6Id; - -/** - Output all the available source addresses to a list entry head SourceList. The - number of source addresses are also returned. - - @param[in] IpSb Points to an IP6 service binding instance. - @param[out] SourceList The list entry head of all source addresses. - It is the caller's responsibility to free the - resources. - @param[out] SourceCount The number of source addresses. - - @retval EFI_SUCCESS The source addresses were copied to a list entry head - SourceList. - @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation. - -**/ -EFI_STATUS -Ip6CandidateSource ( - IN IP6_SERVICE *IpSb, - OUT LIST_ENTRY *SourceList, - OUT UINT32 *SourceCount - ) -{ - IP6_INTERFACE *IpIf; - LIST_ENTRY *Entry; - LIST_ENTRY *Entry2; - IP6_ADDRESS_INFO *AddrInfo; - IP6_ADDRESS_INFO *Copy; - - *SourceCount = 0; - - if (IpSb->LinkLocalOk) { - Copy = AllocatePool (sizeof (IP6_ADDRESS_INFO)); - if (Copy == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Copy->Signature = IP6_ADDR_INFO_SIGNATURE; - IP6_COPY_ADDRESS (&Copy->Address, &IpSb->LinkLocalAddr); - Copy->IsAnycast = FALSE; - Copy->PrefixLength = IP6_LINK_LOCAL_PREFIX_LENGTH; - Copy->ValidLifetime = (UINT32) IP6_INFINIT_LIFETIME; - Copy->PreferredLifetime = (UINT32) IP6_INFINIT_LIFETIME; - - InsertTailList (SourceList, &Copy->Link); - (*SourceCount)++; - } - - NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) { - IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link); - - NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) { - AddrInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE); - - if (AddrInfo->IsAnycast) { - // - // Never use an anycast address. - // - continue; - } - - Copy = AllocateCopyPool (sizeof (IP6_ADDRESS_INFO), AddrInfo); - if (Copy == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - InsertTailList (SourceList, &Copy->Link); - (*SourceCount)++; - } - } - - return EFI_SUCCESS; -} - -/** - Calculate how many bits are the same between two IPv6 addresses. - - @param[in] AddressA Points to an IPv6 address. - @param[in] AddressB Points to another IPv6 address. - - @return The common bits of the AddressA and AddressB. - -**/ -UINT8 -Ip6CommonPrefixLen ( - IN EFI_IPv6_ADDRESS *AddressA, - IN EFI_IPv6_ADDRESS *AddressB - ) -{ - UINT8 Count; - UINT8 Index; - UINT8 ByteA; - UINT8 ByteB; - UINT8 NumBits; - - Count = 0; - Index = 0; - - while (Index < 16) { - ByteA = AddressA->Addr[Index]; - ByteB = AddressB->Addr[Index]; - - if (ByteA == ByteB) { - Count += 8; - Index++; - continue; - } - - // - // Check how many bits are common between the two bytes. - // - NumBits = 8; - ByteA = (UINT8) (ByteA ^ ByteB); - - while (ByteA != 0) { - NumBits--; - ByteA = (UINT8) (ByteA >> 1); - } - - return (UINT8) (Count + NumBits); - } - - return Count; -} - -/** - Output all the available source addresses to a list entry head SourceList. The - number of source addresses are also returned. - - @param[in] IpSb Points to a IP6 service binding instance. - @param[in] Destination The IPv6 destination address. - @param[out] Source The selected IPv6 source address according to - the Destination. - - @retval EFI_SUCCESS The source addresses were copied to a list entry - head SourceList. - @retval EFI_NO_MAPPING The IPv6 stack is not auto configured. - -**/ -EFI_STATUS -Ip6SelectSourceAddress ( - IN IP6_SERVICE *IpSb, - IN EFI_IPv6_ADDRESS *Destination, - OUT EFI_IPv6_ADDRESS *Source - ) -{ - EFI_STATUS Status; - LIST_ENTRY SourceList; - UINT32 SourceCount; - UINT8 ScopeD; - LIST_ENTRY *Entry; - IP6_ADDRESS_INFO *AddrInfo; - IP6_PREFIX_LIST_ENTRY *Prefix; - UINT8 LastCommonLength; - UINT8 CurrentCommonLength; - EFI_IPv6_ADDRESS *TmpAddress; - - NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE); - - Status = EFI_SUCCESS; - InitializeListHead (&SourceList); - - if (!IpSb->LinkLocalOk) { - return EFI_NO_MAPPING; - } - - // - // Rule 1: Prefer same address. - // - if (Ip6IsOneOfSetAddress (IpSb, Destination, NULL, NULL)) { - IP6_COPY_ADDRESS (Source, Destination); - goto Exit; - } - - // - // Rule 2: Prefer appropriate scope. - // - if (IP6_IS_MULTICAST (Destination)) { - ScopeD = (UINT8) (Destination->Addr[1] >> 4); - } else if (NetIp6IsLinkLocalAddr (Destination)) { - ScopeD = 0x2; - } else { - ScopeD = 0xE; - } - - if (ScopeD <= 0x2) { - // - // Return the link-local address if it exists - // One IP6_SERVICE only has one link-local address. - // - IP6_COPY_ADDRESS (Source, &IpSb->LinkLocalAddr); - goto Exit; - } - - // - // All candidate source addresses are global unicast address. - // - Ip6CandidateSource (IpSb, &SourceList, &SourceCount); - - if (SourceCount == 0) { - Status = EFI_NO_MAPPING; - goto Exit; - } - - IP6_COPY_ADDRESS (Source, &IpSb->LinkLocalAddr); - - if (SourceCount == 1) { - goto Exit; - } - - // - // Rule 3: Avoid deprecated addresses. - // TODO: check the "deprecated" state of the stateful configured address - // - NET_LIST_FOR_EACH (Entry, &IpSb->AutonomousPrefix) { - Prefix = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link); - if (Prefix->PreferredLifetime == 0) { - Ip6RemoveAddr (NULL, &SourceList, &SourceCount, &Prefix->Prefix, Prefix->PrefixLength); - - if (SourceCount == 1) { - goto Exit; - } - } - } - - // - // TODO: Rule 4: Prefer home addresses. - // TODO: Rule 5: Prefer outgoing interface. - // TODO: Rule 6: Prefer matching label. - // TODO: Rule 7: Prefer public addresses. - // - - // - // Rule 8: Use longest matching prefix. - // - LastCommonLength = Ip6CommonPrefixLen (Source, Destination); - TmpAddress = NULL; - - for (Entry = SourceList.ForwardLink; Entry != &SourceList; Entry = Entry->ForwardLink) { - AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE); - - CurrentCommonLength = Ip6CommonPrefixLen (&AddrInfo->Address, Destination); - if (CurrentCommonLength > LastCommonLength) { - LastCommonLength = CurrentCommonLength; - TmpAddress = &AddrInfo->Address; - } - } - - if (TmpAddress != NULL) { - IP6_COPY_ADDRESS (Source, TmpAddress); - } - -Exit: - - Ip6RemoveAddr (NULL, &SourceList, &SourceCount, NULL, 0); - - return Status; -} - -/** - Select an interface to send the packet generated in the IP6 driver - itself: that is, not by the requests of the IP6 child's consumer. Such - packets include the ICMPv6 echo replies and other ICMPv6 error packets. - - @param[in] IpSb The IP4 service that wants to send the packets. - @param[in] Destination The destination of the packet. - @param[in, out] Source The source of the packet. - - @return NULL if no proper interface is found, otherwise, the interface that - can be used to send the system packet from. - -**/ -IP6_INTERFACE * -Ip6SelectInterface ( - IN IP6_SERVICE *IpSb, - IN EFI_IPv6_ADDRESS *Destination, - IN OUT EFI_IPv6_ADDRESS *Source - ) -{ - EFI_STATUS Status; - EFI_IPv6_ADDRESS SelectedSource; - IP6_INTERFACE *IpIf; - BOOLEAN Exist; - - NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE); - ASSERT (Destination != NULL && Source != NULL); - - if (NetIp6IsUnspecifiedAddr (Destination)) { - return NULL; - } - - if (!NetIp6IsUnspecifiedAddr (Source)) { - Exist = Ip6IsOneOfSetAddress (IpSb, Source, &IpIf, NULL); - ASSERT (Exist); - - return IpIf; - } - - // - // If source is unspecified, select a source according to the destination. - // - Status = Ip6SelectSourceAddress (IpSb, Destination, &SelectedSource); - if (EFI_ERROR (Status)) { - return IpSb->DefaultInterface; - } - - Ip6IsOneOfSetAddress (IpSb, &SelectedSource, &IpIf, NULL); - IP6_COPY_ADDRESS (Source, &SelectedSource); - - return IpIf; -} - -/** - The default callback function for the system generated packet. - It will free the packet. - - @param[in] Packet The packet that transmitted. - @param[in] IoStatus The result of the transmission, succeeded or failed. - @param[in] LinkFlag Not used when transmitted. Check IP6_FRAME_CALLBACK - for reference. - @param[in] Context The context provided by us. - -**/ -VOID -Ip6SysPacketSent ( - NET_BUF *Packet, - EFI_STATUS IoStatus, - UINT32 LinkFlag, - VOID *Context - ) -{ - NetbufFree (Packet); - Packet = NULL; -} - -/** - Prefix an IP6 basic head and unfragmentable extension headers and a fragment header - to the Packet. Used for IP6 fragmentation. - - @param[in] IpSb The IP6 service instance to transmit the packet. - @param[in] Packet The packet to prefix the IP6 header to. - @param[in] Head The caller supplied header. - @param[in] FragmentOffset The fragment offset of the data following the header. - @param[in] ExtHdrs The length of the original extension header. - @param[in] ExtHdrsLen The length of the extension headers. - @param[in] LastHeader The pointer of next header of last extension header. - @param[in] HeadLen The length of the unfragmented part of the IP6 header. - - @retval EFI_BAD_BUFFER_SIZE There is no enough room in the head space of - Packet. - @retval EFI_SUCCESS The operation performed successfully. - -**/ -EFI_STATUS -Ip6PrependHead ( - IN IP6_SERVICE *IpSb, - IN NET_BUF *Packet, - IN EFI_IP6_HEADER *Head, - IN UINT16 FragmentOffset, - IN UINT8 *ExtHdrs, - IN UINT32 ExtHdrsLen, - IN UINT8 LastHeader, - IN UINT32 HeadLen - ) -{ - UINT32 Len; - UINT32 UnFragExtHdrsLen; - EFI_IP6_HEADER *PacketHead; - UINT8 *UpdatedExtHdrs; - EFI_STATUS Status; - UINT8 NextHeader; - - UpdatedExtHdrs = NULL; - - // - // HeadLen is the length of the fixed part of the sequences of fragments, i.e. - // the unfragment part. - // - PacketHead = (EFI_IP6_HEADER *) NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD); - if (PacketHead == NULL) { - return EFI_BAD_BUFFER_SIZE; - } - - // - // Set the head up, convert the host byte order to network byte order - // - CopyMem (PacketHead, Head, sizeof (EFI_IP6_HEADER)); - PacketHead->PayloadLength = HTONS ((UINT16) (Packet->TotalSize - sizeof (EFI_IP6_HEADER))); - Packet->Ip.Ip6 = PacketHead; - - Len = HeadLen - sizeof (EFI_IP6_HEADER); - UnFragExtHdrsLen = Len - sizeof (IP6_FRAGMENT_HEADER); - - if (UnFragExtHdrsLen == 0) { - PacketHead->NextHeader = IP6_FRAGMENT; - } - - // - // Append the extension headers: firstly copy the unfragmentable headers, then append - // fragmentation header. - // - if ((FragmentOffset & IP6_FRAGMENT_OFFSET_MASK) == 0) { - NextHeader = Head->NextHeader; - } else { - NextHeader = PacketHead->NextHeader; - } - - Status = Ip6FillFragmentHeader ( - IpSb, - NextHeader, - LastHeader, - ExtHdrs, - ExtHdrsLen, - FragmentOffset, - &UpdatedExtHdrs - ); - if (EFI_ERROR (Status)) { - return Status; - } - - CopyMem ( - (UINT8 *) (PacketHead + 1), - UpdatedExtHdrs, - UnFragExtHdrsLen + sizeof (IP6_FRAGMENT_HEADER) - ); - - FreePool (UpdatedExtHdrs); - return EFI_SUCCESS; -} - -/** - Transmit an IP6 packet. The packet comes either from the IP6 - child's consumer (IpInstance != NULL) or the IP6 driver itself - (IpInstance == NULL). It will route the packet, fragment it, - then transmit all the fragments through an interface. - - @param[in] IpSb The IP6 service instance to transmit the packet. - @param[in] Interface The IP6 interface to transmit the packet. Ignored - if NULL. - @param[in] IpInstance The IP6 child that issues the transmission. It is - NULL if the packet is from the system. - @param[in] Packet The user data to send, excluding the IP header. - @param[in] Head The caller supplied header. The caller should set - the following header fields: NextHeader, HopLimit, - Src, Dest, FlowLabel, PayloadLength. This function - will fill in the Ver, TrafficClass. - @param[in] ExtHdrs The extension headers to append to the IPv6 basic - header. - @param[in] ExtHdrsLen The length of the extension headers. - @param[in] Callback The callback function to issue when transmission - completed. - @param[in] Context The opaque context for the callback. - - @retval EFI_INVALID_PARAMETER Any input parameter or the packet is invalid. - @retval EFI_NO_MAPPING There is no interface to the destination. - @retval EFI_NOT_FOUND There is no route to the destination. - @retval EFI_SUCCESS The packet successfully transmitted. - @retval EFI_OUT_OF_RESOURCES Failed to finish the operation due to lack of - resources. - @retval Others Failed to transmit the packet. - -**/ -EFI_STATUS -Ip6Output ( - IN IP6_SERVICE *IpSb, - IN IP6_INTERFACE *Interface OPTIONAL, - IN IP6_PROTOCOL *IpInstance OPTIONAL, - IN NET_BUF *Packet, - IN EFI_IP6_HEADER *Head, - IN UINT8 *ExtHdrs, - IN UINT32 ExtHdrsLen, - IN IP6_FRAME_CALLBACK Callback, - IN VOID *Context - ) -{ - IP6_INTERFACE *IpIf; - EFI_IPv6_ADDRESS NextHop; - IP6_NEIGHBOR_ENTRY *NeighborCache; - IP6_ROUTE_CACHE_ENTRY *RouteCache; - EFI_STATUS Status; - UINT32 Mtu; - UINT32 HeadLen; - UINT16 FragmentOffset; - UINT8 *LastHeader; - UINT32 UnFragmentLen; - UINT32 UnFragmentHdrsLen; - UINT32 FragmentHdrsLen; - UINT16 *Checksum; - UINT16 PacketChecksum; - UINT16 PseudoChecksum; - UINT32 Index; - UINT32 PacketLen; - UINT32 RealExtLen; - UINT32 Offset; - NET_BUF *TmpPacket; - NET_BUF *Fragment; - UINT32 Num; - UINT8 *Buf; - EFI_IP6_HEADER *PacketHead; - IP6_ICMP_HEAD *IcmpHead; - IP6_TXTOKEN_WRAP *Wrap; - IP6_ROUTE_ENTRY *RouteEntry; - UINT8 *UpdatedExtHdrs; - UINT8 NextHeader; - UINT8 LastHeaderBackup; - BOOLEAN FragmentHeadInserted; - UINT8 *ExtHdrsBackup; - UINT8 NextHeaderBackup; - EFI_IPv6_ADDRESS Source; - EFI_IPv6_ADDRESS Destination; - - NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE); - - // - // RFC2460: Each extension header is an integer multiple of 8 octets long, - // in order to retain 8-octet alignment for subsequent headers. - // - if ((ExtHdrsLen & 0x7) != 0) { - return EFI_INVALID_PARAMETER; - } - - LastHeader = NULL; - - Ip6IsExtsValid ( - NULL, - NULL, - &Head->NextHeader, - ExtHdrs, - ExtHdrsLen, - FALSE, - NULL, - &LastHeader, - NULL, - NULL, - NULL - ); - - // - // Select an interface/source for system packet, application - // should select them itself. - // - IpIf = Interface; - if (IpIf == NULL) { - // - // IpInstance->Interface is NULL when IpInstance is configured with both stationaddress - // and destinationaddress is unspecified. - // - if (IpInstance == NULL || IpInstance->Interface == NULL) { - IpIf = Ip6SelectInterface (IpSb, &Head->DestinationAddress, &Head->SourceAddress); - if (IpInstance != NULL) { - IpInstance->Interface = IpIf; - } - } else { - IpIf = IpInstance->Interface; - } - } - - if (IpIf == NULL) { - return EFI_NO_MAPPING; - } - - // - // Update the common field in Head here. - // - Head->Version = 6; - Head->TrafficClassL = 0; - Head->TrafficClassH = 0; - - Checksum = NULL; - NextHeader = *LastHeader; - - switch (NextHeader) { - case EFI_IP_PROTO_UDP: - Packet->Udp = (EFI_UDP_HEADER *) NetbufGetByte (Packet, 0, NULL); - ASSERT (Packet->Udp != NULL); - if (Packet->Udp->Checksum == 0) { - Checksum = &Packet->Udp->Checksum; - } - break; - - case EFI_IP_PROTO_TCP: - Packet->Tcp = (TCP_HEAD *) NetbufGetByte (Packet, 0, NULL); - ASSERT (Packet->Tcp != NULL); - if (Packet->Tcp->Checksum == 0) { - Checksum = &Packet->Tcp->Checksum; - } - break; - - case IP6_ICMP: - // - // Don't send ICMP packet to an IPv6 anycast address. - // - if (Ip6IsAnycast (IpSb, &Head->DestinationAddress)) { - return EFI_INVALID_PARAMETER; - } - - IcmpHead = (IP6_ICMP_HEAD *) NetbufGetByte (Packet, 0, NULL); - ASSERT (IcmpHead != NULL); - if (IcmpHead->Checksum == 0) { - Checksum = &IcmpHead->Checksum; - } - break; - - default: - break; - } - - if (Checksum != NULL) { - // - // Calculate the checksum for upper layer protocol if it is not calculated due to lack of - // IPv6 source address. - // - PacketChecksum = NetbufChecksum (Packet); - PseudoChecksum = NetIp6PseudoHeadChecksum ( - &Head->SourceAddress, - &Head->DestinationAddress, - NextHeader, - Packet->TotalSize - ); - *Checksum = (UINT16) ~NetAddChecksum (PacketChecksum, PseudoChecksum); - } - - Status = Ip6IpSecProcessPacket ( - IpSb, - &Head, - LastHeader, // no need get the lasthead value for output - &Packet, - &ExtHdrs, - &ExtHdrsLen, - EfiIPsecOutBound, - Context - ); - - if (EFI_ERROR(Status)) { - return Status; - } - - LastHeader = NULL; - // - // Check incoming parameters. - // - if (!Ip6IsExtsValid ( - IpSb, - Packet, - &Head->NextHeader, - ExtHdrs, - ExtHdrsLen, - FALSE, - NULL, - &LastHeader, - &RealExtLen, - &UnFragmentHdrsLen, - NULL - )) { - return EFI_INVALID_PARAMETER; - } - - if ((RealExtLen & 0x7) != 0) { - return EFI_INVALID_PARAMETER; - } - - LastHeaderBackup = *LastHeader; - - // - // Perform next hop determination: - // For multicast packets, the next-hop is always the destination address and - // is considered to be on-link. - // - if (IP6_IS_MULTICAST (&Head->DestinationAddress)) { - IP6_COPY_ADDRESS (&NextHop, &Head->DestinationAddress); - } else { - // - // For unicast packets, use a combination of the Destination Cache, the Prefix List - // and the Default Router List to determine the IP address of the appropriate next hop. - // - - NeighborCache = Ip6FindNeighborEntry (IpSb, &Head->DestinationAddress); - if (NeighborCache != NULL) { - // - // Hit Neighbor Cache. - // - IP6_COPY_ADDRESS (&NextHop, &Head->DestinationAddress); - } else { - // - // Not in Neighbor Cache, check Router cache - // - RouteCache = Ip6Route (IpSb, &Head->DestinationAddress, &Head->SourceAddress); - if (RouteCache == NULL) { - return EFI_NOT_FOUND; - } - - IP6_COPY_ADDRESS (&NextHop, &RouteCache->NextHop); - Ip6FreeRouteCacheEntry (RouteCache); - } - } - - // - // Examines the Neighbor Cache for link-layer information about that neighbor. - // DO NOT create neighbor cache if neighbor is itself - when reporting ICMP error. - // - if (!IP6_IS_MULTICAST (&NextHop) && !EFI_IP6_EQUAL (&Head->DestinationAddress, &Head->SourceAddress)) { - NeighborCache = Ip6FindNeighborEntry (IpSb, &NextHop); - if (NeighborCache == NULL) { - NeighborCache = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, &NextHop, NULL); - - if (NeighborCache == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Send out multicast neighbor solicitation for address resolution immediately. - // - Ip6CreateSNMulticastAddr (&NeighborCache->Neighbor, &Destination); - Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = Ip6SendNeighborSolicit ( - IpSb, - &Source, - &Destination, - &NeighborCache->Neighbor, - &IpSb->SnpMode.CurrentAddress - ); - if (EFI_ERROR (Status)) { - return Status; - } - - --NeighborCache->Transmit; - NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer) + 1; - } - - NeighborCache->Interface = IpIf; - } - - UpdatedExtHdrs = NULL; - ExtHdrsBackup = NULL; - NextHeaderBackup = 0; - FragmentHeadInserted = FALSE; - - // - // Check whether we received Packet Too Big message for the packet sent to the - // Destination. If yes include a Fragment Header in the subsequent packets. - // - RouteEntry = Ip6FindRouteEntry ( - IpSb->RouteTable, - &Head->DestinationAddress, - NULL - ); - if (RouteEntry != NULL) { - if ((RouteEntry->Flag & IP6_PACKET_TOO_BIG) == IP6_PACKET_TOO_BIG) { - - // - // FragmentHead is inserted after Hop-by-Hop Options header, Destination - // Options header (first occur), Routing header, and before Fragment header, - // Authentication header, Encapsulating Security Payload header, and - // Destination Options header (last occur), and upper-layer header. - // - Status = Ip6FillFragmentHeader ( - IpSb, - Head->NextHeader, - LastHeaderBackup, - ExtHdrs, - ExtHdrsLen, - 0, - &UpdatedExtHdrs - ); - if (EFI_ERROR (Status)) { - return Status; - } - - if ((ExtHdrs == NULL) && (ExtHdrsLen == 0)) { - NextHeaderBackup = Head->NextHeader; - Head->NextHeader = IP6_FRAGMENT; - } - - ExtHdrsBackup = ExtHdrs; - ExtHdrs = UpdatedExtHdrs; - ExtHdrsLen = ExtHdrsLen + sizeof (IP6_FRAGMENT_HEADER); - RealExtLen = RealExtLen + sizeof (IP6_FRAGMENT_HEADER); - - mIp6Id++; - - FragmentHeadInserted = TRUE; - } - - Ip6FreeRouteEntry (RouteEntry); - } - - // - // OK, selected the source and route, fragment the packet then send - // them. Tag each fragment other than the first one as spawn from it. - // Each extension header is an integer multiple of 8 octets long, in - // order to retain 8-octet alignment for subsequent headers. - // - Mtu = IpSb->MaxPacketSize + sizeof (EFI_IP6_HEADER); - HeadLen = sizeof (EFI_IP6_HEADER) + RealExtLen; - - if (Packet->TotalSize + HeadLen > Mtu) { - // - // Remove the inserted Fragment Header since we need fragment the packet. - // - if (FragmentHeadInserted) { - ExtHdrs = ExtHdrsBackup; - ExtHdrsLen = ExtHdrsLen - sizeof (IP6_FRAGMENT_HEADER); - - if ((ExtHdrs == NULL) && (ExtHdrsLen == 0)) { - Head->NextHeader = NextHeaderBackup; - } - } - - FragmentHdrsLen = ExtHdrsLen - UnFragmentHdrsLen; - - // - // The packet is beyond the maximum which can be described through the - // fragment offset field in Fragment header. - // - if ((((Packet->TotalSize + FragmentHdrsLen) >> 3) & (~0x1fff)) != 0) { - Status = EFI_BAD_BUFFER_SIZE; - goto Error; - } - - if (FragmentHdrsLen != 0) { - // - // Append the fragmentable extension hdrs before the upper layer payload - // to form a new NET_BUF. This NET_BUF contains all the buffer which will - // be fragmented below. - // - TmpPacket = NetbufGetFragment (Packet, 0, Packet->TotalSize, FragmentHdrsLen); - ASSERT (TmpPacket != NULL); - - // - // Allocate the space to contain the fragmentable hdrs and copy the data. - // - Buf = NetbufAllocSpace (TmpPacket, FragmentHdrsLen, TRUE); - ASSERT (Buf != NULL); - CopyMem (Buf, ExtHdrs + UnFragmentHdrsLen, FragmentHdrsLen); - - // - // Free the old Packet. - // - NetbufFree (Packet); - Packet = TmpPacket; - } - - // - // The unfragment part which appears in every fragmented IPv6 packet includes - // the IPv6 header, the unfragmentable extension hdrs and the fragment header. - // - UnFragmentLen = sizeof (EFI_IP6_HEADER) + UnFragmentHdrsLen + sizeof (IP6_FRAGMENT_HEADER); - - // - // Mtu now is the length of the fragment part in a full-length fragment. - // - Mtu = (Mtu - UnFragmentLen) & (~0x07); - Num = (Packet->TotalSize + Mtu - 1) / Mtu; - - for (Index = 0, Offset = 0, PacketLen = Mtu; Index < Num; Index++) { - // - // Get fragment from the Packet, append UnFragnmentLen spare buffer - // before the fragmented data, the corresponding data is filled in later. - // - Fragment = NetbufGetFragment (Packet, Offset, PacketLen, UnFragmentLen); - if (Fragment == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Error; - } - - FragmentOffset = (UINT16) ((UINT16) Offset | 0x1); - if (Index == Num - 1){ - // - // The last fragment, clear the M flag. - // - FragmentOffset &= (~0x1); - } - - Status = Ip6PrependHead ( - IpSb, - Fragment, - Head, - FragmentOffset, - ExtHdrs, - ExtHdrsLen, - LastHeaderBackup, - UnFragmentLen - ); - ASSERT (Status == EFI_SUCCESS); - - Status = Ip6SendFrame ( - IpIf, - IpInstance, - Fragment, - &NextHop, - Ip6SysPacketSent, - Packet - ); - if (EFI_ERROR (Status)) { - goto Error; - } - - // - // The last fragment of upper layer packet, update the IP6 token status. - // - if ((Index == Num -1) && (Context != NULL)) { - Wrap = (IP6_TXTOKEN_WRAP *) Context; - Wrap->Token->Status = Status; - } - - Offset += PacketLen; - PacketLen = Packet->TotalSize - Offset; - if (PacketLen > Mtu) { - PacketLen = Mtu; - } - } - - NetbufFree (Packet); - mIp6Id++; - - if (UpdatedExtHdrs != NULL) { - FreePool (UpdatedExtHdrs); - } - - return EFI_SUCCESS; - } - - // - // Need not fragment the packet, send it in one frame. - // - PacketHead = (EFI_IP6_HEADER *) NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD); - if (PacketHead == NULL) { - Status = EFI_BAD_BUFFER_SIZE; - goto Error; - } - - CopyMem (PacketHead, Head, sizeof (EFI_IP6_HEADER)); - Packet->Ip.Ip6 = PacketHead; - - if (ExtHdrs != NULL) { - Buf = (UINT8 *) (PacketHead + 1); - CopyMem (Buf, ExtHdrs, ExtHdrsLen); - } - - if (UpdatedExtHdrs != NULL) { - // - // A Fragment Header is inserted to the packet, update the payload length. - // - PacketHead->PayloadLength = (UINT16) (NTOHS (PacketHead->PayloadLength) + - sizeof (IP6_FRAGMENT_HEADER)); - PacketHead->PayloadLength = HTONS (PacketHead->PayloadLength); - FreePool (UpdatedExtHdrs); - } - - return Ip6SendFrame ( - IpIf, - IpInstance, - Packet, - &NextHop, - Callback, - Context - ); - -Error: - if (UpdatedExtHdrs != NULL) { - FreePool (UpdatedExtHdrs); - } - Ip6CancelPacket (IpIf, Packet, Status); - return Status; -} - -/** - The filter function to find a packet and all its fragments. - The packet's fragments have their Context set to the packet. - - @param[in] Frame The frames hold by the low level interface. - @param[in] Context Context to the function, which is the packet. - - @retval TRUE This is the packet to cancel or its fragments. - @retval FALSE This is an unrelated packet. - -**/ -BOOLEAN -Ip6CancelPacketFragments ( - IN IP6_LINK_TX_TOKEN *Frame, - IN VOID *Context - ) -{ - if ((Frame->Packet == (NET_BUF *) Context) || (Frame->Context == Context)) { - return TRUE; - } - - return FALSE; -} - -/** - Remove all the frames on the interface that pass the FrameToCancel, - either queued on ARP queues or that have already been delivered to - MNP and not yet recycled. - - @param[in] Interface Interface to remove the frames from. - @param[in] IoStatus The transmit status returned to the frames' callback. - @param[in] FrameToCancel Function to select the frame to cancel; NULL to select all. - @param[in] Context Opaque parameters passed to FrameToCancel. Ignored if - FrameToCancel is NULL. - -**/ -VOID -Ip6CancelFrames ( - IN IP6_INTERFACE *Interface, - IN EFI_STATUS IoStatus, - IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL, - IN VOID *Context OPTIONAL - ) -{ - LIST_ENTRY *Entry; - LIST_ENTRY *Next; - IP6_LINK_TX_TOKEN *Token; - IP6_SERVICE *IpSb; - IP6_NEIGHBOR_ENTRY *ArpQue; - EFI_STATUS Status; - - IpSb = Interface->Service; - NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE); - - // - // Cancel all the pending frames on ARP requests - // - NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->ArpQues) { - ArpQue = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, ArpList); - - Status = Ip6FreeNeighborEntry ( - IpSb, - ArpQue, - FALSE, - FALSE, - IoStatus, - FrameToCancel, - Context - ); - ASSERT_EFI_ERROR (Status); - } - - // - // Cancel all the frames that have been delivered to MNP - // but not yet recycled. - // - NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->SentFrames) { - Token = NET_LIST_USER_STRUCT (Entry, IP6_LINK_TX_TOKEN, Link); - - if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) { - IpSb->Mnp->Cancel (IpSb->Mnp, &Token->MnpToken); - } - } -} - -/** - Cancel the Packet and all its fragments. - - @param[in] IpIf The interface from which the Packet is sent. - @param[in] Packet The Packet to cancel. - @param[in] IoStatus The status returns to the sender. - -**/ -VOID -Ip6CancelPacket ( - IN IP6_INTERFACE *IpIf, - IN NET_BUF *Packet, - IN EFI_STATUS IoStatus - ) -{ - Ip6CancelFrames (IpIf, IoStatus, Ip6CancelPacketFragments, Packet); -} - -- cgit v1.2.3