/** @file\r
IP4 input process.\r
- \r
-Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
+\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
// check whether THIS.Start < PREV.End for overlap. If two fragments\r
// overlaps, trim the overlapped part off THIS fragment.\r
//\r
- if ((Cur != Head) && ((Prev = Cur->BackLink) != Head)) {\r
+ if ((Prev = Cur->BackLink) != Head) {\r
Fragment = NET_LIST_USER_STRUCT (Prev, NET_BUF, List);\r
Node = IP4_GET_CLIP_INFO (Fragment);\r
\r
}\r
\r
NewPacket->Ip.Ip4 = Assemble->Head;\r
- CopyMem (IP4_GET_CLIP_INFO (NewPacket), Assemble->Info, sizeof (*IP4_GET_CLIP_INFO (NewPacket)));\r
+\r
+ ASSERT (Assemble->Info != NULL);\r
+\r
+ CopyMem (\r
+ IP4_GET_CLIP_INFO (NewPacket),\r
+ Assemble->Info,\r
+ sizeof (*IP4_GET_CLIP_INFO (NewPacket))\r
+ );\r
+\r
return NewPacket;\r
}\r
\r
}\r
\r
/**\r
- The callback function for the net buffer which wraps the packet processed by \r
- IPsec. It releases the wrap packet and also signals IPsec to free the resources. \r
+ The callback function for the net buffer which wraps the packet processed by\r
+ IPsec. It releases the wrap packet and also signals IPsec to free the resources.\r
\r
@param[in] Arg The wrap context\r
\r
}\r
\r
/**\r
- The work function to locate IPsec protocol to process the inbound or \r
+ The work function to locate IPsec protocol to process the inbound or\r
outbound IP packets. The process routine handls the packet with following\r
- actions: bypass the packet, discard the packet, or protect the packet. \r
+ actions: bypass the packet, discard the packet, or protect the packet.\r
\r
@param[in] IpSb The IP4 service instance.\r
@param[in, out] Head The The caller supplied IP4 header.\r
@param[in, out] Netbuf The IP4 packet to be processed by IPsec.\r
@param[in, out] Options The caller supplied options.\r
@param[in, out] OptionsLen The length of the option.\r
- @param[in] Direction The directionality in an SPD entry, \r
+ @param[in] Direction The directionality in an SPD entry,\r
EfiIPsecInBound or EfiIPsecOutBound.\r
@param[in] Context The token's wrap.\r
\r
@retval EFI_SUCCESS The IPsec protocol is not available or disabled.\r
@retval EFI_SUCCESS The packet was bypassed and all buffers remain the same.\r
@retval EFI_SUCCESS The packet was protected.\r
- @retval EFI_ACCESS_DENIED The packet was discarded. \r
+ @retval EFI_ACCESS_DENIED The packet was discarded.\r
@retval EFI_OUT_OF_RESOURCES There is no suffcient resource to complete the operation.\r
- @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than the \r
+ @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than the\r
number of input data blocks when build a fragment table.\r
\r
**/\r
IP4_HEAD ZeroHead;\r
\r
Status = EFI_SUCCESS;\r
+\r
+ if (!mIpSec2Installed) {\r
+ goto ON_EXIT;\r
+ }\r
+ ASSERT (mIpSec != NULL);\r
+\r
Packet = *Netbuf;\r
RecycleEvent = NULL;\r
IpSecWrap = NULL;\r
FragmentTable = NULL;\r
- TxWrap = (IP4_TXTOKEN_WRAP *) Context; \r
+ TxWrap = (IP4_TXTOKEN_WRAP *) Context;\r
FragmentCount = Packet->BlockOpNum;\r
\r
ZeroMem (&ZeroHead, sizeof (IP4_HEAD));\r
- \r
- if (mIpSec == NULL) {\r
- gBS->LocateProtocol (&gEfiIpSecProtocolGuid, NULL, (VOID **) &mIpSec);\r
- if (mIpSec == NULL) {\r
- goto ON_EXIT;\r
- }\r
- }\r
\r
//\r
// Check whether the IPsec enable variable is set.\r
if (mIpSec->DisabledFlag) {\r
//\r
// If IPsec is disabled, restore the original MTU\r
- // \r
+ //\r
IpSb->MaxPacketSize = IpSb->OldMaxPacketSize;\r
goto ON_EXIT;\r
} else {\r
//\r
- // If IPsec is enabled, use the MTU which reduce the IPsec header length. \r
+ // If IPsec is enabled, use the MTU which reduce the IPsec header length.\r
//\r
- IpSb->MaxPacketSize = IpSb->OldMaxPacketSize - IP4_MAX_IPSEC_HEADLEN; \r
+ IpSb->MaxPacketSize = IpSb->OldMaxPacketSize - IP4_MAX_IPSEC_HEADLEN;\r
}\r
\r
//\r
Status = EFI_OUT_OF_RESOURCES;\r
goto ON_EXIT;\r
}\r
- \r
+\r
Status = NetbufBuildExt (Packet, FragmentTable, &FragmentCount);\r
- \r
+\r
//\r
// Record the original FragmentTable and count.\r
//\r
// Convert host byte order to network byte order\r
//\r
Ip4NtohHead (*Head);\r
- \r
+\r
Status = mIpSec->ProcessExt (\r
mIpSec,\r
IpSb->Controller,\r
IP_VERSION_4,\r
(VOID *) (*Head),\r
&(*Head)->Protocol,\r
- (VOID **)Options,\r
+ (VOID **) Options,\r
OptionsLen,\r
(EFI_IPSEC_FRAGMENT_DATA **) (&FragmentTable),\r
&FragmentCount,\r
// Convert back to host byte order\r
//\r
Ip4NtohHead (*Head);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
+ FreePool (OriginalFragmentTable);\r
goto ON_EXIT;\r
}\r
\r
if (OriginalFragmentTable == FragmentTable && OriginalFragmentCount == FragmentCount) {\r
+ //\r
+ // For ByPass Packet\r
+ //\r
+ FreePool (FragmentTable);\r
goto ON_EXIT;\r
+ } else {\r
+ //\r
+ // Free the FragmentTable which allocated before calling the IPsec.\r
+ //\r
+ FreePool (OriginalFragmentTable);\r
}\r
\r
if (Direction == EfiIPsecOutBound && TxWrap != NULL) {\r
- \r
+\r
TxWrap->IpSecRecycleSignal = RecycleEvent;\r
TxWrap->Packet = NetbufFromExt (\r
FragmentTable,\r
TxWrap\r
);\r
if (TxWrap->Packet == NULL) {\r
+ //\r
+ // Recover the TxWrap->Packet, if meet a error, and the caller will free\r
+ // the TxWrap.\r
+ //\r
+ TxWrap->Packet = *Netbuf;\r
Status = EFI_OUT_OF_RESOURCES;\r
goto ON_EXIT;\r
}\r
//\r
NetIpSecNetbufFree (*Netbuf);\r
*Netbuf = TxWrap->Packet;\r
- \r
+\r
} else {\r
- \r
+\r
IpSecWrap = AllocateZeroPool (sizeof (IP4_IPSEC_WRAP));\r
- \r
+\r
if (IpSecWrap == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ gBS->SignalEvent (RecycleEvent);\r
goto ON_EXIT;\r
}\r
- \r
+\r
IpSecWrap->IpSecRecycleSignal = RecycleEvent;\r
IpSecWrap->Packet = Packet;\r
Packet = NetbufFromExt (\r
- FragmentTable, \r
- FragmentCount, \r
- IP4_MAX_HEADLEN, \r
- 0, \r
- Ip4IpSecFree, \r
+ FragmentTable,\r
+ FragmentCount,\r
+ IP4_MAX_HEADLEN,\r
+ 0,\r
+ Ip4IpSecFree,\r
IpSecWrap\r
);\r
- \r
+\r
if (Packet == NULL) {\r
+ Packet = IpSecWrap->Packet;\r
+ gBS->SignalEvent (RecycleEvent);\r
+ FreePool (IpSecWrap);\r
Status = EFI_OUT_OF_RESOURCES;\r
goto ON_EXIT;\r
}\r
/**\r
Pre-process the IPv4 packet. First validates the IPv4 packet, and\r
then reassembles packet if it is necessary.\r
- \r
+\r
@param[in] IpSb Pointer to IP4_SERVICE.\r
@param[in, out] Packet Pointer to the Packet to be processed.\r
@param[in] Head Pointer to the IP4_HEAD.\r
as multicast.\r
\r
@retval EFI_SEUCCESS The recieved packet is in well form.\r
- @retval EFI_INVAILD_PARAMETER The recieved packet is malformed. \r
+ @retval EFI_INVAILD_PARAMETER The recieved packet is malformed.\r
\r
**/\r
EFI_STATUS\r
IN OUT NET_BUF **Packet,\r
IN IP4_HEAD *Head,\r
IN UINT8 *Option,\r
- IN UINT32 OptionLen, \r
+ IN UINT32 OptionLen,\r
IN UINT32 Flag\r
- ) \r
+ )\r
{\r
IP4_CLIP_INFO *Info;\r
UINT32 HeadLen;\r
UINT16 Checksum;\r
\r
//\r
- // Check that the IP4 header is correctly formatted\r
+ // Check if the IP4 header is correctly formatted.\r
//\r
if ((*Packet)->TotalSize < IP4_MIN_HEADLEN) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
HeadLen = (Head->HeadLen << 2);\r
TotalLen = NTOHS (Head->TotalLen);\r
\r
// Validate the options. Don't call the Ip4OptionIsValid if\r
// there is no option to save some CPU process.\r
//\r
- \r
+\r
if ((OptionLen > 0) && !Ip4OptionIsValid (Option, OptionLen, TRUE)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
- // Trim the head off, after this point, the packet is headless.\r
+ // Trim the head off, after this point, the packet is headless,\r
// and Packet->TotalLen == Info->Length.\r
//\r
NetbufTrim (*Packet, HeadLen, TRUE);\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
- \r
+\r
return EFI_SUCCESS;\r
}\r
\r
IP4_HEAD ZeroHead;\r
UINT8 *Option;\r
UINT32 OptionLen;\r
- \r
+\r
IpSb = (IP4_SERVICE *) Context;\r
Option = NULL;\r
\r
- if (EFI_ERROR (IoStatus) || (IpSb->State == IP4_SERVICE_DESTORY)) {\r
+ if (EFI_ERROR (IoStatus) || (IpSb->State == IP4_SERVICE_DESTROY)) {\r
goto DROP;\r
}\r
\r
- Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL); \r
+ Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL);\r
+ ASSERT (Head != NULL);\r
OptionLen = (Head->HeadLen << 2) - IP4_MIN_HEADLEN;\r
if (OptionLen > 0) {\r
Option = (UINT8 *) (Head + 1);\r
// Validate packet format and reassemble packet if it is necessary.\r
//\r
Status = Ip4PreProcessPacket (\r
- IpSb, \r
- &Packet, \r
- Head, \r
+ IpSb,\r
+ &Packet,\r
+ Head,\r
Option,\r
- OptionLen, \r
+ OptionLen,\r
Flag\r
);\r
\r
// and no need consider any other ahead ext headers.\r
//\r
Status = Ip4IpSecProcessPacket (\r
- IpSb, \r
- &Head, \r
- &Packet, \r
+ IpSb,\r
+ &Head,\r
+ &Packet,\r
&Option,\r
- &OptionLen, \r
+ &OptionLen,\r
EfiIPsecInBound,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
goto RESTART;\r
}\r
- \r
+\r
//\r
// If the packet is protected by tunnel mode, parse the inner Ip Packet.\r
//\r
// is transfered to the packet process logic.\r
//\r
Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL);\r
+ ASSERT (Head != NULL);\r
Status = Ip4PreProcessPacket (\r
- IpSb, \r
- &Packet, \r
- Head, \r
+ IpSb,\r
+ &Packet,\r
+ Head,\r
Option,\r
- OptionLen, \r
+ OptionLen,\r
Flag\r
);\r
if (EFI_ERROR (Status)) {\r
goto RESTART;\r
}\r
}\r
- \r
+\r
ASSERT (Packet != NULL);\r
Head = Packet->Ip.Ip4;\r
IP4_GET_CLIP_INFO (Packet)->Status = EFI_SUCCESS;\r
break;\r
\r
default:\r
- Ip4Demultiplex (IpSb, Head, Packet);\r
+ Ip4Demultiplex (IpSb, Head, Packet, Option, OptionLen);\r
}\r
\r
Packet = NULL;\r
to the upper layer. Upper layer will signal the recycle event in\r
it when it is done with the packet.\r
\r
- @param[in] IpInstance The IP4 child to receive the packet\r
- @param[in] Packet The packet to deliver up.\r
+ @param[in] IpInstance The IP4 child to receive the packet.\r
+ @param[in] Packet The packet to deliver up.\r
\r
@retval Wrap if warp the packet succeed.\r
@retval NULL failed to wrap the packet .\r
IP4_RXDATA_WRAP *Wrap;\r
EFI_IP4_RECEIVE_DATA *RxData;\r
EFI_STATUS Status;\r
+ BOOLEAN RawData;\r
\r
Wrap = AllocatePool (IP4_RXDATA_WRAP_SIZE (Packet->BlockOpNum));\r
\r
Wrap->Packet = Packet;\r
RxData = &Wrap->RxData;\r
\r
- ZeroMem (&RxData->TimeStamp, sizeof (EFI_TIME));\r
+ ZeroMem (RxData, sizeof (EFI_IP4_RECEIVE_DATA));\r
\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_SIGNAL,\r
\r
ASSERT (Packet->Ip.Ip4 != NULL);\r
\r
+ ASSERT (IpInstance != NULL);\r
+ RawData = IpInstance->ConfigData.RawData;\r
+\r
//\r
// The application expects a network byte order header.\r
//\r
- RxData->HeaderLength = (Packet->Ip.Ip4->HeadLen << 2);\r
- RxData->Header = (EFI_IP4_HEADER *) Ip4NtohHead (Packet->Ip.Ip4);\r
+ if (!RawData) {\r
+ RxData->HeaderLength = (Packet->Ip.Ip4->HeadLen << 2);\r
+ RxData->Header = (EFI_IP4_HEADER *) Ip4NtohHead (Packet->Ip.Ip4);\r
+ RxData->OptionsLength = RxData->HeaderLength - IP4_MIN_HEADLEN;\r
+ RxData->Options = NULL;\r
\r
- RxData->OptionsLength = RxData->HeaderLength - IP4_MIN_HEADLEN;\r
- RxData->Options = NULL;\r
-\r
- if (RxData->OptionsLength != 0) {\r
- RxData->Options = (VOID *) (RxData->Header + 1);\r
+ if (RxData->OptionsLength != 0) {\r
+ RxData->Options = (VOID *) (RxData->Header + 1);\r
+ }\r
}\r
\r
RxData->DataLength = Packet->TotalSize;\r
NET_BUF *Packet;\r
NET_BUF *Dup;\r
UINT8 *Head;\r
+ UINT32 HeadLen;\r
\r
//\r
// Deliver a packet if there are both a packet and a receive token.\r
//\r
// Create a duplicated packet if this packet is shared\r
//\r
- Dup = NetbufDuplicate (Packet, NULL, IP4_MAX_HEADLEN);\r
+ if (IpInstance->ConfigData.RawData) {\r
+ HeadLen = 0;\r
+ } else {\r
+ HeadLen = IP4_MAX_HEADLEN;\r
+ }\r
+\r
+ Dup = NetbufDuplicate (Packet, NULL, HeadLen);\r
\r
if (Dup == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- //\r
- // Copy the IP head over. The packet to deliver up is\r
- // headless. Trim the head off after copy. The IP head\r
- // may be not continuous before the data.\r
- //\r
- Head = NetbufAllocSpace (Dup, IP4_MAX_HEADLEN, NET_BUF_HEAD);\r
- Dup->Ip.Ip4 = (IP4_HEAD *) Head;\r
+ if (!IpInstance->ConfigData.RawData) {\r
+ //\r
+ // Copy the IP head over. The packet to deliver up is\r
+ // headless. Trim the head off after copy. The IP head\r
+ // may be not continuous before the data.\r
+ //\r
+ Head = NetbufAllocSpace (Dup, IP4_MAX_HEADLEN, NET_BUF_HEAD);\r
+ ASSERT (Head != NULL);\r
\r
- CopyMem (Head, Packet->Ip.Ip4, Packet->Ip.Ip4->HeadLen << 2);\r
- NetbufTrim (Dup, IP4_MAX_HEADLEN, TRUE);\r
+ Dup->Ip.Ip4 = (IP4_HEAD *) Head;\r
+\r
+ CopyMem (Head, Packet->Ip.Ip4, Packet->Ip.Ip4->HeadLen << 2);\r
+ NetbufTrim (Dup, IP4_MAX_HEADLEN, TRUE);\r
+ }\r
\r
Wrap = Ip4WrapRxData (IpInstance, Dup);\r
\r
Enqueue a received packet to all the IP children that share\r
the same interface.\r
\r
- @param[in] IpSb The IP4 service instance that receive the packet\r
- @param[in] Head The header of the received packet\r
- @param[in] Packet The data of the received packet\r
- @param[in] IpIf The interface to enqueue the packet to\r
+ @param[in] IpSb The IP4 service instance that receive the packet.\r
+ @param[in] Head The header of the received packet.\r
+ @param[in] Packet The data of the received packet.\r
+ @param[in] Option Point to the IP4 packet header options.\r
+ @param[in] OptionLen Length of the IP4 packet header options.\r
+ @param[in] IpIf The interface to enqueue the packet to.\r
\r
@return The number of the IP4 children that accepts the packet\r
\r
IN IP4_SERVICE *IpSb,\r
IN IP4_HEAD *Head,\r
IN NET_BUF *Packet,\r
+ IN UINT8 *Option,\r
+ IN UINT32 OptionLen,\r
IN IP4_INTERFACE *IpIf\r
)\r
{\r
IpInstance = NET_LIST_USER_STRUCT (Entry, IP4_PROTOCOL, AddrLink);\r
NET_CHECK_SIGNATURE (IpInstance, IP4_PROTOCOL_SIGNATURE);\r
\r
+ //\r
+ // In RawData mode, add IPv4 headers and options back to packet.\r
+ //\r
+ if ((IpInstance->ConfigData.RawData) && (Option != NULL) && (OptionLen != 0)){\r
+ Ip4PrependHead (Packet, Head, Option, OptionLen);\r
+ }\r
+\r
if (Ip4InstanceEnquePacket (IpInstance, Head, Packet) == EFI_SUCCESS) {\r
Enqueued++;\r
}\r
child wants to consume the packet because each IP child needs\r
its own copy of the packet to make changes.\r
\r
- @param[in] IpSb The IP4 service instance that received the packet\r
- @param[in] Head The header of the received packet\r
- @param[in] Packet The data of the received packet\r
+ @param[in] IpSb The IP4 service instance that received the packet.\r
+ @param[in] Head The header of the received packet.\r
+ @param[in] Packet The data of the received packet.\r
+ @param[in] Option Point to the IP4 packet header options.\r
+ @param[in] OptionLen Length of the IP4 packet header options.\r
\r
- @retval EFI_NOT_FOUND No IP child accepts the packet\r
+ @retval EFI_NOT_FOUND No IP child accepts the packet.\r
@retval EFI_SUCCESS The packet is enqueued or delivered to some IP\r
children.\r
\r
Ip4Demultiplex (\r
IN IP4_SERVICE *IpSb,\r
IN IP4_HEAD *Head,\r
- IN NET_BUF *Packet\r
+ IN NET_BUF *Packet,\r
+ IN UINT8 *Option,\r
+ IN UINT32 OptionLen\r
)\r
{\r
LIST_ENTRY *Entry;\r
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);\r
\r
if (IpIf->Configured) {\r
- Enqueued += Ip4InterfaceEnquePacket (IpSb, Head, Packet, IpIf);\r
+ Enqueued += Ip4InterfaceEnquePacket (\r
+ IpSb,\r
+ Head,\r
+ Packet,\r
+ Option,\r
+ OptionLen,\r
+ IpIf\r
+ );\r
}\r
}\r
\r