]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c
MdeModulePkg: Fix IPv4 double free
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Config2Impl.c
index 2da4a513495e138512d5f7c440ca73279edb593b..17e0247832200cbf3fe7504ab762544cff18b5d4 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 - 2016, 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
@@ -84,22 +85,6 @@ Ip4Config2DestroyDhcp4 (
   return Status;  \r
 }\r
 \r
   return Status;  \r
 }\r
 \r
-/**\r
-  Start the DHCP configuration for this IP service instance.\r
-  It will locates the EFI_IP4_CONFIG2_PROTOCOL, then start the\r
-  DHCP configuration.\r
-\r
-  @param[in]  Instance           The IP4 config2 instance to configure.\r
-\r
-  @retval EFI_SUCCESS            The auto configuration is successfull started.\r
-  @retval Others                 Failed to start auto configuration.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4StartAutoConfig (\r
-  IN IP4_CONFIG2_INSTANCE   *Instance\r
-  );\r
-\r
 /**\r
   Update the current policy to NewPolicy. During the transition\r
   period, the default router list\r
 /**\r
   Update the current policy to NewPolicy. During the transition\r
   period, the default router list\r
@@ -165,6 +150,7 @@ Ip4Config2OnPolicyChanged (
   // Start the dhcp configuration.\r
   //\r
   if (NewPolicy == Ip4Config2PolicyDhcp) {\r
   // Start the dhcp configuration.\r
   //\r
   if (NewPolicy == Ip4Config2PolicyDhcp) {\r
+    IpSb->Reconfig = TRUE;\r
     Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);\r
   }\r
 \r
     Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);\r
   }\r
 \r
@@ -479,7 +465,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
@@ -489,13 +475,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
@@ -503,43 +488,45 @@ 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
   if ((IpIf->Ip == StationAddress) && (IpIf->SubnetMask == SubnetMask)) {\r
   IpIf = IpSb->DefaultInterface;\r
   ASSERT (IpIf != NULL);\r
 \r
   if ((IpIf->Ip == StationAddress) && (IpIf->SubnetMask == SubnetMask)) {\r
+    IpSb->State = IP4_SERVICE_CONFIGED;\r
     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
@@ -593,6 +580,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
@@ -619,7 +608,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
@@ -627,7 +618,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
@@ -688,6 +678,126 @@ 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
+  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
+  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
+\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
+\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
@@ -712,6 +822,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
@@ -735,6 +848,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 == DHCP_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
@@ -842,9 +993,10 @@ Ip4StartAutoConfig (
   // yields the control of this DHCP service to us.\r
   //\r
   ParaList.Head.OpCode             = DHCP_TAG_PARA_LIST;\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.Length             = 3;\r
   ParaList.Head.Data[0]            = DHCP_TAG_NETMASK;\r
   ParaList.Route                   = DHCP_TAG_ROUTER;\r
   ParaList.Head.Data[0]            = DHCP_TAG_NETMASK;\r
   ParaList.Route                   = DHCP_TAG_ROUTER;\r
+  ParaList.Dns                     = DHCP_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
@@ -995,7 +1147,6 @@ Ip4Config2SetPolicy (
     if (NewPolicy != Ip4Config2PolicyDhcp || Instance->DhcpSuccess) {\r
       return EFI_ABORTED;\r
     }\r
     if (NewPolicy != Ip4Config2PolicyDhcp || Instance->DhcpSuccess) {\r
       return EFI_ABORTED;\r
     }\r
-    \r
   } else {\r
     if (NewPolicy == Ip4Config2PolicyDhcp) {\r
       //\r
   } else {\r
     if (NewPolicy == Ip4Config2PolicyDhcp) {\r
       //\r
@@ -1043,6 +1194,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
@@ -1089,6 +1241,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
@@ -1123,7 +1278,8 @@ Ip4Config2SetMaunualAddress (
   StationAddress = EFI_NTOHL (NewAddress.Address);\r
   SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);\r
 \r
   StationAddress = EFI_NTOHL (NewAddress.Address);\r
   SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);\r
 \r
-  Status = Ip4Config2SetDefaultAddr (Instance, StationAddress, SubnetMask);\r
+  IpSb->Reconfig = TRUE;\r
+  Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);\r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
   }  \r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
   }  \r
@@ -1303,102 +1459,11 @@ 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
-  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
   if (Instance->Policy != Ip4Config2PolicyStatic) {\r
     return EFI_WRITE_PROTECTED;\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
-\r
-    CopyMem (Item->Data.Ptr, Data, DataSize);\r
-    Item->DataSize = DataSize;\r
-    Item->Status   = EFI_SUCCESS;\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
+  return Ip4Config2SetDnsServerWorker (Instance, DataSize, Data);\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -1846,7 +1911,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
@@ -1877,6 +1942,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
@@ -1886,21 +1953,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
@@ -1945,6 +1998,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
@@ -1967,3 +2021,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