]> 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 669e041c102929adaa9a8dea3417121462756b14..44b8d9fc8faf64aeb736eb23e6adc366a908f3ce 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   Implement IP4 pesudo interface.\r
-  \r
-Copyright (c) 2005 - 2015, 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
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -68,7 +62,7 @@ Ip4OnArpResolvedDpc (
   @param  Event             The Arp request event.\r
   @param  Context           The context of the callback, a point to the ARP\r
                             queue.\r
-                                \r
+\r
 **/\r
 VOID\r
 EFIAPI\r
@@ -138,8 +132,9 @@ 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   Token               The wrapped token if succeed\r
   @retval   NULL                The wrapped token if NULL\r
 \r
 **/\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
@@ -560,9 +557,6 @@ Ip4SetAddress (
 {\r
   EFI_ARP_CONFIG_DATA       ArpConfig;\r
   EFI_STATUS                Status;\r
-  INTN                      Type;\r
-  INTN                      Len;\r
-  IP4_ADDR                  Netmask;\r
 \r
   NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);\r
 \r
@@ -577,13 +571,7 @@ Ip4SetAddress (
   Interface->Ip             = IpAddr;\r
   Interface->SubnetMask     = SubnetMask;\r
   Interface->SubnetBrdcast  = (IpAddr | ~SubnetMask);\r
-\r
-  Type                      = NetGetIpClass (IpAddr);\r
-  ASSERT (Type <= IP4_ADDR_CLASSC);\r
-  Len                       = NetGetMaskLength (SubnetMask);\r
-  ASSERT (Len < IP4_MASK_NUM);\r
-  Netmask                   = gIp4AllMasks[MIN (Len, Type << 3)];\r
-  Interface->NetBrdcast     = (IpAddr | ~Netmask);\r
+  Interface->NetBrdcast     = (IpAddr | ~SubnetMask);\r
 \r
   //\r
   // Do clean up for Arp child\r
@@ -596,10 +584,10 @@ Ip4SetAddress (
              Interface->Image,\r
              Interface->Controller\r
              );\r
-      \r
+\r
       Interface->Arp = NULL;\r
     }\r
-    \r
+\r
     NetLibDestroyServiceChild (\r
       Interface->Controller,\r
       Interface->Image,\r
@@ -801,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
@@ -823,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
@@ -830,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
@@ -845,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
@@ -864,7 +943,7 @@ Ip4OnArpResolvedDpc (
 \r
     Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);\r
     if (EFI_ERROR (Status)) {\r
-      RemoveEntryList (Entry);\r
+      RemoveEntryList (&Token->Link);\r
       Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);\r
 \r
       Ip4FreeLinkTxToken (Token);\r
@@ -872,7 +951,8 @@ Ip4OnArpResolvedDpc (
     }\r
   }\r
 \r
-  Ip4FreeArpQue (ArpQue, EFI_SUCCESS);\r
+ON_EXIT:\r
+  Ip4FreeArpQue (ArpQue, IoStatus);\r
 }\r
 \r
 /**\r
@@ -881,7 +961,7 @@ Ip4OnArpResolvedDpc (
   @param  Event             The Arp request event.\r
   @param  Context           The context of the callback, a point to the ARP\r
                             queue.\r
-                                \r
+\r
 **/\r
 VOID\r
 EFIAPI\r
@@ -966,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
@@ -980,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
@@ -991,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
@@ -1090,7 +1172,7 @@ SEND_NOW:
   InsertTailList (&Interface->SentFrames, &Token->Link);\r
   Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);\r
   if (EFI_ERROR (Status)) {\r
-    RemoveEntryList (&Interface->SentFrames);\r
+    RemoveEntryList (&Token->Link);\r
     goto ON_ERROR;\r
   }\r
 \r