]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4If.c
index 6e0e3290c75f6367c207cbd7a5ba932d84781df1..44b8d9fc8faf64aeb736eb23e6adc366a908f3ce 100644 (file)
@@ -2,13 +2,7 @@
   Implement IP4 pesudo interface.\r
 \r
 Copyright (c) 2005 - 2018, 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
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -138,6 +132,7 @@ Ip4CancelFrameArp (
   @param[in]  CallBack          Call back function to execute if transmission\r
                                 finished.\r
   @param[in]  Context           Opaque parameter to the call back.\r
+  @param[in]  IpSb              The pointer to the IP4 service binding instance.\r
 \r
   @retval   Token               The wrapped token if succeed\r
   @retval   NULL                The wrapped token if NULL\r
@@ -149,7 +144,8 @@ Ip4WrapLinkTxToken (
   IN IP4_PROTOCOL           *IpInstance     OPTIONAL,\r
   IN NET_BUF                *Packet,\r
   IN IP4_FRAME_CALLBACK     CallBack,\r
-  IN VOID                   *Context\r
+  IN VOID                   *Context,\r
+  IN IP4_SERVICE            *IpSb\r
   )\r
 {\r
   EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *MnpToken;\r
@@ -170,6 +166,7 @@ Ip4WrapLinkTxToken (
 \r
   Token->Interface  = Interface;\r
   Token->IpInstance = IpInstance;\r
+  Token->IpSb       = IpSb;\r
   Token->CallBack   = CallBack;\r
   Token->Packet     = Packet;\r
   Token->Context    = Context;\r
@@ -792,9 +789,89 @@ Ip4FreeInterface (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  This function tries to send all the queued frames in ArpQue to the default gateway if\r
+  the ARP resolve for direct destination address is failed when using /32 subnet mask.\r
+\r
+  @param[in]   ArpQue           The ARP queue of a failed request.\r
+\r
+  @retval EFI_SUCCESS           All the queued frames have been send to the default route.\r
+  @retval Others                Failed to send the queued frames.\r
+\r
+**/\r
+EFI_STATUS\r
+Ip4SendFrameToDefaultRoute (\r
+  IN  IP4_ARP_QUE               *ArpQue\r
+  )\r
+{\r
+  LIST_ENTRY                *Entry;\r
+  LIST_ENTRY                *Next;\r
+  IP4_ROUTE_CACHE_ENTRY     *RtCacheEntry;\r
+  IP4_LINK_TX_TOKEN         *Token;\r
+  IP4_ADDR                  Gateway;\r
+  EFI_STATUS                Status;\r
+  IP4_ROUTE_ENTRY           *DefaultRoute;\r
+\r
+  //\r
+  // ARP resolve failed when using /32 subnet mask.\r
+  //\r
+  NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {\r
+    RemoveEntryList (Entry);\r
+    Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);\r
+    ASSERT (Token->Interface->SubnetMask == IP4_ALLONE_ADDRESS);\r
+    //\r
+    // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().\r
+    //\r
+    RtCacheEntry = NULL;\r
+    if (Token->IpInstance != NULL) {\r
+      RtCacheEntry = Ip4FindRouteCache (Token->IpInstance->RouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);\r
+    }\r
+    if (RtCacheEntry == NULL) {\r
+      RtCacheEntry = Ip4FindRouteCache (Token->IpSb->DefaultRouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);\r
+    }\r
+    if (RtCacheEntry == NULL) {\r
+      Status= EFI_NO_MAPPING;\r
+      goto ON_ERROR;\r
+    }\r
+    DefaultRoute = (IP4_ROUTE_ENTRY*)RtCacheEntry->Tag;\r
+    if (DefaultRoute == NULL) {\r
+      Status= EFI_NO_MAPPING;\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Try to send the frame to the default route.\r
+    //\r
+    Gateway = DefaultRoute->NextHop;\r
+    if (ArpQue->Ip == Gateway) {\r
+      //\r
+      // ARP resolve for the default route is failed, return error to caller.\r
+      //\r
+      Status= EFI_NO_MAPPING;\r
+      goto ON_ERROR;\r
+    }\r
+    RtCacheEntry->NextHop = Gateway;\r
+    Status = Ip4SendFrame (Token->Interface,Token->IpInstance,Token->Packet,Gateway,Token->CallBack,Token->Context,Token->IpSb);\r
+    if (EFI_ERROR (Status)) {\r
+      Status= EFI_NO_MAPPING;\r
+      goto ON_ERROR;\r
+    }\r
+    Ip4FreeRouteCacheEntry (RtCacheEntry);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+  if (RtCacheEntry != NULL) {\r
+    Ip4FreeRouteCacheEntry (RtCacheEntry);\r
+  }\r
+  Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);\r
+  Ip4FreeLinkTxToken (Token);\r
+  return Status;\r
+}\r
+\r
 \r
 /**\r
-  Callback function when ARP request are finished. It will cancelled\r
+  Callback function when ARP request are finished. It will cancel\r
   all the queued frame if the ARP requests failed. Or transmit them\r
   if the request succeed.\r
 \r
@@ -814,6 +891,7 @@ Ip4OnArpResolvedDpc (
   IP4_INTERFACE             *Interface;\r
   IP4_LINK_TX_TOKEN         *Token;\r
   EFI_STATUS                Status;\r
+  EFI_STATUS                IoStatus;\r
 \r
   ArpQue = (IP4_ARP_QUE *) Context;\r
   NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);\r
@@ -821,14 +899,23 @@ Ip4OnArpResolvedDpc (
   RemoveEntryList (&ArpQue->Link);\r
 \r
   //\r
-  // ARP resolve failed for some reason. Release all the frame\r
-  // and ARP queue itself. Ip4FreeArpQue will call the frame's\r
-  // owner back.\r
+  // ARP resolve failed for some reason.\r
   //\r
   if (NET_MAC_EQUAL (&ArpQue->Mac, &mZeroMacAddress, ArpQue->Interface->HwaddrLen)) {\r
-    Ip4FreeArpQue (ArpQue, EFI_NO_MAPPING);\r
-\r
-    return ;\r
+    if (ArpQue->Interface->SubnetMask != IP4_ALLONE_ADDRESS) {\r
+      //\r
+      // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's\r
+      // owner back.\r
+      //\r
+      IoStatus = EFI_NO_MAPPING;\r
+    } else {\r
+      //\r
+      // ARP resolve failed when using 32bit subnet mask, try to send the packets to the\r
+      // default route.\r
+      //\r
+      IoStatus = Ip4SendFrameToDefaultRoute (ArpQue);\r
+    }\r
+    goto ON_EXIT;\r
   }\r
 \r
   //\r
@@ -836,6 +923,7 @@ Ip4OnArpResolvedDpc (
   // queue. It isn't necessary for us to cache the ARP binding because\r
   // we always check the ARP cache first before transmit.\r
   //\r
+  IoStatus = EFI_SUCCESS;\r
   Interface = ArpQue->Interface;\r
 \r
   NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {\r
@@ -863,7 +951,8 @@ Ip4OnArpResolvedDpc (
     }\r
   }\r
 \r
-  Ip4FreeArpQue (ArpQue, EFI_SUCCESS);\r
+ON_EXIT:\r
+  Ip4FreeArpQue (ArpQue, IoStatus);\r
 }\r
 \r
 /**\r
@@ -957,6 +1046,7 @@ Ip4OnFrameSent (
                                 to.\r
   @param[in]  CallBack          Function to call back when transmit finished.\r
   @param[in]  Context           Opaque parameter to the call back.\r
+  @param[in]  IpSb              The pointer to the IP4 service binding instance.\r
 \r
   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource to send the frame\r
   @retval EFI_NO_MAPPING        Can't resolve the MAC for the nexthop\r
@@ -971,7 +1061,8 @@ Ip4SendFrame (
   IN  NET_BUF               *Packet,\r
   IN  IP4_ADDR              NextHop,\r
   IN  IP4_FRAME_CALLBACK    CallBack,\r
-  IN  VOID                  *Context\r
+  IN  VOID                  *Context,\r
+  IN IP4_SERVICE            *IpSb\r
   )\r
 {\r
   IP4_LINK_TX_TOKEN         *Token;\r
@@ -982,7 +1073,7 @@ Ip4SendFrame (
 \r
   ASSERT (Interface->Configured);\r
 \r
-  Token = Ip4WrapLinkTxToken (Interface, IpInstance, Packet, CallBack, Context);\r
+  Token = Ip4WrapLinkTxToken (Interface, IpInstance, Packet, CallBack, Context, IpSb);\r
 \r
   if (Token == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r