]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c
MdeModulePkg/Ip4Dxe: Ignore duplicated DNS address check
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Config2Impl.c
index caf84fb7a5fdb097ee5b457dacc32db621970140..6c7ac68791c3c3e638731c1d723d6f047496d679 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
   The implementation of EFI IPv4 Configuration II Protocol.\r
 \r
 /** @file\r
   The implementation of EFI IPv4 Configuration II Protocol.\r
 \r
-  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -141,7 +142,7 @@ Ip4Config2OnPolicyChanged (
   IpSb->DefaultRouteTable = RouteTable;\r
   Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
 \r
   IpSb->DefaultRouteTable = RouteTable;\r
   Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
 \r
-  if (IpSb->State == IP4_SERVICE_CONFIGED) {\r
+  if (IpSb->State == IP4_SERVICE_CONFIGED || IpSb->State == IP4_SERVICE_STARTED) {\r
     IpSb->State = IP4_SERVICE_UNSTARTED;\r
   }\r
 \r
     IpSb->State = IP4_SERVICE_UNSTARTED;\r
   }\r
 \r
@@ -414,7 +415,7 @@ Ip4Config2BuildDefaultRouteTable (
   //\r
   Count = 0;\r
 \r
   //\r
   Count = 0;\r
 \r
-  for (Index = IP4_MASK_NUM - 1; Index >= 0; Index--) {\r
+  for (Index = IP4_MASK_MAX; Index >= 0; Index--) {\r
 \r
     NET_LIST_FOR_EACH (Entry, &(IpSb->DefaultRouteTable->RouteArea[Index])) {\r
       RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);\r
 \r
     NET_LIST_FOR_EACH (Entry, &(IpSb->DefaultRouteTable->RouteArea[Index])) {\r
       RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);\r
@@ -463,7 +464,7 @@ Ip4Config2OnDhcp4SbInstalled (
 /**\r
   Set the station address and subnetmask for the default interface.\r
 \r
 /**\r
   Set the station address and subnetmask for the default interface.\r
 \r
-  @param[in]  Instance           The pointer to the IP4 config2 instance data.\r
+  @param[in]  IpSb               The pointer to the IP4 service binding instance.\r
   @param[in]  StationAddress     Ip address to be set.\r
   @param[in]  SubnetMask         Subnet to be set.\r
 \r
   @param[in]  StationAddress     Ip address to be set.\r
   @param[in]  SubnetMask         Subnet to be set.\r
 \r
@@ -473,13 +474,12 @@ Ip4Config2OnDhcp4SbInstalled (
 **/\r
 EFI_STATUS\r
 Ip4Config2SetDefaultAddr (\r
 **/\r
 EFI_STATUS\r
 Ip4Config2SetDefaultAddr (\r
-  IN IP4_CONFIG2_INSTANCE   *Instance,\r
+  IN IP4_SERVICE            *IpSb,\r
   IN IP4_ADDR               StationAddress,\r
   IN IP4_ADDR               SubnetMask\r
   )\r
 {\r
   EFI_STATUS                Status;\r
   IN IP4_ADDR               StationAddress,\r
   IN IP4_ADDR               SubnetMask\r
   )\r
 {\r
   EFI_STATUS                Status;\r
-  IP4_SERVICE               *IpSb;\r
   IP4_INTERFACE             *IpIf;\r
   IP4_PROTOCOL              *Ip4Instance;\r
   EFI_ARP_PROTOCOL          *Arp;\r
   IP4_INTERFACE             *IpIf;\r
   IP4_PROTOCOL              *Ip4Instance;\r
   EFI_ARP_PROTOCOL          *Arp;\r
@@ -487,7 +487,6 @@ Ip4Config2SetDefaultAddr (
   IP4_ADDR                  Subnet;\r
   IP4_ROUTE_TABLE           *RouteTable;\r
 \r
   IP4_ADDR                  Subnet;\r
   IP4_ROUTE_TABLE           *RouteTable;\r
 \r
-  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
   IpIf = IpSb->DefaultInterface;\r
   ASSERT (IpIf != NULL);\r
 \r
   IpIf = IpSb->DefaultInterface;\r
   ASSERT (IpIf != NULL);\r
 \r
@@ -496,35 +495,37 @@ Ip4Config2SetDefaultAddr (
     return EFI_SUCCESS;\r
   }\r
 \r
     return EFI_SUCCESS;\r
   }\r
 \r
-  //\r
-  // The default address is changed, free the previous interface first.\r
-  //\r
-  if (IpSb->DefaultRouteTable != NULL) {\r
-    Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
-    IpSb->DefaultRouteTable = NULL;    \r
-  }\r
+  if (IpSb->Reconfig) {\r
+    //\r
+    // The default address is changed, free the previous interface first.\r
+    //\r
+    if (IpSb->DefaultRouteTable != NULL) {\r
+      Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
+      IpSb->DefaultRouteTable = NULL;    \r
+    }\r
 \r
 \r
-  Ip4CancelReceive (IpSb->DefaultInterface);\r
-  Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
-  IpSb->DefaultInterface = NULL;\r
-  //\r
-  // Create new default interface and route table.\r
-  //    \r
-  IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
-  if (IpIf == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
+    Ip4CancelReceive (IpSb->DefaultInterface);\r
+    Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
+    IpSb->DefaultInterface = NULL;\r
+    //\r
+    // Create new default interface and route table.\r
+    //    \r
+    IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
+    if (IpIf == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
 \r
 \r
-  RouteTable = Ip4CreateRouteTable ();\r
-  if (RouteTable == NULL) {\r
-    Ip4FreeInterface (IpIf, NULL);\r
-    return EFI_OUT_OF_RESOURCES;\r
+    RouteTable = Ip4CreateRouteTable ();\r
+    if (RouteTable == NULL) {\r
+      Ip4FreeInterface (IpIf, NULL);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    \r
+    IpSb->DefaultInterface  = IpIf;\r
+    InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
+    IpSb->DefaultRouteTable = RouteTable;\r
+    Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
   }\r
   }\r
-  \r
-  IpSb->DefaultInterface  = IpIf;\r
-  InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
-  IpSb->DefaultRouteTable = RouteTable;\r
-  Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
 \r
   if (IpSb->State == IP4_SERVICE_CONFIGED) {\r
     IpSb->State = IP4_SERVICE_UNSTARTED;\r
 \r
   if (IpSb->State == IP4_SERVICE_CONFIGED) {\r
     IpSb->State = IP4_SERVICE_UNSTARTED;\r
@@ -578,6 +579,8 @@ Ip4Config2SetDefaultAddr (
     );\r
 \r
   IpSb->State = IP4_SERVICE_CONFIGED;\r
     );\r
 \r
   IpSb->State = IP4_SERVICE_CONFIGED;\r
+  IpSb->Reconfig = FALSE;\r
+  \r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -604,7 +607,9 @@ Ip4Config2SetDefaultIf (
   EFI_STATUS                Status;\r
   IP4_SERVICE               *IpSb;\r
 \r
   EFI_STATUS                Status;\r
   IP4_SERVICE               *IpSb;\r
 \r
-  Status = Ip4Config2SetDefaultAddr (Instance, StationAddress, SubnetMask);\r
+  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
+\r
+  Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -612,7 +617,6 @@ Ip4Config2SetDefaultIf (
   //\r
   // Create a route if there is a default router.\r
   //\r
   //\r
   // Create a route if there is a default router.\r
   //\r
-  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
   if (GatewayAddress != IP4_ALLZERO_ADDRESS) {\r
     Ip4AddRoute (\r
       IpSb->DefaultRouteTable,\r
   if (GatewayAddress != IP4_ALLZERO_ADDRESS) {\r
     Ip4AddRoute (\r
       IpSb->DefaultRouteTable,\r
@@ -673,6 +677,119 @@ Ip4Config2CleanDhcp4 (
   }\r
 }\r
 \r
   }\r
 }\r
 \r
+/**\r
+  This worker function sets the DNS server list for the EFI IPv4 network\r
+  stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL\r
+  manages. The DNS server addresses must be unicast IPv4 addresses. \r
+\r
+  @param[in]     Instance        The pointer to the IP4 config2 instance data.\r
+  @param[in]     DataSize        The size of the buffer pointed to by Data in bytes.\r
+  @param[in]     Data            The data buffer to set, points to an array of\r
+                                 EFI_IPv4_ADDRESS instances.\r
+\r
+  @retval EFI_BAD_BUFFER_SIZE    The DataSize does not match the size of the type.\r
+  @retval EFI_INVALID_PARAMETER  One or more fields in Data is invalid.\r
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources to complete the operation.\r
+  @retval EFI_ABORTED            The DNS server addresses to be set equal the current\r
+                                 configuration.\r
+  @retval EFI_SUCCESS            The specified configuration data for the EFI IPv4\r
+                                 network stack was set.\r
+\r
+**/\r
+EFI_STATUS\r
+Ip4Config2SetDnsServerWorker (\r
+  IN IP4_CONFIG2_INSTANCE    *Instance,\r
+  IN UINTN                   DataSize,\r
+  IN VOID                    *Data\r
+  )\r
+{\r
+  UINTN                 OldIndex;\r
+  UINTN                 NewIndex;\r
+  EFI_IPv4_ADDRESS      *OldDns;\r
+  EFI_IPv4_ADDRESS      *NewDns;\r
+  UINTN                 OldDnsCount;\r
+  UINTN                 NewDnsCount;\r
+  IP4_CONFIG2_DATA_ITEM *Item;\r
+  BOOLEAN               OneAdded;\r
+  VOID                  *Tmp;\r
+  IP4_ADDR              DnsAddress;\r
+\r
+  if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  Item        = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
+  NewDns      = (EFI_IPv4_ADDRESS *) Data;\r
+  OldDns      = Item->Data.DnsServers;\r
+  NewDnsCount = DataSize / sizeof (EFI_IPv4_ADDRESS);  \r
+  OldDnsCount = Item->DataSize / sizeof (EFI_IPv4_ADDRESS);\r
+  OneAdded    = FALSE;\r
+\r
+  if (NewDnsCount != OldDnsCount) {\r
+    Tmp = AllocatePool (DataSize);\r
+    if (Tmp == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  } else {\r
+    Tmp = NULL;\r
+  }\r
+\r
+  for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {\r
+    CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR));\r
+    if (IP4_IS_UNSPECIFIED (NTOHL (DnsAddress)) || IP4_IS_LOCAL_BROADCAST (NTOHL (DnsAddress))) {\r
+      //\r
+      // The dns server address must be unicast.\r
+      //\r
+      if (Tmp != NULL) {\r
+        FreePool (Tmp);\r
+      }\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if (OneAdded) {\r
+      //\r
+      // If any address in the new setting is not in the old settings, skip the\r
+      // comparision below.\r
+      //\r
+      continue;\r
+    }\r
+\r
+    for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {\r
+      if (EFI_IP4_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {\r
+        //\r
+        // If found break out.\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (OldIndex == OldDnsCount) {\r
+      OneAdded = TRUE;\r
+    }\r
+  }\r
+\r
+  if (!OneAdded && (DataSize == Item->DataSize)) {\r
+    //\r
+    // No new item is added and the size is the same.\r
+    //\r
+    Item->Status = EFI_SUCCESS;\r
+    return EFI_ABORTED;\r
+  } else {\r
+    if (Tmp != NULL) {\r
+      if (Item->Data.Ptr != NULL) {\r
+        FreePool (Item->Data.Ptr);\r
+      }      \r
+      Item->Data.Ptr = Tmp;\r
+    }\r
+\r
+    CopyMem (Item->Data.Ptr, Data, DataSize);\r
+    Item->DataSize = DataSize;\r
+    Item->Status   = EFI_SUCCESS;\r
+    return EFI_SUCCESS;\r
+  }\r
+}\r
+\r
+\r
 \r
 /**\r
   Callback function when DHCP process finished. It will save the\r
 \r
 /**\r
   Callback function when DHCP process finished. It will save the\r
@@ -697,6 +814,9 @@ Ip4Config2OnDhcp4Complete (
   IP4_ADDR                  StationAddress;\r
   IP4_ADDR                  SubnetMask;\r
   IP4_ADDR                  GatewayAddress;\r
   IP4_ADDR                  StationAddress;\r
   IP4_ADDR                  SubnetMask;\r
   IP4_ADDR                  GatewayAddress;\r
+  UINT32                    Index;\r
+  UINT32                    OptionCount;\r
+  EFI_DHCP4_PACKET_OPTION   **OptionList;\r
 \r
   Instance = (IP4_CONFIG2_INSTANCE *) Context;\r
   ASSERT (Instance->Dhcp4 != NULL);\r
 \r
   Instance = (IP4_CONFIG2_INSTANCE *) Context;\r
   ASSERT (Instance->Dhcp4 != NULL);\r
@@ -720,6 +840,44 @@ Ip4Config2OnDhcp4Complete (
       goto Exit;\r
     }\r
   \r
       goto Exit;\r
     }\r
   \r
+    //\r
+    // Parse the ACK to get required DNS server information.\r
+    //\r
+    OptionCount = 0;\r
+    OptionList  = NULL;\r
+\r
+    Status      = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList);\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      goto Exit;\r
+    }\r
+\r
+    OptionList = AllocateZeroPool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
+    if (OptionList == NULL) {\r
+      goto Exit;\r
+    }\r
+\r
+    Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList);\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (OptionList);\r
+      goto Exit;\r
+    }\r
+\r
+    for (Index = 0; Index < OptionCount; Index++) {\r
+      //\r
+      // Look for DNS Server opcode (6).\r
+      //\r
+      if (OptionList[Index]->OpCode == DHCP4_TAG_DNS_SERVER) {\r
+        if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) {\r
+          break;\r
+        }\r
+\r
+        Ip4Config2SetDnsServerWorker (Instance, OptionList[Index]->Length, &OptionList[Index]->Data[0]);\r
+        break;\r
+      }\r
+    }\r
+\r
+    FreePool (OptionList);\r
+\r
     Instance->DhcpSuccess = TRUE;\r
   }\r
 \r
     Instance->DhcpSuccess = TRUE;\r
   }\r
 \r
@@ -736,7 +894,7 @@ Exit:
 \r
   @param[in]  Instance           The IP4 config2 instance to configure\r
 \r
 \r
   @param[in]  Instance           The IP4 config2 instance to configure\r
 \r
-  @retval EFI_SUCCESS            The auto configuration is successfull started\r
+  @retval EFI_SUCCESS            The auto configuration is successfully started\r
   @retval Others                 Failed to start auto configuration.\r
 \r
 **/\r
   @retval Others                 Failed to start auto configuration.\r
 \r
 **/\r
@@ -826,10 +984,11 @@ Ip4StartAutoConfig (
   // DHCP configuration to avoid problems if some DHCP client\r
   // yields the control of this DHCP service to us.\r
   //\r
   // DHCP configuration to avoid problems if some DHCP client\r
   // yields the control of this DHCP service to us.\r
   //\r
-  ParaList.Head.OpCode             = DHCP_TAG_PARA_LIST;\r
-  ParaList.Head.Length             = 2;\r
-  ParaList.Head.Data[0]            = DHCP_TAG_NETMASK;\r
-  ParaList.Route                   = DHCP_TAG_ROUTER;\r
+  ParaList.Head.OpCode             = DHCP4_TAG_PARA_LIST;\r
+  ParaList.Head.Length             = 3;\r
+  ParaList.Head.Data[0]            = DHCP4_TAG_NETMASK;\r
+  ParaList.Route                   = DHCP4_TAG_ROUTER;\r
+  ParaList.Dns                     = DHCP4_TAG_DNS_SERVER;\r
   OptionList[0]                    = &ParaList.Head;\r
   Dhcp4Mode.ConfigData.OptionCount = 1;\r
   Dhcp4Mode.ConfigData.OptionList  = OptionList;\r
   OptionList[0]                    = &ParaList.Head;\r
   Dhcp4Mode.ConfigData.OptionCount = 1;\r
   Dhcp4Mode.ConfigData.OptionList  = OptionList;\r
@@ -893,7 +1052,6 @@ Ip4Config2GetIfInfo (
   IN VOID                 *Data      OPTIONAL\r
   )\r
 {\r
   IN VOID                 *Data      OPTIONAL\r
   )\r
 {\r
-\r
   IP4_SERVICE                    *IpSb;\r
   UINTN                          Length;\r
   IP4_CONFIG2_DATA_ITEM          *Item;\r
   IP4_SERVICE                    *IpSb;\r
   UINTN                          Length;\r
   IP4_CONFIG2_DATA_ITEM          *Item;\r
@@ -977,40 +1135,43 @@ Ip4Config2SetPolicy (
   }\r
 \r
   if (NewPolicy == Instance->Policy) {\r
   }\r
 \r
   if (NewPolicy == Instance->Policy) {\r
-     return EFI_ABORTED;\r
+    if (NewPolicy != Ip4Config2PolicyDhcp || Instance->DhcpSuccess) {\r
+      return EFI_ABORTED;\r
+    }\r
   } else {\r
   } else {\r
-    if (NewPolicy == Ip4Config2PolicyDhcp) {\r
-      //\r
-      // The policy is changed from static to dhcp:\r
-      // Clean the ManualAddress, Gateway and DnsServers, shrink the variable\r
-      // data size, and fire up all the related events.\r
-      //\r
-      DataItem           = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
-      if (DataItem->Data.Ptr != NULL) {\r
-        FreePool (DataItem->Data.Ptr);\r
-      }\r
-      DataItem->Data.Ptr = NULL;\r
-      DataItem->DataSize = 0;\r
-      DataItem->Status   = EFI_NOT_FOUND;\r
-      NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
+    //\r
+    // The policy is changed. Clean the ManualAddress, Gateway and DnsServers, \r
+    // shrink the variable data size, and fire up all the related events.\r
+    //\r
+    DataItem           = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
+    if (DataItem->Data.Ptr != NULL) {\r
+      FreePool (DataItem->Data.Ptr);\r
+    }\r
+    DataItem->Data.Ptr = NULL;\r
+    DataItem->DataSize = 0;\r
+    DataItem->Status   = EFI_NOT_FOUND;\r
+    NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
 \r
 \r
-      DataItem           = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
-      if (DataItem->Data.Ptr != NULL) {\r
-        FreePool (DataItem->Data.Ptr);\r
-      }\r
-      DataItem->Data.Ptr = NULL;\r
-      DataItem->DataSize = 0;\r
-      DataItem->Status   = EFI_NOT_FOUND;\r
-      NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
+    DataItem           = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
+    if (DataItem->Data.Ptr != NULL) {\r
+      FreePool (DataItem->Data.Ptr);\r
+    }\r
+    DataItem->Data.Ptr = NULL;\r
+    DataItem->DataSize = 0;\r
+    DataItem->Status   = EFI_NOT_FOUND;\r
+    NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
 \r
 \r
-      DataItem           = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
-      if (DataItem->Data.Ptr != NULL) {\r
-        FreePool (DataItem->Data.Ptr);\r
-      }\r
-      DataItem->Data.Ptr = NULL;\r
-      DataItem->DataSize = 0;\r
-      DataItem->Status   = EFI_NOT_FOUND;\r
-      NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
+    DataItem           = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
+    if (DataItem->Data.Ptr != NULL) {\r
+      FreePool (DataItem->Data.Ptr);\r
+    }\r
+    DataItem->Data.Ptr = NULL;\r
+    DataItem->DataSize = 0;\r
+    DataItem->Status   = EFI_NOT_FOUND;\r
+    NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
+    \r
+    if (NewPolicy == Ip4Config2PolicyDhcp) {\r
+      SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_VOLATILE);\r
     } else {\r
       //\r
       // The policy is changed from dhcp to static. Stop the DHCPv4 process\r
     } else {\r
       //\r
       // The policy is changed from dhcp to static. Stop the DHCPv4 process\r
@@ -1025,6 +1186,7 @@ Ip4Config2SetPolicy (
       //\r
       if (Instance->Dhcp4Event != NULL) {\r
         gBS->CloseEvent (Instance->Dhcp4Event);\r
       //\r
       if (Instance->Dhcp4Event != NULL) {\r
         gBS->CloseEvent (Instance->Dhcp4Event);\r
+        Instance->Dhcp4Event = NULL;\r
       }\r
     }\r
   }\r
       }\r
     }\r
   }\r
@@ -1071,6 +1233,9 @@ Ip4Config2SetMaunualAddress (
   IP4_ADDR                       StationAddress;\r
   IP4_ADDR                       SubnetMask;\r
   VOID                           *Ptr;\r
   IP4_ADDR                       StationAddress;\r
   IP4_ADDR                       SubnetMask;\r
   VOID                           *Ptr;\r
+  IP4_SERVICE                    *IpSb;\r
+\r
+  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
 \r
   ASSERT (Instance->DataItem[Ip4Config2DataTypeManualAddress].Status != EFI_NOT_READY);\r
 \r
 \r
   ASSERT (Instance->DataItem[Ip4Config2DataTypeManualAddress].Status != EFI_NOT_READY);\r
 \r
@@ -1084,6 +1249,13 @@ Ip4Config2SetMaunualAddress (
 \r
   NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data);\r
 \r
 \r
   NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data);\r
 \r
+  StationAddress = EFI_NTOHL (NewAddress.Address);\r
+  SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);\r
+\r
+  if (NetGetMaskLength (SubnetMask) == IP4_MASK_NUM) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   //\r
   // Store the new data, and init the DataItem status to EFI_NOT_READY because\r
   // we may have an asynchronous configuration process.\r
   //\r
   // Store the new data, and init the DataItem status to EFI_NOT_READY because\r
   // we may have an asynchronous configuration process.\r
@@ -1102,25 +1274,19 @@ Ip4Config2SetMaunualAddress (
   DataItem->DataSize = DataSize;\r
   DataItem->Status   = EFI_NOT_READY;\r
 \r
   DataItem->DataSize = DataSize;\r
   DataItem->Status   = EFI_NOT_READY;\r
 \r
-  StationAddress = EFI_NTOHL (NewAddress.Address);\r
-  SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);\r
-\r
-  Status = Ip4Config2SetDefaultAddr (Instance, StationAddress, SubnetMask);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }  \r
+  IpSb->Reconfig = TRUE;\r
+  Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);\r
 \r
 \r
-  DataItem->Status = EFI_SUCCESS;   \r
+  DataItem->Status = Status; \r
 \r
 \r
-ON_EXIT:\r
-  if (EFI_ERROR (DataItem->Status)) {\r
+  if (EFI_ERROR (DataItem->Status) && DataItem->Status != EFI_NOT_READY) {\r
     if (Ptr != NULL) {\r
       FreePool (Ptr);\r
     }\r
     DataItem->Data.Ptr = NULL; \r
   }\r
 \r
     if (Ptr != NULL) {\r
       FreePool (Ptr);\r
     }\r
     DataItem->Data.Ptr = NULL; \r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -1174,14 +1340,15 @@ Ip4Config2SetGateway (
     return EFI_WRITE_PROTECTED;\r
   }\r
 \r
     return EFI_WRITE_PROTECTED;\r
   }\r
 \r
+  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
 \r
   NewGateway      = (EFI_IPv4_ADDRESS *) Data;\r
   NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS);\r
   for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
     CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));\r
 \r
   NewGateway      = (EFI_IPv4_ADDRESS *) Data;\r
   NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS);\r
   for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
     CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));\r
-    \r
-    if (!NetIp4IsUnicast (NTOHL (Gateway), 0)) {\r
 \r
 \r
+    if ((IpSb->DefaultInterface->SubnetMask != 0) && \r
+        !NetIp4IsUnicast (NTOHL (Gateway), IpSb->DefaultInterface->SubnetMask)) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
@@ -1192,7 +1359,6 @@ Ip4Config2SetGateway (
     }\r
   }\r
  \r
     }\r
   }\r
  \r
-  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
   DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
   OldGateway      = DataItem->Data.Gateway;\r
   OldGatewayCount = DataItem->DataSize / sizeof (EFI_IPv4_ADDRESS);\r
   DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
   OldGateway      = DataItem->Data.Gateway;\r
   OldGatewayCount = DataItem->DataSize / sizeof (EFI_IPv4_ADDRESS);\r
@@ -1285,102 +1451,21 @@ Ip4Config2SetDnsServer (
   IN VOID                 *Data\r
   )\r
 {\r
   IN VOID                 *Data\r
   )\r
 {\r
-  UINTN                 OldIndex;\r
-  UINTN                 NewIndex;\r
-  UINTN                 Index1;\r
-  EFI_IPv4_ADDRESS      *OldDns;\r
-  EFI_IPv4_ADDRESS      *NewDns;\r
-  UINTN                 OldDnsCount;\r
-  UINTN                 NewDnsCount;\r
   IP4_CONFIG2_DATA_ITEM *Item;\r
   IP4_CONFIG2_DATA_ITEM *Item;\r
-  BOOLEAN               OneAdded;\r
-  VOID                  *Tmp;\r
-  IP4_ADDR              DnsAddress;\r
 \r
 \r
-  if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {\r
-    return EFI_BAD_BUFFER_SIZE;\r
-  }\r
+  Item = NULL;\r
 \r
   if (Instance->Policy != Ip4Config2PolicyStatic) {\r
     return EFI_WRITE_PROTECTED;\r
   }\r
 \r
 \r
   if (Instance->Policy != Ip4Config2PolicyStatic) {\r
     return EFI_WRITE_PROTECTED;\r
   }\r
 \r
-  Item        = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
-  NewDns      = (EFI_IPv4_ADDRESS *) Data;\r
-  OldDns      = Item->Data.DnsServers;\r
-  NewDnsCount = DataSize / sizeof (EFI_IPv4_ADDRESS);\r
-  OldDnsCount = Item->DataSize / sizeof (EFI_IPv4_ADDRESS);\r
-  OneAdded    = FALSE;\r
-\r
-  if (NewDnsCount != OldDnsCount) {\r
-    Tmp = AllocatePool (DataSize);\r
-    if (Tmp == NULL) {\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-  } else {\r
-    Tmp = NULL;\r
-  }\r
-\r
-  for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {\r
-    CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR));\r
-\r
-    if (!NetIp4IsUnicast (NTOHL (DnsAddress), 0)) {\r
-      //\r
-      // The dns server address must be unicast.\r
-      //\r
-      FreePool (Tmp);\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    for (Index1 = NewIndex + 1; Index1 < NewDnsCount; Index1++) {\r
-      if (EFI_IP4_EQUAL (NewDns + NewIndex, NewDns + Index1)) {\r
-        FreePool (Tmp);\r
-        return EFI_INVALID_PARAMETER;\r
-      }\r
-    }\r
-\r
-    if (OneAdded) {\r
-      //\r
-      // If any address in the new setting is not in the old settings, skip the\r
-      // comparision below.\r
-      //\r
-      continue;\r
-    }\r
-\r
-    for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {\r
-      if (EFI_IP4_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {\r
-        //\r
-        // If found break out.\r
-        //\r
-        break;\r
-      }\r
-    }\r
-\r
-    if (OldIndex == OldDnsCount) {\r
-      OneAdded = TRUE;\r
-    }\r
-  }\r
-\r
-  if (!OneAdded && (DataSize == Item->DataSize)) {\r
-    //\r
-    // No new item is added and the size is the same.\r
-    //\r
-    Item->Status = EFI_SUCCESS;\r
-    return EFI_ABORTED;\r
-  } else {\r
-    if (Tmp != NULL) {\r
-      if (Item->Data.Ptr != NULL) {\r
-        FreePool (Item->Data.Ptr);\r
-      }      \r
-      Item->Data.Ptr = Tmp;\r
-    }\r
+  Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
 \r
 \r
-    CopyMem (Item->Data.Ptr, Data, DataSize);\r
-    Item->DataSize = DataSize;\r
-    Item->Status   = EFI_SUCCESS;\r
-    return EFI_SUCCESS;\r
+  if (DATA_ATTRIB_SET (Item->Attribute, DATA_ATTRIB_VOLATILE)) {\r
+    REMOVE_DATA_ATTRIB (Item->Attribute, DATA_ATTRIB_VOLATILE);\r
   }\r
 \r
   }\r
 \r
+  return Ip4Config2SetDnsServerWorker (Instance, DataSize, Data);\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -1397,11 +1482,12 @@ Ip4Config2InitIfInfo (
   OUT EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo\r
   )\r
 {\r
   OUT EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo\r
   )\r
 {\r
-  IfInfo->Name[0] = L'e';\r
-  IfInfo->Name[1] = L't';\r
-  IfInfo->Name[2] = L'h';\r
-  IfInfo->Name[3] = (CHAR16) (L'0' + IpSb->Ip4Config2Instance.IfIndex);\r
-  IfInfo->Name[4] = 0;\r
+  UnicodeSPrint (\r
+    IfInfo->Name,\r
+    EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE,\r
+    L"eth%d",\r
+    IpSb->Ip4Config2Instance.IfIndex\r
+  );\r
 \r
   IfInfo->IfType        = IpSb->SnpMode.IfType;\r
   IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize;\r
 \r
   IfInfo->IfType        = IpSb->SnpMode.IfType;\r
   IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize;\r
@@ -1828,7 +1914,7 @@ Ip4Config2InitInstance (
   DataItem->SetData  = Ip4Config2SetPolicy;\r
   DataItem->Data.Ptr = &Instance->Policy;\r
   DataItem->DataSize = sizeof (Instance->Policy);\r
   DataItem->SetData  = Ip4Config2SetPolicy;\r
   DataItem->Data.Ptr = &Instance->Policy;\r
   DataItem->DataSize = sizeof (Instance->Policy);\r
-  Instance->Policy   = Ip4Config2PolicyDhcp;\r
+  Instance->Policy   = Ip4Config2PolicyStatic;\r
   SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);\r
 \r
   DataItem           = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
   SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);\r
 \r
   DataItem           = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
@@ -1859,6 +1945,8 @@ Ip4Config2InitInstance (
 \r
   //\r
   // Try to read the config data from NV variable.\r
 \r
   //\r
   // Try to read the config data from NV variable.\r
+  // If not found, write initialized config data into NV variable \r
+  // as a default config data.\r
   //\r
   Status = Ip4Config2ReadConfigData (IpSb->MacString, Instance);\r
   if (Status == EFI_NOT_FOUND) {\r
   //\r
   Status = Ip4Config2ReadConfigData (IpSb->MacString, Instance);\r
   if (Status == EFI_NOT_FOUND) {\r
@@ -1868,21 +1956,7 @@ Ip4Config2InitInstance (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-\r
-  //\r
-  // Try to set the configured parameter.\r
-  //\r
-  for (Index = Ip4Config2DataTypePolicy; Index < Ip4Config2DataTypeMaximum; Index++) {\r
-    DataItem = &IpSb->Ip4Config2Instance.DataItem[Index];\r
-    if (DataItem->Data.Ptr != NULL) {\r
-      DataItem->SetData (\r
-                  &IpSb->Ip4Config2Instance,\r
-                  DataItem->DataSize,\r
-                  DataItem->Data.Ptr\r
-                  );\r
-    }\r
-  }\r
-\r
+  \r
   Instance->Ip4Config2.SetData              = EfiIp4Config2SetData;\r
   Instance->Ip4Config2.GetData              = EfiIp4Config2GetData;\r
   Instance->Ip4Config2.RegisterDataNotify   = EfiIp4Config2RegisterDataNotify;\r
   Instance->Ip4Config2.SetData              = EfiIp4Config2SetData;\r
   Instance->Ip4Config2.GetData              = EfiIp4Config2GetData;\r
   Instance->Ip4Config2.RegisterDataNotify   = EfiIp4Config2RegisterDataNotify;\r
@@ -1927,6 +2001,7 @@ Ip4Config2CleanInstance (
   //\r
   if (Instance->Dhcp4Event != NULL) {\r
     gBS->CloseEvent (Instance->Dhcp4Event);\r
   //\r
   if (Instance->Dhcp4Event != NULL) {\r
     gBS->CloseEvent (Instance->Dhcp4Event);\r
+    Instance->Dhcp4Event = NULL;\r
   }\r
 \r
   for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {\r
   }\r
 \r
   for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {\r
@@ -1949,3 +2024,53 @@ Ip4Config2CleanInstance (
   RemoveEntryList (&Instance->Link);\r
 }\r
 \r
   RemoveEntryList (&Instance->Link);\r
 }\r
 \r
+/**\r
+  The event handle for IP4 auto reconfiguration. The original default\r
+  interface and route table will be removed as the default.\r
+\r
+  @param[in]  Context                The IP4 service binding instance.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ip4AutoReconfigCallBackDpc (\r
+  IN VOID                   *Context\r
+  )\r
+{\r
+  IP4_SERVICE               *IpSb;\r
+\r
+  IpSb      = (IP4_SERVICE *) Context;\r
+  NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
+\r
+  if (IpSb->State > IP4_SERVICE_UNSTARTED) {\r
+    IpSb->State = IP4_SERVICE_UNSTARTED;\r
+  }\r
+  \r
+  IpSb->Reconfig = TRUE;\r
+\r
+  Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);\r
+\r
+  return ;\r
+}\r
+\r
+\r
+/**\r
+  Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.\r
+\r
+  @param Event     The event that is signalled.\r
+  @param Context   The IP4 service binding instance.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ip4AutoReconfigCallBack (\r
+  IN EFI_EVENT              Event,\r
+  IN VOID                   *Context\r
+  )\r
+{\r
+  //\r
+  // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK\r
+  //\r
+  QueueDpc (TPL_CALLBACK, Ip4AutoReconfigCallBackDpc, Context);\r
+}\r
+\r