]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c
Fixed GCC 4.4 build issues due to EFIAPI not being used when required.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Input.c
index 725735330129ae820cea598dc5077dde3f07f4da..24d2f29d383de45239df4c5028632fd9a23a1560 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   IP4 input process.\r
   \r
-Copyright (c) 2005 - 2009, Intel Corporation.<BR>\r
+Copyright (c) 2005 - 2010, Intel Corporation.<BR>\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
@@ -85,7 +85,7 @@ Ip4FreeAssembleEntry (
     NetbufFree (Fragment);\r
   }\r
 \r
-  gBS->FreePool (Assemble);\r
+  FreePool (Assemble);\r
 }\r
 \r
 \r
@@ -188,6 +188,7 @@ Ip4TrimPacket (
 \r
 **/\r
 VOID\r
+EFIAPI\r
 Ip4OnFreeFragments (\r
   IN VOID                   *Arg\r
   )\r
@@ -429,6 +430,220 @@ DROP:
   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 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]       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]       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
+**/\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
+  )\r
+{\r
+  NET_FRAGMENT              *FragmentTable;\r
+  UINT32                    FragmentCount;\r
+  EFI_EVENT                 RecycleEvent;\r
+  NET_BUF                   *Packet;\r
+  IP4_TXTOKEN_WRAP          *TxWrap;\r
+  IP4_IPSEC_WRAP            *IpSecWrap;\r
+  EFI_STATUS                Status;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  Packet        = *Netbuf;\r
+  RecycleEvent  = NULL;\r
+  IpSecWrap     = NULL;\r
+  FragmentTable = NULL;\r
+  TxWrap        = (IP4_TXTOKEN_WRAP *) Context; \r
+  FragmentCount = Packet->BlockOpNum;\r
+  \r
+  if (mIpSec == NULL) {\r
+    gBS->LocateProtocol (&gEfiIpSecProtocolGuid, NULL, (VOID **) &mIpSec);\r
+    if (mIpSec != NULL) {\r
+      //\r
+      // Save the original MTU\r
+      //\r
+      IpSb->OldMaxPacketSize = IpSb->MaxPacketSize; \r
+    }\r
+  }\r
+\r
+  //\r
+  // Check whether the IPsec protocol is available.\r
+  //\r
+  if (mIpSec == NULL) {\r
+    goto ON_EXIT;\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
+  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->Process (\r
+                     mIpSec,\r
+                     IpSb->Controller,\r
+                     IP_VERSION_4,\r
+                     (VOID *) Head,\r
+                     &Head->Protocol,\r
+                     NULL,\r
+                     0,\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
+    goto ON_EXIT;\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
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    *Netbuf = TxWrap->Packet;\r
+    \r
+  } else {\r
+  \r
+    IpSecWrap = AllocateZeroPool (sizeof (IP4_IPSEC_WRAP));\r
+  \r
+    if (IpSecWrap == NULL) {\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
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    if (Direction == EfiIPsecInBound) {\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
+\r
+    *Netbuf = Packet;\r
+  }\r
+\r
+ON_EXIT:\r
+  return Status;\r
+}\r
 \r
 /**\r
   The IP4 input routine. It is called by the IP4_INTERFACE when a\r
@@ -459,6 +674,7 @@ Ip4AccpetFrame (
   UINT32                    OptionLen;\r
   UINT32                    TotalLen;\r
   UINT16                    Checksum;\r
+  EFI_STATUS                Status;\r
 \r
   IpSb = (IP4_SERVICE *) Context;\r
 \r
@@ -566,6 +782,22 @@ Ip4AccpetFrame (
   }\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
+             NULL,\r
+             0, \r
+             EfiIPsecInBound,\r
+             NULL\r
+             );\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    goto RESTART;\r
+  }\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
@@ -651,11 +883,11 @@ Ip4InstanceFrameAcceptable (
   //\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 == EFI_IP_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
@@ -794,7 +1026,7 @@ Ip4OnRecyclePacket (
   NetbufFree (Wrap->Packet);\r
 \r
   gBS->CloseEvent (Wrap->RxData.RecycleSignal);\r
-  gBS->FreePool (Wrap);\r
+  FreePool (Wrap);\r
 }\r
 \r
 \r
@@ -846,7 +1078,7 @@ Ip4WrapRxData (
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    gBS->FreePool (Wrap);\r
+    FreePool (Wrap);\r
     return NULL;\r
   }\r
 \r