/** @file\r
-\r
-Copyright (c) 2005 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- Ip4Input.c\r
-\r
-Abstract:\r
-\r
IP4 input process.\r
\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
(Dst, Src, Id, Protocol). The default life for the packet is\r
120 seconds.\r
\r
- @param Dst The destination address\r
- @param Src The source address\r
- @param Id The ID field in IP header\r
- @param Protocol The protocol field in IP header\r
+ @param[in] Dst The destination address\r
+ @param[in] Src The source address\r
+ @param[in] Id The ID field in IP header\r
+ @param[in] Protocol The protocol field in IP header\r
\r
@return NULL if failed to allocate memory for the entry, otherwise\r
- @return the point to just created reassemble entry.\r
+ the point to just created reassemble entry.\r
\r
**/\r
IP4_ASSEMBLE_ENTRY *\r
/**\r
Release all the fragments of a packet, then free the assemble entry.\r
\r
- @param Assemble The assemble entry to free\r
-\r
- @return None\r
+ @param[in] Assemble The assemble entry to free\r
\r
**/\r
VOID\r
NetbufFree (Fragment);\r
}\r
\r
- gBS->FreePool (Assemble);\r
+ FreePool (Assemble);\r
}\r
\r
\r
Initialize an already allocated assemble table. This is generally\r
the assemble table embedded in the IP4 service instance.\r
\r
- @param Table The assemble table to initialize.\r
-\r
- @return NONE\r
+ @param[in, out] Table The assemble table to initialize.\r
\r
**/\r
VOID\r
Clean up the assemble table: remove all the fragments\r
and assemble entries.\r
\r
- @param Table The assemble table to clean up\r
-\r
- @return None\r
+ @param[in] Table The assemble table to clean up\r
\r
**/\r
VOID\r
@param Start The sequence of the first byte to fit in\r
@param End One beyond the sequence of last byte to fit in.\r
\r
- @return None\r
-\r
**/\r
VOID\r
Ip4TrimPacket (\r
the assembled packet's OnFree. It will free the assemble entry,\r
which in turn will free all the fragments of the packet.\r
\r
- @param Arg The assemble entry to free\r
-\r
- @return None\r
+ @param[in] Arg The assemble entry to free\r
\r
**/\r
VOID\r
+EFIAPI\r
Ip4OnFreeFragments (\r
IN VOID *Arg\r
)\r
NET_BUF *NewPacket;\r
INTN Index;\r
\r
- IpHead = Packet->Ip;\r
+ IpHead = Packet->Ip.Ip4;\r
This = IP4_GET_CLIP_INFO (Packet);\r
\r
ASSERT (IpHead != NULL);\r
\r
InsertHeadList (&Table->Bucket[Index], &Assemble->Link);\r
}\r
+ //\r
+ // Assemble shouldn't be NULL here\r
+ //\r
+ ASSERT (Assemble != NULL);\r
\r
//\r
// Find the point to insert the packet: before the first\r
// check whether THIS.Start < PREV.End for overlap. If two fragments\r
// overlaps, trim the overlapped part off THIS fragment.\r
//\r
- if ((Prev = Cur->ForwardLink) != 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
return NULL;\r
}\r
\r
- NewPacket->Ip = Assemble->Head;\r
- CopyMem (IP4_GET_CLIP_INFO (NewPacket), Assemble->Info, sizeof (*IP4_GET_CLIP_INFO (NewPacket)));\r
+ NewPacket->Ip.Ip4 = Assemble->Head;\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
return NULL;\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
+\r
+ @param[in] Arg The wrap context\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ip4IpSecFree (\r
+ IN VOID *Arg\r
+ )\r
+{\r
+ IP4_IPSEC_WRAP *Wrap;\r
+\r
+ Wrap = (IP4_IPSEC_WRAP *) Arg;\r
+\r
+ if (Wrap->IpSecRecycleSignal != NULL) {\r
+ gBS->SignalEvent (Wrap->IpSecRecycleSignal);\r
+ }\r
+\r
+ NetbufFree (Wrap->Packet);\r
+\r
+ FreePool (Wrap);\r
+\r
+ return;\r
+}\r
\r
/**\r
- The IP4 input routine. It is called by the IP4_INTERFACE when a\r
- IP4 fragment is received from MNP.\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
+\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
+ 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_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
+ number of input data blocks when build a fragment table.\r
\r
- @param Ip4Instance The IP4 child that request the receive, most like\r
- it is NULL.\r
- @param Packet The IP4 packet received.\r
- @param IoStatus The return status of receive request.\r
- @param Flag The link layer flag for the packet received, such\r
- as multicast.\r
- @param Context The IP4 service instance that own the MNP.\r
+**/\r
+EFI_STATUS\r
+Ip4IpSecProcessPacket (\r
+ IN IP4_SERVICE *IpSb,\r
+ IN OUT IP4_HEAD **Head,\r
+ IN OUT NET_BUF **Netbuf,\r
+ IN OUT UINT8 **Options,\r
+ IN OUT UINT32 *OptionsLen,\r
+ IN EFI_IPSEC_TRAFFIC_DIR Direction,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ NET_FRAGMENT *FragmentTable;\r
+ NET_FRAGMENT *OriginalFragmentTable;\r
+ UINT32 FragmentCount;\r
+ UINT32 OriginalFragmentCount;\r
+ EFI_EVENT RecycleEvent;\r
+ NET_BUF *Packet;\r
+ IP4_TXTOKEN_WRAP *TxWrap;\r
+ IP4_IPSEC_WRAP *IpSecWrap;\r
+ EFI_STATUS Status;\r
+ IP4_HEAD ZeroHead;\r
+\r
+ Status = EFI_SUCCESS;\r
\r
- @return None\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
+ FragmentCount = Packet->BlockOpNum;\r
+\r
+ ZeroMem (&ZeroHead, sizeof (IP4_HEAD));\r
+\r
+ //\r
+ // Check whether the IPsec enable variable is set.\r
+ //\r
+ if (mIpSec->DisabledFlag) {\r
+ //\r
+ // If IPsec is disabled, restore the original MTU\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
+ //\r
+ IpSb->MaxPacketSize = IpSb->OldMaxPacketSize - IP4_MAX_IPSEC_HEADLEN;\r
+ }\r
+\r
+ //\r
+ // Rebuild fragment table from netbuf to ease IPsec process.\r
+ //\r
+ FragmentTable = AllocateZeroPool (FragmentCount * sizeof (NET_FRAGMENT));\r
+\r
+ if (FragmentTable == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = NetbufBuildExt (Packet, FragmentTable, &FragmentCount);\r
+\r
+ //\r
+ // Record the original FragmentTable and count.\r
+ //\r
+ OriginalFragmentTable = FragmentTable;\r
+ OriginalFragmentCount = FragmentCount;\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (FragmentTable);\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Convert host byte order to network byte order\r
+ //\r
+ Ip4NtohHead (*Head);\r
+\r
+ Status = mIpSec->ProcessExt (\r
+ mIpSec,\r
+ IpSb->Controller,\r
+ IP_VERSION_4,\r
+ (VOID *) (*Head),\r
+ &(*Head)->Protocol,\r
+ (VOID **) Options,\r
+ OptionsLen,\r
+ (EFI_IPSEC_FRAGMENT_DATA **) (&FragmentTable),\r
+ &FragmentCount,\r
+ Direction,\r
+ &RecycleEvent\r
+ );\r
+ //\r
+ // Convert back to host byte order\r
+ //\r
+ Ip4NtohHead (*Head);\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
+ TxWrap->IpSecRecycleSignal = RecycleEvent;\r
+ TxWrap->Packet = NetbufFromExt (\r
+ FragmentTable,\r
+ FragmentCount,\r
+ IP4_MAX_HEADLEN,\r
+ 0,\r
+ Ip4FreeTxToken,\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
+ //\r
+ // Free orginal Netbuf.\r
+ //\r
+ NetIpSecNetbufFree (*Netbuf);\r
+ *Netbuf = TxWrap->Packet;\r
+\r
+ } else {\r
+\r
+ IpSecWrap = AllocateZeroPool (sizeof (IP4_IPSEC_WRAP));\r
+\r
+ if (IpSecWrap == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ gBS->SignalEvent (RecycleEvent);\r
+ goto ON_EXIT;\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
+ IpSecWrap\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
+ if (Direction == EfiIPsecInBound && 0 != CompareMem (*Head, &ZeroHead, sizeof (IP4_HEAD))) {\r
+ Ip4PrependHead (Packet, *Head, *Options, *OptionsLen);\r
+ Ip4NtohHead (Packet->Ip.Ip4);\r
+ NetbufTrim (Packet, ((*Head)->HeadLen << 2), TRUE);\r
+\r
+ CopyMem (\r
+ IP4_GET_CLIP_INFO (Packet),\r
+ IP4_GET_CLIP_INFO (IpSecWrap->Packet),\r
+ sizeof (IP4_CLIP_INFO)\r
+ );\r
+ }\r
+ *Netbuf = Packet;\r
+ }\r
+\r
+ON_EXIT:\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Pre-process the IPv4 packet. First validates the IPv4 packet, and\r
+ then reassembles packet if it is necessary.\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
+ @param[in] Option Pointer to a buffer which contains the IPv4 option.\r
+ @param[in] OptionLen The length of Option in bytes.\r
+ @param[in] Flag The link layer flag for the packet received, such\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
\r
**/\r
-VOID\r
-Ip4AccpetFrame (\r
- IN IP4_PROTOCOL *Ip4Instance,\r
- IN NET_BUF *Packet,\r
- IN EFI_STATUS IoStatus,\r
- IN UINT32 Flag,\r
- IN VOID *Context\r
+EFI_STATUS\r
+Ip4PreProcessPacket (\r
+ IN IP4_SERVICE *IpSb,\r
+ IN OUT NET_BUF **Packet,\r
+ IN IP4_HEAD *Head,\r
+ IN UINT8 *Option,\r
+ IN UINT32 OptionLen,\r
+ IN UINT32 Flag\r
)\r
{\r
- IP4_SERVICE *IpSb;\r
IP4_CLIP_INFO *Info;\r
- IP4_HEAD *Head;\r
UINT32 HeadLen;\r
- UINT32 OptionLen;\r
UINT32 TotalLen;\r
UINT16 Checksum;\r
\r
- IpSb = (IP4_SERVICE *) Context;\r
-\r
- if (EFI_ERROR (IoStatus) || (IpSb->State == IP4_SERVICE_DESTORY)) {\r
- goto DROP;\r
- }\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
- goto RESTART;\r
+ if ((*Packet)->TotalSize < IP4_MIN_HEADLEN) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
- Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL);\r
HeadLen = (Head->HeadLen << 2);\r
TotalLen = NTOHS (Head->TotalLen);\r
\r
//\r
// Mnp may deliver frame trailer sequence up, trim it off.\r
//\r
- if (TotalLen < Packet->TotalSize) {\r
- NetbufTrim (Packet, Packet->TotalSize - TotalLen, FALSE);\r
+ if (TotalLen < (*Packet)->TotalSize) {\r
+ NetbufTrim (*Packet, (*Packet)->TotalSize - TotalLen, FALSE);\r
}\r
\r
if ((Head->Ver != 4) || (HeadLen < IP4_MIN_HEADLEN) ||\r
- (TotalLen < HeadLen) || (TotalLen != Packet->TotalSize)) {\r
- goto RESTART;\r
+ (TotalLen < HeadLen) || (TotalLen != (*Packet)->TotalSize)) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
Checksum = (UINT16) (~NetblockChecksum ((UINT8 *) Head, HeadLen));\r
\r
if ((Head->Checksum != 0) && (Checksum != 0)) {\r
- goto RESTART;\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
// Convert the IP header to host byte order, then get the per packet info.\r
//\r
- Packet->Ip = Ip4NtohHead (Head);\r
+ (*Packet)->Ip.Ip4 = Ip4NtohHead (Head);\r
\r
- Info = IP4_GET_CLIP_INFO (Packet);\r
+ Info = IP4_GET_CLIP_INFO (*Packet);\r
Info->LinkFlag = Flag;\r
Info->CastType = Ip4GetHostCast (IpSb, Head->Dst, Head->Src);\r
Info->Start = (Head->Fragment & IP4_HEAD_OFFSET_MASK) << 3;\r
// The packet is destinated to us if the CastType is non-zero.\r
//\r
if ((Info->CastType == 0) || (Info->End > IP4_MAX_PACKET_SIZE)) {\r
- goto RESTART;\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
// Validate the options. Don't call the Ip4OptionIsValid if\r
// there is no option to save some CPU process.\r
//\r
- OptionLen = HeadLen - IP4_MIN_HEADLEN;\r
\r
- if ((OptionLen > 0) && !Ip4OptionIsValid ((UINT8 *) (Head + 1), OptionLen, TRUE)) {\r
- goto RESTART;\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
+ NetbufTrim (*Packet, HeadLen, TRUE);\r
\r
//\r
// Reassemble the packet if this is a fragment. The packet is a\r
// fragment if its head has MF (more fragment) set, or it starts\r
// at non-zero byte.\r
//\r
- if ((Head->Fragment & IP4_HEAD_MF_MASK) || (Info->Start != 0)) {\r
+ if (((Head->Fragment & IP4_HEAD_MF_MASK) != 0) || (Info->Start != 0)) {\r
//\r
// Drop the fragment if DF is set but it is fragmented. Gateway\r
// need to send a type 4 destination unreache ICMP message here.\r
//\r
- if (Head->Fragment & IP4_HEAD_DF_MASK) {\r
- goto RESTART;\r
+ if ((Head->Fragment & IP4_HEAD_DF_MASK) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
// The length of all but the last fragments is in the unit of 8 bytes.\r
//\r
- if ((Head->Fragment & IP4_HEAD_MF_MASK) && (Info->Length % 8 != 0)) {\r
- goto RESTART;\r
+ if (((Head->Fragment & IP4_HEAD_MF_MASK) != 0) && (Info->Length % 8 != 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
- Packet = Ip4Reassemble (&IpSb->Assemble, Packet);\r
+ *Packet = Ip4Reassemble (&IpSb->Assemble, *Packet);\r
\r
//\r
// Packet assembly isn't complete, start receive more packet.\r
//\r
- if (Packet == NULL) {\r
- goto RESTART;\r
+ if (*Packet == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
}\r
\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ The IP4 input routine. It is called by the IP4_INTERFACE when a\r
+ IP4 fragment is received from MNP.\r
+\r
+ @param[in] Ip4Instance The IP4 child that request the receive, most like\r
+ it is NULL.\r
+ @param[in] Packet The IP4 packet received.\r
+ @param[in] IoStatus The return status of receive request.\r
+ @param[in] Flag The link layer flag for the packet received, such\r
+ as multicast.\r
+ @param[in] Context The IP4 service instance that own the MNP.\r
+\r
+**/\r
+VOID\r
+Ip4AccpetFrame (\r
+ IN IP4_PROTOCOL *Ip4Instance,\r
+ IN NET_BUF *Packet,\r
+ IN EFI_STATUS IoStatus,\r
+ IN UINT32 Flag,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ IP4_SERVICE *IpSb;\r
+ IP4_HEAD *Head;\r
+ EFI_STATUS Status;\r
+ IP4_HEAD ZeroHead;\r
+ UINT8 *Option;\r
+ UINT32 OptionLen;\r
+\r
+ IpSb = (IP4_SERVICE *) Context;\r
+ Option = NULL;\r
+\r
+ if (EFI_ERROR (IoStatus) || (IpSb->State == IP4_SERVICE_DESTROY)) {\r
+ goto DROP;\r
+ }\r
+\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
+ }\r
+\r
+ //\r
+ // Validate packet format and reassemble packet if it is necessary.\r
+ //\r
+ Status = Ip4PreProcessPacket (\r
+ IpSb,\r
+ &Packet,\r
+ Head,\r
+ Option,\r
+ OptionLen,\r
+ Flag\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto RESTART;\r
+ }\r
+\r
+ //\r
+ // After trim off, the packet is a esp/ah/udp/tcp/icmp6 net buffer,\r
+ // and no need consider any other ahead ext headers.\r
+ //\r
+ Status = Ip4IpSecProcessPacket (\r
+ IpSb,\r
+ &Head,\r
+ &Packet,\r
+ &Option,\r
+ &OptionLen,\r
+ EfiIPsecInBound,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto RESTART;\r
+ }\r
+\r
+ //\r
+ // If the packet is protected by tunnel mode, parse the inner Ip Packet.\r
//\r
+ ZeroMem (&ZeroHead, sizeof (IP4_HEAD));\r
+ if (0 == CompareMem (Head, &ZeroHead, sizeof (IP4_HEAD))) {\r
// Packet may have been changed. Head, HeadLen, TotalLen, and\r
// info must be reloaded bofore use. The ownership of the packet\r
// is transfered to the packet process logic.\r
//\r
- Head = Packet->Ip;\r
+ Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL);\r
+ ASSERT (Head != NULL);\r
+ Status = Ip4PreProcessPacket (\r
+ IpSb,\r
+ &Packet,\r
+ Head,\r
+ Option,\r
+ OptionLen,\r
+ Flag\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto RESTART;\r
+ }\r
+ }\r
+\r
+ ASSERT (Packet != NULL);\r
+ Head = Packet->Ip.Ip4;\r
IP4_GET_CLIP_INFO (Packet)->Status = EFI_SUCCESS;\r
\r
switch (Head->Protocol) {\r
- case IP4_PROTO_ICMP:\r
+ case EFI_IP_PROTO_ICMP:\r
Ip4IcmpHandle (IpSb, Head, Packet);\r
break;\r
\r
break;\r
\r
default:\r
- Ip4Demultiplex (IpSb, Head, Packet);\r
+ Ip4Demultiplex (IpSb, Head, Packet, Option, OptionLen);\r
}\r
\r
Packet = NULL;\r
// Dispatch the DPCs queued by the NotifyFunction of the rx token's events\r
// which are signaled with received data.\r
//\r
- NetLibDispatchDpc ();\r
+ DispatchDpc ();\r
\r
RESTART:\r
Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);\r
/**\r
Check whether this IP child accepts the packet.\r
\r
- @param IpInstance The IP child to check\r
- @param Head The IP header of the packet\r
- @param Packet The data of the packet\r
+ @param[in] IpInstance The IP child to check\r
+ @param[in] Head The IP header of the packet\r
+ @param[in] Packet The data of the packet\r
\r
@retval TRUE If the child wants to receive the packet.\r
@retval FALSE Otherwise.\r
//\r
// Use protocol from the IP header embedded in the ICMP error\r
// message to filter, instead of ICMP itself. ICMP handle will\r
- // can Ip4Demultiplex to deliver ICMP errors.\r
+ // call Ip4Demultiplex to deliver ICMP errors.\r
//\r
Proto = Head->Protocol;\r
\r
- if (Proto == IP4_PROTO_ICMP) {\r
+ if ((Proto == EFI_IP_PROTO_ICMP) && (!Config->AcceptAnyProtocol) && (Proto != Config->DefaultProtocol)) {\r
NetbufCopy (Packet, 0, sizeof (Icmp.Head), (UINT8 *) &Icmp.Head);\r
\r
if (mIcmpClass[Icmp.Head.Type].IcmpClass == ICMP_ERROR_MESSAGE) {\r
packet is acceptable to it. Here the data of the packet is\r
shared, but the net buffer isn't.\r
\r
- @param IpInstance The IP4 child to enqueue the packet to\r
- @param Head The IP header of the received packet\r
- @param Packet The data of the received packet\r
+ @param[in] IpInstance The IP4 child to enqueue the packet to\r
+ @param[in] Head The IP header of the received packet\r
+ @param[in] Packet The data of the received packet\r
\r
@retval EFI_NOT_STARTED The IP child hasn't been configured.\r
@retval EFI_INVALID_PARAMETER The child doesn't want to receive the packet\r
The signal handle of IP4's recycle event. It is called back\r
when the upper layer release the packet.\r
\r
- @param Event The IP4's recycle event.\r
- @param Context The context of the handle, which is a\r
- IP4_RXDATA_WRAP\r
-\r
- @return None\r
+ @param Event The IP4's recycle event.\r
+ @param Context The context of the handle, which is a\r
+ IP4_RXDATA_WRAP\r
\r
**/\r
VOID\r
NetbufFree (Wrap->Packet);\r
\r
gBS->CloseEvent (Wrap->RxData.RecycleSignal);\r
- gBS->FreePool (Wrap);\r
+ FreePool (Wrap);\r
}\r
\r
\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 IpInstance The IP4 child to receive the packet\r
- @param 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
- @return NULL if failed to wrap the packet, otherwise the wrapper.\r
+ @retval Wrap if warp the packet succeed.\r
+ @retval NULL failed to wrap the packet .\r
\r
**/\r
IP4_RXDATA_WRAP *\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
\r
if (EFI_ERROR (Status)) {\r
- gBS->FreePool (Wrap);\r
+ FreePool (Wrap);\r
return NULL;\r
}\r
\r
- ASSERT (Packet->Ip != NULL);\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->HeadLen << 2);\r
- RxData->Header = (EFI_IP4_HEADER *) Ip4NtohHead (Packet->Ip);\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
duplicate it to a non-shared packet, release the shared packet, then\r
deliver the non-shared packet up.\r
\r
- @param IpInstance The IP child to deliver the packet up.\r
+ @param[in] IpInstance The IP child to deliver the packet up.\r
\r
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources to deliver the\r
packets.\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_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, Packet->Ip->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 IpSb The IP4 service instance that receive the packet\r
- @param Head The header of the received packet\r
- @param Packet The data of the received packet\r
- @param 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
/**\r
Deliver the packet for each IP4 child on the interface.\r
\r
- @param IpSb The IP4 service instance that received the packet\r
- @param IpIf The IP4 interface to deliver the packet.\r
+ @param[in] IpSb The IP4 service instance that received the packet\r
+ @param[in] IpIf The IP4 interface to deliver the packet.\r
\r
@retval EFI_SUCCESS It always returns EFI_SUCCESS now\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 IpSb The IP4 service instance that received the packet\r
- @param Head The header of the received packet\r
- @param 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
/**\r
Timeout the fragment and enqueued packets.\r
\r
- @param IpSb The IP4 service instance to timeout\r
-\r
- @return None\r
+ @param[in] IpSb The IP4 service instance to timeout\r
\r
**/\r
VOID\r