]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c
Update IPsec.h file to follow approved ECR which will be collected into future UEFI...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Input.c
index 75333b82efa6c521e5e8d93bb4cac4eba70ac525..0734e091bf7c8ec32af23e9d6891862d60552195 100644 (file)
@@ -463,14 +463,14 @@ Ip4IpSecFree (
   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]       Head          The The caller supplied IP4 header.\r
-  @param[in, out]  Netbuf        The IP4 packet to be processed by IPsec\r
-  @param[in]       Options       The caller supplied options\r
-  @param[in]       OptionsLen    The length of the option\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
+                                 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
@@ -483,22 +483,25 @@ Ip4IpSecFree (
 **/\r
 EFI_STATUS\r
 Ip4IpSecProcessPacket (\r
-  IN IP4_SERVICE            *IpSb,\r
-  IN IP4_HEAD               *Head,\r
-  IN OUT NET_BUF            **Netbuf,\r
-  IN UINT8                  *Options,\r
-  IN UINT32                 OptionsLen,\r
-  IN EFI_IPSEC_TRAFFIC_DIR  Direction,\r
-  IN VOID                   *Context\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
   Packet        = *Netbuf;\r
@@ -507,6 +510,8 @@ Ip4IpSecProcessPacket (
   FragmentTable = NULL;\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
@@ -542,6 +547,12 @@ Ip4IpSecProcessPacket (
   }\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
@@ -551,16 +562,16 @@ Ip4IpSecProcessPacket (
   //\r
   // Convert host byte order to network byte order\r
   //\r
-  Ip4NtohHead (Head);\r
+  Ip4NtohHead (*Head);\r
   \r
-  Status = mIpSec->Process (\r
+  Status = mIpSec->ProcessExt (\r
                      mIpSec,\r
                      IpSb->Controller,\r
                      IP_VERSION_4,\r
-                     (VOID *) Head,\r
-                     &Head->Protocol,\r
-                     NULL,\r
-                     0,\r
+                     (VOID *) (*Head),\r
+                     &(*Head)->Protocol,\r
+                     Options,\r
+                     OptionsLen,\r
                      (EFI_IPSEC_FRAGMENT_DATA **) (&FragmentTable),\r
                      &FragmentCount,\r
                      Direction,\r
@@ -569,12 +580,16 @@ Ip4IpSecProcessPacket (
   //\r
   // Convert back to host byte order\r
   //\r
-  Ip4NtohHead (Head);\r
+  Ip4NtohHead (*Head);\r
   \r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
   }\r
 \r
+  if (OriginalFragmentTable == FragmentTable && OriginalFragmentCount == FragmentCount) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
   if (Direction == EfiIPsecOutBound && TxWrap != NULL) {\r
   \r
     TxWrap->IpSecRecycleSignal = RecycleEvent;\r
@@ -591,6 +606,10 @@ Ip4IpSecProcessPacket (
       goto ON_EXIT;\r
     }\r
 \r
+    //\r
+    // Free orginal Netbuf.\r
+    //\r
+    NetIpSecNetbufFree (*Netbuf);\r
     *Netbuf = TxWrap->Packet;\r
     \r
   } else {\r
@@ -617,10 +636,10 @@ Ip4IpSecProcessPacket (
       goto ON_EXIT;\r
     }\r
 \r
-    if (Direction == EfiIPsecInBound) {\r
-      Ip4PrependHead (Packet, Head, Options, OptionsLen);\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
+      NetbufTrim (Packet, ((*Head)->HeadLen << 2), TRUE);\r
 \r
       CopyMem (\r
         IP4_GET_CLIP_INFO (Packet),\r
@@ -628,7 +647,6 @@ Ip4IpSecProcessPacket (
         sizeof (IP4_CLIP_INFO)\r
         );\r
     }\r
-\r
     *Netbuf = Packet;\r
   }\r
 \r
@@ -637,63 +655,56 @@ ON_EXIT:
 }\r
 \r
 /**\r
-  The IP4 input routine. It is called by the IP4_INTERFACE when a\r
-  IP4 fragment is received from MNP.\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
-  @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
+  @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
-  )\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
-  EFI_STATUS                Status;\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
   //\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
+  \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
@@ -702,15 +713,15 @@ Ip4AccpetFrame (
   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.Ip4  = 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
@@ -722,24 +733,23 @@ Ip4AccpetFrame (
   // 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
+  \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
   // 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
@@ -752,25 +762,86 @@ Ip4AccpetFrame (
     // need to send a type 4 destination unreache ICMP message here.\r
     //\r
     if ((Head->Fragment & IP4_HEAD_DF_MASK) != 0) {\r
-      goto RESTART;\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) != 0) && (Info->Length % 8 != 0)) {\r
-      goto RESTART;\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_DESTORY)) {\r
+    goto DROP;\r
+  }\r
+\r
+  Head      = (IP4_HEAD *) NetbufGetByte (Packet, 0, 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
@@ -778,21 +849,40 @@ Ip4AccpetFrame (
   //\r
   Status = Ip4IpSecProcessPacket (\r
              IpSb, \r
-             Head, \r
+             &Head, \r
              &Packet, \r
-             NULL,\r
-             0\r
+             &Option,\r
+             &OptionLen\r
              EfiIPsecInBound,\r
              NULL\r
              );\r
 \r
-  if (EFI_ERROR(Status)) {\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 = (IP4_HEAD *) NetbufGetByte (Packet, 0, 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
   Head  = Packet->Ip.Ip4;\r
   IP4_GET_CLIP_INFO (Packet)->Status = EFI_SUCCESS;\r
 \r