X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FNetwork%2FIp4Dxe%2FIp4Input.c;h=24c5846588031b0e0a43f7d13708973e98a63632;hp=24d2f29d383de45239df4c5028632fd9a23a1560;hb=9d510e61fceee7b92955ef9a3c20343752d8ce3f;hpb=e798cd87ca9a3a30c4cea50c5f5de84e10a8bc5a diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c index 24d2f29d38..24c5846588 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c @@ -1,14 +1,10 @@ /** @file IP4 input process. - -Copyright (c) 2005 - 2010, 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. +Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -292,7 +288,7 @@ Ip4Reassemble ( // check whether THIS.Start < PREV.End for overlap. If two fragments // overlaps, trim the overlapped part off THIS fragment. // - if ((Prev = Cur->ForwardLink) != Head) { + if ((Prev = Cur->BackLink) != Head) { Fragment = NET_LIST_USER_STRUCT (Prev, NET_BUF, List); Node = IP4_GET_CLIP_INFO (Fragment); @@ -419,7 +415,15 @@ Ip4Reassemble ( } NewPacket->Ip.Ip4 = Assemble->Head; - CopyMem (IP4_GET_CLIP_INFO (NewPacket), Assemble->Info, sizeof (*IP4_GET_CLIP_INFO (NewPacket))); + + ASSERT (Assemble->Info != NULL); + + CopyMem ( + IP4_GET_CLIP_INFO (NewPacket), + Assemble->Info, + sizeof (*IP4_GET_CLIP_INFO (NewPacket)) + ); + return NewPacket; } @@ -431,8 +435,8 @@ DROP: } /** - The callback function for the net buffer which wraps the packet processed by - IPsec. It releases the wrap packet and also signals IPsec to free the resources. + The callback function for the net buffer which wraps the packet processed by + IPsec. It releases the wrap packet and also signals IPsec to free the resources. @param[in] Arg The wrap context @@ -459,85 +463,80 @@ Ip4IpSecFree ( } /** - The work function to locate IPsec protocol to process the inbound or + The work function to locate IPsec protocol to process the inbound or outbound IP packets. The process routine handls the packet with following - actions: bypass the packet, discard the packet, or protect the packet. + actions: bypass the packet, discard the packet, or protect the packet. - @param[in] IpSb The IP4 service instance - @param[in] Head The The caller supplied IP4 header. - @param[in, out] Netbuf The IP4 packet to be processed by IPsec - @param[in] Options The caller supplied options - @param[in] OptionsLen The length of the option - @param[in] Direction The directionality in an SPD entry, - EfiIPsecInBound or EfiIPsecOutBound - @param[in] Context The token's wrap + @param[in] IpSb The IP4 service instance. + @param[in, out] Head The The caller supplied IP4 header. + @param[in, out] Netbuf The IP4 packet to be processed by IPsec. + @param[in, out] Options The caller supplied options. + @param[in, out] OptionsLen The length of the option. + @param[in] Direction The directionality in an SPD entry, + EfiIPsecInBound or EfiIPsecOutBound. + @param[in] Context The token's wrap. @retval EFI_SUCCESS The IPsec protocol is not available or disabled. @retval EFI_SUCCESS The packet was bypassed and all buffers remain the same. @retval EFI_SUCCESS The packet was protected. - @retval EFI_ACCESS_DENIED The packet was discarded. + @retval EFI_ACCESS_DENIED The packet was discarded. @retval EFI_OUT_OF_RESOURCES There is no suffcient resource to complete the operation. - @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than the + @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than the number of input data blocks when build a fragment table. **/ EFI_STATUS Ip4IpSecProcessPacket ( - IN IP4_SERVICE *IpSb, - IN IP4_HEAD *Head, - IN OUT NET_BUF **Netbuf, - IN UINT8 *Options, - IN UINT32 OptionsLen, - IN EFI_IPSEC_TRAFFIC_DIR Direction, - IN VOID *Context + IN IP4_SERVICE *IpSb, + IN OUT IP4_HEAD **Head, + IN OUT NET_BUF **Netbuf, + IN OUT UINT8 **Options, + IN OUT UINT32 *OptionsLen, + IN EFI_IPSEC_TRAFFIC_DIR Direction, + IN VOID *Context ) { NET_FRAGMENT *FragmentTable; + NET_FRAGMENT *OriginalFragmentTable; UINT32 FragmentCount; + UINT32 OriginalFragmentCount; EFI_EVENT RecycleEvent; NET_BUF *Packet; IP4_TXTOKEN_WRAP *TxWrap; IP4_IPSEC_WRAP *IpSecWrap; EFI_STATUS Status; + IP4_HEAD ZeroHead; Status = EFI_SUCCESS; + + if (!mIpSec2Installed) { + goto ON_EXIT; + } + ASSERT (mIpSec != NULL); + Packet = *Netbuf; RecycleEvent = NULL; IpSecWrap = NULL; FragmentTable = NULL; - TxWrap = (IP4_TXTOKEN_WRAP *) Context; + TxWrap = (IP4_TXTOKEN_WRAP *) Context; FragmentCount = Packet->BlockOpNum; - - if (mIpSec == NULL) { - gBS->LocateProtocol (&gEfiIpSecProtocolGuid, NULL, (VOID **) &mIpSec); - if (mIpSec != NULL) { - // - // Save the original MTU - // - IpSb->OldMaxPacketSize = IpSb->MaxPacketSize; - } - } - // - // Check whether the IPsec protocol is available. - // - if (mIpSec == NULL) { - goto ON_EXIT; - } + ZeroMem (&ZeroHead, sizeof (IP4_HEAD)); + // // Check whether the IPsec enable variable is set. // if (mIpSec->DisabledFlag) { // // If IPsec is disabled, restore the original MTU - // + // IpSb->MaxPacketSize = IpSb->OldMaxPacketSize; goto ON_EXIT; } else { // - // If IPsec is enabled, use the MTU which reduce the IPsec header length. + // If IPsec is enabled, use the MTU which reduce the IPsec header length. // - IpSb->MaxPacketSize = IpSb->OldMaxPacketSize - IP4_MAX_IPSEC_HEADLEN; + IpSb->MaxPacketSize = IpSb->OldMaxPacketSize - IP4_MAX_IPSEC_HEADLEN; } // @@ -549,9 +548,15 @@ Ip4IpSecProcessPacket ( Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } - + Status = NetbufBuildExt (Packet, FragmentTable, &FragmentCount); + // + // Record the original FragmentTable and count. + // + OriginalFragmentTable = FragmentTable; + OriginalFragmentCount = FragmentCount; + if (EFI_ERROR (Status)) { FreePool (FragmentTable); goto ON_EXIT; @@ -560,16 +565,16 @@ Ip4IpSecProcessPacket ( // // Convert host byte order to network byte order // - Ip4NtohHead (Head); - - Status = mIpSec->Process ( + Ip4NtohHead (*Head); + + Status = mIpSec->ProcessExt ( mIpSec, IpSb->Controller, IP_VERSION_4, - (VOID *) Head, - &Head->Protocol, - NULL, - 0, + (VOID *) (*Head), + &(*Head)->Protocol, + (VOID **) Options, + OptionsLen, (EFI_IPSEC_FRAGMENT_DATA **) (&FragmentTable), &FragmentCount, Direction, @@ -578,14 +583,28 @@ Ip4IpSecProcessPacket ( // // Convert back to host byte order // - Ip4NtohHead (Head); - + Ip4NtohHead (*Head); + if (EFI_ERROR (Status)) { + FreePool (OriginalFragmentTable); + goto ON_EXIT; + } + + if (OriginalFragmentTable == FragmentTable && OriginalFragmentCount == FragmentCount) { + // + // For ByPass Packet + // + FreePool (FragmentTable); goto ON_EXIT; + } else { + // + // Free the FragmentTable which allocated before calling the IPsec. + // + FreePool (OriginalFragmentTable); } if (Direction == EfiIPsecOutBound && TxWrap != NULL) { - + TxWrap->IpSecRecycleSignal = RecycleEvent; TxWrap->Packet = NetbufFromExt ( FragmentTable, @@ -596,40 +615,54 @@ Ip4IpSecProcessPacket ( TxWrap ); if (TxWrap->Packet == NULL) { + // + // Recover the TxWrap->Packet, if meet a error, and the caller will free + // the TxWrap. + // + TxWrap->Packet = *Netbuf; Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } + // + // Free orginal Netbuf. + // + NetIpSecNetbufFree (*Netbuf); *Netbuf = TxWrap->Packet; - + } else { - + IpSecWrap = AllocateZeroPool (sizeof (IP4_IPSEC_WRAP)); - + if (IpSecWrap == NULL) { + Status = EFI_OUT_OF_RESOURCES; + gBS->SignalEvent (RecycleEvent); goto ON_EXIT; } - + IpSecWrap->IpSecRecycleSignal = RecycleEvent; IpSecWrap->Packet = Packet; Packet = NetbufFromExt ( - FragmentTable, - FragmentCount, - IP4_MAX_HEADLEN, - 0, - Ip4IpSecFree, + FragmentTable, + FragmentCount, + IP4_MAX_HEADLEN, + 0, + Ip4IpSecFree, IpSecWrap ); - + if (Packet == NULL) { + Packet = IpSecWrap->Packet; + gBS->SignalEvent (RecycleEvent); + FreePool (IpSecWrap); Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } - if (Direction == EfiIPsecInBound) { - Ip4PrependHead (Packet, Head, Options, OptionsLen); + if (Direction == EfiIPsecInBound && 0 != CompareMem (*Head, &ZeroHead, sizeof (IP4_HEAD))) { + Ip4PrependHead (Packet, *Head, *Options, *OptionsLen); Ip4NtohHead (Packet->Ip.Ip4); - NetbufTrim (Packet, (Head->HeadLen << 2), TRUE); + NetbufTrim (Packet, ((*Head)->HeadLen << 2), TRUE); CopyMem ( IP4_GET_CLIP_INFO (Packet), @@ -637,7 +670,6 @@ Ip4IpSecProcessPacket ( sizeof (IP4_CLIP_INFO) ); } - *Netbuf = Packet; } @@ -646,63 +678,56 @@ ON_EXIT: } /** - The IP4 input routine. It is called by the IP4_INTERFACE when a - IP4 fragment is received from MNP. + Pre-process the IPv4 packet. First validates the IPv4 packet, and + then reassembles packet if it is necessary. - @param[in] Ip4Instance The IP4 child that request the receive, most like - it is NULL. - @param[in] Packet The IP4 packet received. - @param[in] IoStatus The return status of receive request. - @param[in] Flag The link layer flag for the packet received, such - as multicast. - @param[in] Context The IP4 service instance that own the MNP. + @param[in] IpSb Pointer to IP4_SERVICE. + @param[in, out] Packet Pointer to the Packet to be processed. + @param[in] Head Pointer to the IP4_HEAD. + @param[in] Option Pointer to a buffer which contains the IPv4 option. + @param[in] OptionLen The length of Option in bytes. + @param[in] Flag The link layer flag for the packet received, such + as multicast. + + @retval EFI_SEUCCESS The recieved packet is in well form. + @retval EFI_INVAILD_PARAMETER The recieved packet is malformed. **/ -VOID -Ip4AccpetFrame ( - IN IP4_PROTOCOL *Ip4Instance, - IN NET_BUF *Packet, - IN EFI_STATUS IoStatus, - IN UINT32 Flag, - IN VOID *Context +EFI_STATUS +Ip4PreProcessPacket ( + IN IP4_SERVICE *IpSb, + IN OUT NET_BUF **Packet, + IN IP4_HEAD *Head, + IN UINT8 *Option, + IN UINT32 OptionLen, + IN UINT32 Flag ) { - IP4_SERVICE *IpSb; IP4_CLIP_INFO *Info; - IP4_HEAD *Head; UINT32 HeadLen; - UINT32 OptionLen; UINT32 TotalLen; UINT16 Checksum; - EFI_STATUS Status; - - IpSb = (IP4_SERVICE *) Context; - - if (EFI_ERROR (IoStatus) || (IpSb->State == IP4_SERVICE_DESTORY)) { - goto DROP; - } // - // Check that the IP4 header is correctly formatted + // Check if the IP4 header is correctly formatted. // - if (Packet->TotalSize < IP4_MIN_HEADLEN) { - goto RESTART; + if ((*Packet)->TotalSize < IP4_MIN_HEADLEN) { + return EFI_INVALID_PARAMETER; } - Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL); HeadLen = (Head->HeadLen << 2); TotalLen = NTOHS (Head->TotalLen); // // Mnp may deliver frame trailer sequence up, trim it off. // - if (TotalLen < Packet->TotalSize) { - NetbufTrim (Packet, Packet->TotalSize - TotalLen, FALSE); + if (TotalLen < (*Packet)->TotalSize) { + NetbufTrim (*Packet, (*Packet)->TotalSize - TotalLen, FALSE); } if ((Head->Ver != 4) || (HeadLen < IP4_MIN_HEADLEN) || - (TotalLen < HeadLen) || (TotalLen != Packet->TotalSize)) { - goto RESTART; + (TotalLen < HeadLen) || (TotalLen != (*Packet)->TotalSize)) { + return EFI_INVALID_PARAMETER; } // @@ -711,15 +736,15 @@ Ip4AccpetFrame ( Checksum = (UINT16) (~NetblockChecksum ((UINT8 *) Head, HeadLen)); if ((Head->Checksum != 0) && (Checksum != 0)) { - goto RESTART; + return EFI_INVALID_PARAMETER; } // // Convert the IP header to host byte order, then get the per packet info. // - Packet->Ip.Ip4 = Ip4NtohHead (Head); + (*Packet)->Ip.Ip4 = Ip4NtohHead (Head); - Info = IP4_GET_CLIP_INFO (Packet); + Info = IP4_GET_CLIP_INFO (*Packet); Info->LinkFlag = Flag; Info->CastType = Ip4GetHostCast (IpSb, Head->Dst, Head->Src); Info->Start = (Head->Fragment & IP4_HEAD_OFFSET_MASK) << 3; @@ -731,24 +756,23 @@ Ip4AccpetFrame ( // The packet is destinated to us if the CastType is non-zero. // if ((Info->CastType == 0) || (Info->End > IP4_MAX_PACKET_SIZE)) { - goto RESTART; + return EFI_INVALID_PARAMETER; } // // Validate the options. Don't call the Ip4OptionIsValid if // there is no option to save some CPU process. // - OptionLen = HeadLen - IP4_MIN_HEADLEN; - if ((OptionLen > 0) && !Ip4OptionIsValid ((UINT8 *) (Head + 1), OptionLen, TRUE)) { - goto RESTART; + if ((OptionLen > 0) && !Ip4OptionIsValid (Option, OptionLen, TRUE)) { + return EFI_INVALID_PARAMETER; } // - // Trim the head off, after this point, the packet is headless. + // Trim the head off, after this point, the packet is headless, // and Packet->TotalLen == Info->Length. // - NetbufTrim (Packet, HeadLen, TRUE); + NetbufTrim (*Packet, HeadLen, TRUE); // // Reassemble the packet if this is a fragment. The packet is a @@ -761,47 +785,131 @@ Ip4AccpetFrame ( // need to send a type 4 destination unreache ICMP message here. // if ((Head->Fragment & IP4_HEAD_DF_MASK) != 0) { - goto RESTART; + return EFI_INVALID_PARAMETER; } // // The length of all but the last fragments is in the unit of 8 bytes. // if (((Head->Fragment & IP4_HEAD_MF_MASK) != 0) && (Info->Length % 8 != 0)) { - goto RESTART; + return EFI_INVALID_PARAMETER; } - Packet = Ip4Reassemble (&IpSb->Assemble, Packet); + *Packet = Ip4Reassemble (&IpSb->Assemble, *Packet); // // Packet assembly isn't complete, start receive more packet. // - if (Packet == NULL) { - goto RESTART; + if (*Packet == NULL) { + return EFI_INVALID_PARAMETER; } } + return EFI_SUCCESS; +} + +/** + The IP4 input routine. It is called by the IP4_INTERFACE when a + IP4 fragment is received from MNP. + + @param[in] Ip4Instance The IP4 child that request the receive, most like + it is NULL. + @param[in] Packet The IP4 packet received. + @param[in] IoStatus The return status of receive request. + @param[in] Flag The link layer flag for the packet received, such + as multicast. + @param[in] Context The IP4 service instance that own the MNP. + +**/ +VOID +Ip4AccpetFrame ( + IN IP4_PROTOCOL *Ip4Instance, + IN NET_BUF *Packet, + IN EFI_STATUS IoStatus, + IN UINT32 Flag, + IN VOID *Context + ) +{ + IP4_SERVICE *IpSb; + IP4_HEAD *Head; + EFI_STATUS Status; + IP4_HEAD ZeroHead; + UINT8 *Option; + UINT32 OptionLen; + + IpSb = (IP4_SERVICE *) Context; + Option = NULL; + + if (EFI_ERROR (IoStatus) || (IpSb->State == IP4_SERVICE_DESTROY)) { + goto DROP; + } + + Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL); + ASSERT (Head != NULL); + OptionLen = (Head->HeadLen << 2) - IP4_MIN_HEADLEN; + if (OptionLen > 0) { + Option = (UINT8 *) (Head + 1); + } + + // + // Validate packet format and reassemble packet if it is necessary. + // + Status = Ip4PreProcessPacket ( + IpSb, + &Packet, + Head, + Option, + OptionLen, + Flag + ); + + if (EFI_ERROR (Status)) { + goto RESTART; + } + // // After trim off, the packet is a esp/ah/udp/tcp/icmp6 net buffer, // and no need consider any other ahead ext headers. // Status = Ip4IpSecProcessPacket ( - IpSb, - Head, - &Packet, - NULL, - 0, + IpSb, + &Head, + &Packet, + &Option, + &OptionLen, EfiIPsecInBound, NULL ); - if (EFI_ERROR(Status)) { + if (EFI_ERROR (Status)) { goto RESTART; } + + // + // If the packet is protected by tunnel mode, parse the inner Ip Packet. + // + ZeroMem (&ZeroHead, sizeof (IP4_HEAD)); + if (0 == CompareMem (Head, &ZeroHead, sizeof (IP4_HEAD))) { // Packet may have been changed. Head, HeadLen, TotalLen, and // info must be reloaded bofore use. The ownership of the packet // is transfered to the packet process logic. // + Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL); + ASSERT (Head != NULL); + Status = Ip4PreProcessPacket ( + IpSb, + &Packet, + Head, + Option, + OptionLen, + Flag + ); + if (EFI_ERROR (Status)) { + goto RESTART; + } + } + + ASSERT (Packet != NULL); Head = Packet->Ip.Ip4; IP4_GET_CLIP_INFO (Packet)->Status = EFI_SUCCESS; @@ -815,7 +923,7 @@ Ip4AccpetFrame ( break; default: - Ip4Demultiplex (IpSb, Head, Packet); + Ip4Demultiplex (IpSb, Head, Packet, Option, OptionLen); } Packet = NULL; @@ -1038,8 +1146,8 @@ Ip4OnRecyclePacket ( to the upper layer. Upper layer will signal the recycle event in it when it is done with the packet. - @param[in] IpInstance The IP4 child to receive the packet - @param[in] Packet The packet to deliver up. + @param[in] IpInstance The IP4 child to receive the packet. + @param[in] Packet The packet to deliver up. @retval Wrap if warp the packet succeed. @retval NULL failed to wrap the packet . @@ -1054,6 +1162,7 @@ Ip4WrapRxData ( IP4_RXDATA_WRAP *Wrap; EFI_IP4_RECEIVE_DATA *RxData; EFI_STATUS Status; + BOOLEAN RawData; Wrap = AllocatePool (IP4_RXDATA_WRAP_SIZE (Packet->BlockOpNum)); @@ -1067,7 +1176,7 @@ Ip4WrapRxData ( Wrap->Packet = Packet; RxData = &Wrap->RxData; - ZeroMem (&RxData->TimeStamp, sizeof (EFI_TIME)); + ZeroMem (RxData, sizeof (EFI_IP4_RECEIVE_DATA)); Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, @@ -1084,17 +1193,21 @@ Ip4WrapRxData ( ASSERT (Packet->Ip.Ip4 != NULL); + ASSERT (IpInstance != NULL); + RawData = IpInstance->ConfigData.RawData; + // // The application expects a network byte order header. // - RxData->HeaderLength = (Packet->Ip.Ip4->HeadLen << 2); - RxData->Header = (EFI_IP4_HEADER *) Ip4NtohHead (Packet->Ip.Ip4); - - RxData->OptionsLength = RxData->HeaderLength - IP4_MIN_HEADLEN; - RxData->Options = NULL; + if (!RawData) { + RxData->HeaderLength = (Packet->Ip.Ip4->HeadLen << 2); + RxData->Header = (EFI_IP4_HEADER *) Ip4NtohHead (Packet->Ip.Ip4); + RxData->OptionsLength = RxData->HeaderLength - IP4_MIN_HEADLEN; + RxData->Options = NULL; - if (RxData->OptionsLength != 0) { - RxData->Options = (VOID *) (RxData->Header + 1); + if (RxData->OptionsLength != 0) { + RxData->Options = (VOID *) (RxData->Header + 1); + } } RxData->DataLength = Packet->TotalSize; @@ -1133,6 +1246,7 @@ Ip4InstanceDeliverPacket ( NET_BUF *Packet; NET_BUF *Dup; UINT8 *Head; + UINT32 HeadLen; // // Deliver a packet if there are both a packet and a receive token. @@ -1158,22 +1272,32 @@ Ip4InstanceDeliverPacket ( // // Create a duplicated packet if this packet is shared // - Dup = NetbufDuplicate (Packet, NULL, IP4_MAX_HEADLEN); + if (IpInstance->ConfigData.RawData) { + HeadLen = 0; + } else { + HeadLen = IP4_MAX_HEADLEN; + } + + Dup = NetbufDuplicate (Packet, NULL, HeadLen); if (Dup == NULL) { return EFI_OUT_OF_RESOURCES; } - // - // Copy the IP head over. The packet to deliver up is - // headless. Trim the head off after copy. The IP head - // may be not continuous before the data. - // - Head = NetbufAllocSpace (Dup, IP4_MAX_HEADLEN, NET_BUF_HEAD); - Dup->Ip.Ip4 = (IP4_HEAD *) Head; + if (!IpInstance->ConfigData.RawData) { + // + // Copy the IP head over. The packet to deliver up is + // headless. Trim the head off after copy. The IP head + // may be not continuous before the data. + // + Head = NetbufAllocSpace (Dup, IP4_MAX_HEADLEN, NET_BUF_HEAD); + ASSERT (Head != NULL); - CopyMem (Head, Packet->Ip.Ip4, Packet->Ip.Ip4->HeadLen << 2); - NetbufTrim (Dup, IP4_MAX_HEADLEN, TRUE); + Dup->Ip.Ip4 = (IP4_HEAD *) Head; + + CopyMem (Head, Packet->Ip.Ip4, Packet->Ip.Ip4->HeadLen << 2); + NetbufTrim (Dup, IP4_MAX_HEADLEN, TRUE); + } Wrap = Ip4WrapRxData (IpInstance, Dup); @@ -1211,10 +1335,12 @@ Ip4InstanceDeliverPacket ( Enqueue a received packet to all the IP children that share the same interface. - @param[in] IpSb The IP4 service instance that receive the packet - @param[in] Head The header of the received packet - @param[in] Packet The data of the received packet - @param[in] IpIf The interface to enqueue the packet to + @param[in] IpSb The IP4 service instance that receive the packet. + @param[in] Head The header of the received packet. + @param[in] Packet The data of the received packet. + @param[in] Option Point to the IP4 packet header options. + @param[in] OptionLen Length of the IP4 packet header options. + @param[in] IpIf The interface to enqueue the packet to. @return The number of the IP4 children that accepts the packet @@ -1224,6 +1350,8 @@ Ip4InterfaceEnquePacket ( IN IP4_SERVICE *IpSb, IN IP4_HEAD *Head, IN NET_BUF *Packet, + IN UINT8 *Option, + IN UINT32 OptionLen, IN IP4_INTERFACE *IpIf ) { @@ -1289,6 +1417,13 @@ Ip4InterfaceEnquePacket ( IpInstance = NET_LIST_USER_STRUCT (Entry, IP4_PROTOCOL, AddrLink); NET_CHECK_SIGNATURE (IpInstance, IP4_PROTOCOL_SIGNATURE); + // + // In RawData mode, add IPv4 headers and options back to packet. + // + if ((IpInstance->ConfigData.RawData) && (Option != NULL) && (OptionLen != 0)){ + Ip4PrependHead (Packet, Head, Option, OptionLen); + } + if (Ip4InstanceEnquePacket (IpInstance, Head, Packet) == EFI_SUCCESS) { Enqueued++; } @@ -1335,11 +1470,13 @@ Ip4InterfaceDeliverPacket ( child wants to consume the packet because each IP child needs its own copy of the packet to make changes. - @param[in] IpSb The IP4 service instance that received the packet - @param[in] Head The header of the received packet - @param[in] Packet The data of the received packet + @param[in] IpSb The IP4 service instance that received the packet. + @param[in] Head The header of the received packet. + @param[in] Packet The data of the received packet. + @param[in] Option Point to the IP4 packet header options. + @param[in] OptionLen Length of the IP4 packet header options. - @retval EFI_NOT_FOUND No IP child accepts the packet + @retval EFI_NOT_FOUND No IP child accepts the packet. @retval EFI_SUCCESS The packet is enqueued or delivered to some IP children. @@ -1348,7 +1485,9 @@ EFI_STATUS Ip4Demultiplex ( IN IP4_SERVICE *IpSb, IN IP4_HEAD *Head, - IN NET_BUF *Packet + IN NET_BUF *Packet, + IN UINT8 *Option, + IN UINT32 OptionLen ) { LIST_ENTRY *Entry; @@ -1365,7 +1504,14 @@ Ip4Demultiplex ( IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link); if (IpIf->Configured) { - Enqueued += Ip4InterfaceEnquePacket (IpSb, Head, Packet, IpIf); + Enqueued += Ip4InterfaceEnquePacket ( + IpSb, + Head, + Packet, + Option, + OptionLen, + IpIf + ); } }