[edk2] [Patch 3/3] NetworkPkg/Ip6Dxe: Support SetData interface to clear specific configuration

Jiaxin Wu posted 3 patches 7 years, 5 months ago
[edk2] [Patch 3/3] NetworkPkg/Ip6Dxe: Support SetData interface to clear specific configuration
Posted by Jiaxin Wu 7 years, 5 months ago
UEFI Spec 2.7 adds the clarification on SetData interface usage to clear specific
individual data types. This patch is to support this feature.

Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com>
---
 NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c | 692 ++++++++++++++++++++++----------------
 1 file changed, 399 insertions(+), 293 deletions(-)

diff --git a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
index 7c7acc7..9e9dc89 100644
--- a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
+++ b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
@@ -917,254 +917,333 @@ Ip6ConfigSetManualAddress (
   LIST_ENTRY                     *Entry2;
   IP6_INTERFACE                  *IpIf;
   IP6_PREFIX_LIST_ENTRY          *PrefixEntry;
   EFI_STATUS                     Status;
   BOOLEAN                        IsUpdated;
+  LIST_ENTRY                     *Next;
+  IP6_DAD_ENTRY                  *DadEntry;
+  IP6_DELAY_JOIN_LIST            *DelayNode;
+
+  NewAddress      = NULL;
+  TmpAddress      = NULL;
+  CurrentAddrInfo = NULL;
+  Copy            = NULL;
+  Entry           = NULL;
+  Entry2          = NULL;
+  IpIf            = NULL;
+  PrefixEntry     = NULL;
+  Next            = NULL;
+  DadEntry        = NULL;
+  DelayNode       = NULL;
+  Status          = EFI_SUCCESS;
 
   ASSERT (Instance->DataItem[Ip6ConfigDataTypeManualAddress].Status != EFI_NOT_READY);
 
-  if (((DataSize % sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)) != 0) || (DataSize == 0)) {
+  if ((DataSize != 0) && ((DataSize % sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)) != 0)) {
     return EFI_BAD_BUFFER_SIZE;
   }
 
   if (Instance->Policy != Ip6ConfigPolicyManual) {
     return EFI_WRITE_PROTECTED;
   }
 
-  NewAddressCount = DataSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);
-  NewAddress      = (EFI_IP6_CONFIG_MANUAL_ADDRESS *) Data;
+  IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
 
-  for (Index1 = 0; Index1 < NewAddressCount; Index1++, NewAddress++) {
+  DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];
 
-    if (NetIp6IsLinkLocalAddr (&NewAddress->Address)    ||
-        !NetIp6IsValidUnicast (&NewAddress->Address)    ||
-        (NewAddress->PrefixLength > 128)
-        ) {
-      //
-      // make sure the IPv6 address is unicast and not link-local address &&
-      // the prefix length is valid.
-      //
-      return EFI_INVALID_PARAMETER;
-    }
+  if (Data != NULL && DataSize != 0) {
+    NewAddressCount = DataSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);
+    NewAddress      = (EFI_IP6_CONFIG_MANUAL_ADDRESS *) Data;
 
-    TmpAddress = NewAddress + 1;
-    for (Index2 = Index1 + 1; Index2 < NewAddressCount; Index2++, TmpAddress++) {
-      //
-      // Any two addresses in the array can't be equal.
-      //
-      if (EFI_IP6_EQUAL (&TmpAddress->Address, &NewAddress->Address)) {
+    for (Index1 = 0; Index1 < NewAddressCount; Index1++, NewAddress++) {
 
+      if (NetIp6IsLinkLocalAddr (&NewAddress->Address)    ||
+          !NetIp6IsValidUnicast (&NewAddress->Address)    ||
+          (NewAddress->PrefixLength > 128)
+          ) {
+        //
+        // make sure the IPv6 address is unicast and not link-local address &&
+        // the prefix length is valid.
+        //
         return EFI_INVALID_PARAMETER;
       }
+
+      TmpAddress = NewAddress + 1;
+      for (Index2 = Index1 + 1; Index2 < NewAddressCount; Index2++, TmpAddress++) {
+        //
+        // Any two addresses in the array can't be equal.
+        //
+        if (EFI_IP6_EQUAL (&TmpAddress->Address, &NewAddress->Address)) {
+
+          return EFI_INVALID_PARAMETER;
+        }
+      }
     }
-  }
 
-  IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
+    //
+    // Build the current source address list.
+    //
+    InitializeListHead (&CurrentSourceList);
+    CurrentSourceCount = 0;
 
-  //
-  // Build the current source address list.
-  //
-  InitializeListHead (&CurrentSourceList);
-  CurrentSourceCount = 0;
+    NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
+      IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
 
-  NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
-    IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
+      NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {
+        CurrentAddrInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
 
-    NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {
-      CurrentAddrInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
+        Copy            = AllocateCopyPool (sizeof (IP6_ADDRESS_INFO), CurrentAddrInfo);
+        if (Copy == NULL) {
+          break;
+        }
 
-      Copy            = AllocateCopyPool (sizeof (IP6_ADDRESS_INFO), CurrentAddrInfo);
-      if (Copy == NULL) {
-        break;
+        InsertTailList (&CurrentSourceList, &Copy->Link);
+        CurrentSourceCount++;
       }
+    }
+
+    //
+    // Update the value... a long journey starts
+    //
+    NewAddress = AllocateCopyPool (DataSize, Data);
+    if (NewAddress == NULL) {
+      Ip6RemoveAddr (NULL, &CurrentSourceList, &CurrentSourceCount, NULL, 0);
 
-      InsertTailList (&CurrentSourceList, &Copy->Link);
-      CurrentSourceCount++;
+      return EFI_OUT_OF_RESOURCES;
     }
-  }
 
-  //
-  // Update the value... a long journey starts
-  //
-  NewAddress = AllocateCopyPool (DataSize, Data);
-  if (NewAddress == NULL) {
-    Ip6RemoveAddr (NULL, &CurrentSourceList, &CurrentSourceCount, NULL, 0);
+    //
+    // Store the new data, and init the DataItem status to EFI_NOT_READY because
+    // we may have an asynchronous configuration process.
+    //
+    if (DataItem->Data.Ptr != NULL) {
+      FreePool (DataItem->Data.Ptr);
+    }
+    DataItem->Data.Ptr = NewAddress;
+    DataItem->DataSize = DataSize;
+    DataItem->Status   = EFI_NOT_READY;
 
-    return EFI_OUT_OF_RESOURCES;
-  }
+    //
+    // Trigger DAD, it's an asynchronous process.
+    //
+    IsUpdated  = FALSE;
 
-  //
-  // Store the new data, and init the DataItem status to EFI_NOT_READY because
-  // we may have an asynchronous configuration process.
-  //
-  DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];
-  if (DataItem->Data.Ptr != NULL) {
-    FreePool (DataItem->Data.Ptr);
-  }
-  DataItem->Data.Ptr = NewAddress;
-  DataItem->DataSize = DataSize;
-  DataItem->Status   = EFI_NOT_READY;
+    for (Index1 = 0; Index1 < NewAddressCount; Index1++, NewAddress++) {
+      if (Ip6IsOneOfSetAddress (IpSb, &NewAddress->Address, NULL, &CurrentAddrInfo)) {
+        ASSERT (CurrentAddrInfo != NULL);
+        //
+        // Remove this already existing source address from the CurrentSourceList
+        // built before.
+        //
+        Ip6RemoveAddr (
+          NULL,
+          &CurrentSourceList,
+          &CurrentSourceCount,
+          &CurrentAddrInfo->Address,
+          128
+          );
 
-  //
-  // Trigger DAD, it's an asynchronous process.
-  //
-  IsUpdated  = FALSE;
+        //
+        // If the new address's prefix length is not specified, just use the previous configured
+        // prefix length for this address.
+        //
+        if (NewAddress->PrefixLength == 0) {
+          NewAddress->PrefixLength = CurrentAddrInfo->PrefixLength;
+        }
 
-  for (Index1 = 0; Index1 < NewAddressCount; Index1++, NewAddress++) {
-    if (Ip6IsOneOfSetAddress (IpSb, &NewAddress->Address, NULL, &CurrentAddrInfo)) {
-      ASSERT (CurrentAddrInfo != NULL);
-      //
-      // Remove this already existing source address from the CurrentSourceList
-      // built before.
-      //
-      Ip6RemoveAddr (
-        NULL,
-        &CurrentSourceList,
-        &CurrentSourceCount,
-        &CurrentAddrInfo->Address,
-        128
-        );
+        //
+        // This manual address is already in use, see whether prefix length is changed.
+        //
+        if (NewAddress->PrefixLength != CurrentAddrInfo->PrefixLength) {
+          //
+          // Remove the on-link prefix table, the route entry will be removed
+          // implicitly.
+          //
+          PrefixEntry = Ip6FindPrefixListEntry (
+                          IpSb,
+                          TRUE,
+                          CurrentAddrInfo->PrefixLength,
+                          &CurrentAddrInfo->Address
+                          );
+          if (PrefixEntry != NULL) {
+            Ip6DestroyPrefixListEntry (IpSb, PrefixEntry, TRUE, FALSE);
+          }
 
-      //
-      // If the new address's prefix length is not specified, just use the previous configured
-      // prefix length for this address.
-      //
-      if (NewAddress->PrefixLength == 0) {
-        NewAddress->PrefixLength = CurrentAddrInfo->PrefixLength;
-      }
+          //
+          // Save the prefix length.
+          //
+          CurrentAddrInfo->PrefixLength = NewAddress->PrefixLength;
+          IsUpdated = TRUE;
+        }
 
-      //
-      // This manual address is already in use, see whether prefix length is changed.
-      //
-      if (NewAddress->PrefixLength != CurrentAddrInfo->PrefixLength) {
         //
-        // Remove the on-link prefix table, the route entry will be removed
-        // implicitly.
+        // create a new on-link prefix entry.
         //
         PrefixEntry = Ip6FindPrefixListEntry (
                         IpSb,
                         TRUE,
-                        CurrentAddrInfo->PrefixLength,
-                        &CurrentAddrInfo->Address
+                        NewAddress->PrefixLength,
+                        &NewAddress->Address
                         );
-        if (PrefixEntry != NULL) {
-          Ip6DestroyPrefixListEntry (IpSb, PrefixEntry, TRUE, FALSE);
+        if (PrefixEntry == NULL) {
+          Ip6CreatePrefixListEntry (
+            IpSb,
+            TRUE,
+            (UINT32) IP6_INFINIT_LIFETIME,
+            (UINT32) IP6_INFINIT_LIFETIME,
+            NewAddress->PrefixLength,
+            &NewAddress->Address
+            );
         }
 
+        CurrentAddrInfo->IsAnycast = NewAddress->IsAnycast;
         //
-        // Save the prefix length.
+        // Artificially mark this address passed DAD be'coz it is already in use.
+        //
+        Ip6ManualAddrDadCallback (TRUE, &NewAddress->Address, Instance);
+      } else {
+        //
+        // A new address.
         //
-        CurrentAddrInfo->PrefixLength = NewAddress->PrefixLength;
         IsUpdated = TRUE;
+
+        //
+        // Set the new address, this will trigger DAD and activate the address if
+        // DAD succeeds.
+        //
+        Ip6SetAddress (
+          IpSb->DefaultInterface,
+          &NewAddress->Address,
+          NewAddress->IsAnycast,
+          NewAddress->PrefixLength,
+          (UINT32) IP6_INFINIT_LIFETIME,
+          (UINT32) IP6_INFINIT_LIFETIME,
+          Ip6ManualAddrDadCallback,
+          Instance
+          );
       }
+    }
+
+    //
+    // Check the CurrentSourceList, it now contains those addresses currently in
+    // use and will be removed.
+    //
+    IpIf = IpSb->DefaultInterface;
+
+    while (!IsListEmpty (&CurrentSourceList)) {
+      IsUpdated = TRUE;
+
+      CurrentAddrInfo = NET_LIST_HEAD (&CurrentSourceList, IP6_ADDRESS_INFO, Link);
 
       //
-      // create a new on-link prefix entry.
+      // This local address is going to be removed, the IP instances that are
+      // currently using it will be destroyed.
+      //
+      Ip6RemoveAddr (
+        IpSb,
+        &IpIf->AddressList,
+        &IpIf->AddressCount,
+        &CurrentAddrInfo->Address,
+        128
+        );
+
+      //
+      // Remove the on-link prefix table, the route entry will be removed
+      // implicitly.
       //
       PrefixEntry = Ip6FindPrefixListEntry (
                       IpSb,
                       TRUE,
-                      NewAddress->PrefixLength,
-                      &NewAddress->Address
+                      CurrentAddrInfo->PrefixLength,
+                      &CurrentAddrInfo->Address
                       );
-      if (PrefixEntry == NULL) {
-        Ip6CreatePrefixListEntry (
-          IpSb,
-          TRUE,
-          (UINT32) IP6_INFINIT_LIFETIME,
-          (UINT32) IP6_INFINIT_LIFETIME,
-          NewAddress->PrefixLength,
-          &NewAddress->Address
-          );
+      if (PrefixEntry != NULL) {
+        Ip6DestroyPrefixListEntry (IpSb, PrefixEntry, TRUE, FALSE);
       }
 
-      CurrentAddrInfo->IsAnycast = NewAddress->IsAnycast;
-      //
-      // Artificially mark this address passed DAD be'coz it is already in use.
-      //
-      Ip6ManualAddrDadCallback (TRUE, &NewAddress->Address, Instance);
+      RemoveEntryList (&CurrentAddrInfo->Link);
+      FreePool (CurrentAddrInfo);
+    }
+
+    if (IsUpdated) {
+      if (DataItem->Status == EFI_NOT_READY) {
+        //
+        // If DAD is disabled on this interface, the configuration process is
+        // actually synchronous, and the data item's status will be changed to
+        // the final status before we reach here, just check it.
+        //
+        Status = EFI_NOT_READY;
+      } else {
+        Status = EFI_SUCCESS;
+      }
     } else {
       //
-      // A new address.
+      // No update is taken, reset the status to success and return EFI_ABORTED.
       //
-      IsUpdated = TRUE;
+      DataItem->Status = EFI_SUCCESS;
+      Status           = EFI_ABORTED;
+    }
+  } else {
+    //
+    // DataSize is 0 and Data is NULL, clean up the manual address.
+    //
+    if (DataItem->Data.Ptr != NULL) {
+      FreePool (DataItem->Data.Ptr);
+    }
+    DataItem->Data.Ptr = NULL;
+    DataItem->DataSize = 0;
+    DataItem->Status   = EFI_NOT_FOUND;
 
-      //
-      // Set the new address, this will trigger DAD and activate the address if
-      // DAD succeeds.
-      //
-      Ip6SetAddress (
-        IpSb->DefaultInterface,
-        &NewAddress->Address,
-        NewAddress->IsAnycast,
-        NewAddress->PrefixLength,
+    Ip6CleanDefaultRouterList (IpSb);
+    Ip6CleanPrefixListTable (IpSb, &IpSb->OnlinkPrefix);
+    Ip6CleanPrefixListTable (IpSb, &IpSb->AutonomousPrefix);
+    Ip6CleanAssembleTable (&IpSb->Assemble);
+
+    if (IpSb->LinkLocalOk) {
+      Ip6CreatePrefixListEntry (
+        IpSb,
+        TRUE,
         (UINT32) IP6_INFINIT_LIFETIME,
         (UINT32) IP6_INFINIT_LIFETIME,
-        Ip6ManualAddrDadCallback,
-        Instance
+        IP6_LINK_LOCAL_PREFIX_LENGTH,
+        &IpSb->LinkLocalAddr
         );
     }
-  }
 
-  //
-  // Check the CurrentSourceList, it now contains those addresses currently in
-  // use and will be removed.
-  //
-  IpIf = IpSb->DefaultInterface;
-
-  while (!IsListEmpty (&CurrentSourceList)) {
-    IsUpdated = TRUE;
-
-    CurrentAddrInfo = NET_LIST_HEAD (&CurrentSourceList, IP6_ADDRESS_INFO, Link);
-
-    //
-    // This local address is going to be removed, the IP instances that are
-    // currently using it will be destroyed.
-    //
     Ip6RemoveAddr (
       IpSb,
-      &IpIf->AddressList,
-      &IpIf->AddressCount,
-      &CurrentAddrInfo->Address,
-      128
+      &IpSb->DefaultInterface->AddressList,
+      &IpSb->DefaultInterface->AddressCount,
+      NULL,
+      0
       );
 
-    //
-    // Remove the on-link prefix table, the route entry will be removed
-    // implicitly.
-    //
-    PrefixEntry = Ip6FindPrefixListEntry (
-                    IpSb,
-                    TRUE,
-                    CurrentAddrInfo->PrefixLength,
-                    &CurrentAddrInfo->Address
-                    );
-    if (PrefixEntry != NULL) {
-      Ip6DestroyPrefixListEntry (IpSb, PrefixEntry, TRUE, FALSE);
-    }
-
-    RemoveEntryList (&CurrentAddrInfo->Link);
-    FreePool (CurrentAddrInfo);
-  }
-
-  if (IsUpdated) {
-    if (DataItem->Status == EFI_NOT_READY) {
+    NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
       //
-      // If DAD is disabled on this interface, the configuration process is
-      // actually synchronous, and the data item's status will be changed to
-      // the final status before we reach here, just check it.
+      // Remove all pending delay node and DAD entries for the global addresses.
       //
-      Status = EFI_NOT_READY;
-    } else {
-      Status = EFI_SUCCESS;
+      IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
+
+      NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DelayJoinList) {
+        DelayNode = NET_LIST_USER_STRUCT (Entry2, IP6_DELAY_JOIN_LIST, Link);
+        if (!NetIp6IsLinkLocalAddr (&DelayNode->AddressInfo->Address)) {
+          RemoveEntryList (&DelayNode->Link);
+          FreePool (DelayNode);
+        }
+      }
+
+      NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DupAddrDetectList) {
+        DadEntry = NET_LIST_USER_STRUCT_S (Entry2, IP6_DAD_ENTRY, Link, IP6_DAD_ENTRY_SIGNATURE);
+
+        if (!NetIp6IsLinkLocalAddr (&DadEntry->AddressInfo->Address)) {
+          //
+          // Fail this DAD entry if the address is not link-local.
+          //
+          Ip6OnDADFinished (FALSE, IpIf, DadEntry);
+        }
+      }
     }
-  } else {
-    //
-    // No update is taken, reset the status to success and return EFI_ABORTED.
-    //
-    DataItem->Status = EFI_SUCCESS;
-    Status           = EFI_ABORTED;
   }
 
   return Status;
 }
 
@@ -1208,98 +1287,107 @@ Ip6ConfigSetGateway (
   BOOLEAN               OneAdded;
   IP6_SERVICE           *IpSb;
   IP6_DEFAULT_ROUTER    *DefaultRouter;
   VOID                  *Tmp;
 
-  if ((DataSize % sizeof (EFI_IPv6_ADDRESS) != 0) || (DataSize == 0)) {
+  OldGateway      = NULL;
+  NewGateway      = NULL;
+  Item            = NULL;
+  DefaultRouter   = NULL;
+  Tmp             = NULL;
+  OneRemoved      = FALSE;
+  OneAdded        = FALSE;
+
+  if ((DataSize != 0) && (DataSize % sizeof (EFI_IPv6_ADDRESS) != 0)) {
     return EFI_BAD_BUFFER_SIZE;
   }
 
   if (Instance->Policy != Ip6ConfigPolicyManual) {
     return EFI_WRITE_PROTECTED;
   }
 
-  NewGateway      = (EFI_IPv6_ADDRESS *) Data;
-  NewGatewayCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
-  for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
-
-    if (!NetIp6IsValidUnicast (NewGateway + Index1)) {
-
-      return EFI_INVALID_PARAMETER;
-    }
-
-    for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {
-      if (EFI_IP6_EQUAL (NewGateway + Index1, NewGateway + Index2)) {
-        return EFI_INVALID_PARAMETER;
-      }
-    }
-  }
-
   IpSb            = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
   Item            = &Instance->DataItem[Ip6ConfigDataTypeGateway];
   OldGateway      = Item->Data.Gateway;
   OldGatewayCount = Item->DataSize / sizeof (EFI_IPv6_ADDRESS);
-  OneRemoved      = FALSE;
-  OneAdded        = FALSE;
-
-  if (NewGatewayCount != OldGatewayCount) {
-    Tmp = AllocatePool (DataSize);
-    if (Tmp == NULL) {
-      return EFI_OUT_OF_RESOURCES;
-    }
-  } else {
-    Tmp = NULL;
-  }
 
   for (Index1 = 0; Index1 < OldGatewayCount; Index1++) {
     //
-    // Find the gateways that are no long in the new setting and remove them.
+    // Remove this default router.
     //
-    for (Index2 = 0; Index2 < NewGatewayCount; Index2++) {
-      if (EFI_IP6_EQUAL (OldGateway + Index1, NewGateway + Index2)) {
-        OneRemoved = TRUE;
-        break;
+    DefaultRouter = Ip6FindDefaultRouter (IpSb, OldGateway + Index1);
+    if (DefaultRouter != NULL) {
+      Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
+      OneRemoved = TRUE;
+    }
+  }
+
+  if (Data != NULL && DataSize != 0) {
+    NewGateway      = (EFI_IPv6_ADDRESS *) Data;
+    NewGatewayCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
+    for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
+
+      if (!NetIp6IsValidUnicast (NewGateway + Index1)) {
+
+        return EFI_INVALID_PARAMETER;
+      }
+
+      for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {
+        if (EFI_IP6_EQUAL (NewGateway + Index1, NewGateway + Index2)) {
+          return EFI_INVALID_PARAMETER;
+        }
       }
     }
 
-    if (Index2 == NewGatewayCount) {
-      //
-      // Remove this default router.
-      //
-      DefaultRouter = Ip6FindDefaultRouter (IpSb, OldGateway + Index1);
-      if (DefaultRouter != NULL) {
-        Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
+    if (NewGatewayCount != OldGatewayCount) {
+      Tmp = AllocatePool (DataSize);
+      if (Tmp == NULL) {
+        return EFI_OUT_OF_RESOURCES;
       }
+    } else {
+      Tmp = NULL;
     }
-  }
 
-  for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
+    for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
 
-    DefaultRouter = Ip6FindDefaultRouter (IpSb, NewGateway + Index1);
-    if (DefaultRouter == NULL) {
-      Ip6CreateDefaultRouter (IpSb, NewGateway + Index1, IP6_INF_ROUTER_LIFETIME);
-      OneAdded = TRUE;
+      DefaultRouter = Ip6FindDefaultRouter (IpSb, NewGateway + Index1);
+      if (DefaultRouter == NULL) {
+        Ip6CreateDefaultRouter (IpSb, NewGateway + Index1, IP6_INF_ROUTER_LIFETIME);
+        OneAdded = TRUE;
+      }
     }
-  }
 
-  if (!OneRemoved && !OneAdded) {
-    Item->Status = EFI_SUCCESS;
-    return EFI_ABORTED;
-  } else {
+    if (!OneRemoved && !OneAdded) {
+      Item->Status = EFI_SUCCESS;
+      return EFI_ABORTED;
+    } else {
 
-    if (Tmp != NULL) {
-      if (Item->Data.Ptr != NULL) {
-        FreePool (Item->Data.Ptr);
+      if (Tmp != NULL) {
+        if (Item->Data.Ptr != NULL) {
+          FreePool (Item->Data.Ptr);
+        }
+        Item->Data.Ptr = Tmp;
       }
-      Item->Data.Ptr = Tmp;
-    }
 
-    CopyMem (Item->Data.Ptr, Data, DataSize);
-    Item->DataSize = DataSize;
-    Item->Status   = EFI_SUCCESS;
-    return EFI_SUCCESS;
+      CopyMem (Item->Data.Ptr, Data, DataSize);
+      Item->DataSize = DataSize;
+      Item->Status   = EFI_SUCCESS;
+      return EFI_SUCCESS;
+    }
+  } else {
+    //
+    // DataSize is 0 and Data is NULL, clean up the Gateway address.
+    //
+    if (Item->Data.Ptr != NULL) {
+      FreePool (Item->Data.Ptr);
+    }
+    Item->Data.Ptr = NULL;
+    Item->DataSize = 0;
+    Item->Status   = EFI_NOT_FOUND;
   }
+
+  return EFI_SUCCESS;
 }
 
 /**
   The work function for EfiIp6ConfigSetData() to set the DNS server list for the
   EFI IPv6 network stack running on the communication device that this EFI IPv6
@@ -1337,87 +1425,106 @@ Ip6ConfigSetDnsServer (
   UINTN                 NewDnsCount;
   IP6_CONFIG_DATA_ITEM  *Item;
   BOOLEAN               OneAdded;
   VOID                  *Tmp;
 
-  if ((DataSize % sizeof (EFI_IPv6_ADDRESS) != 0) || (DataSize == 0)) {
+  OldDns = NULL;
+  NewDns = NULL;
+  Item   = NULL;
+  Tmp    = NULL;
+
+  if ((DataSize == 0) && (DataSize % sizeof (EFI_IPv6_ADDRESS) != 0)) {
     return EFI_BAD_BUFFER_SIZE;
   }
 
   if (Instance->Policy != Ip6ConfigPolicyManual) {
     return EFI_WRITE_PROTECTED;
   }
 
-  Item        = &Instance->DataItem[Ip6ConfigDataTypeDnsServer];
-  NewDns      = (EFI_IPv6_ADDRESS *) Data;
-  OldDns      = Item->Data.DnsServers;
-  NewDnsCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
-  OldDnsCount = Item->DataSize / sizeof (EFI_IPv6_ADDRESS);
-  OneAdded    = FALSE;
+  Item = &Instance->DataItem[Ip6ConfigDataTypeDnsServer];
 
-  if (NewDnsCount != OldDnsCount) {
-    Tmp = AllocatePool (DataSize);
-    if (Tmp == NULL) {
-      return EFI_OUT_OF_RESOURCES;
-    }
-  } else {
-    Tmp = NULL;
-  }
+  if (Data != NULL && DataSize != 0) {
+    NewDns      = (EFI_IPv6_ADDRESS *) Data;
+    OldDns      = Item->Data.DnsServers;
+    NewDnsCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
+    OldDnsCount = Item->DataSize / sizeof (EFI_IPv6_ADDRESS);
+    OneAdded    = FALSE;
 
-  for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {
-
-    if (!NetIp6IsValidUnicast (NewDns + NewIndex)) {
-      //
-      // The dns server address must be unicast.
-      //
-      if (Tmp != NULL) {
-        FreePool (Tmp);
+    if (NewDnsCount != OldDnsCount) {
+      Tmp = AllocatePool (DataSize);
+      if (Tmp == NULL) {
+        return EFI_OUT_OF_RESOURCES;
       }
-      return EFI_INVALID_PARAMETER;
+    } else {
+      Tmp = NULL;
     }
 
-    if (OneAdded) {
-      //
-      // If any address in the new setting is not in the old settings, skip the
-      // comparision below.
-      //
-      continue;
-    }
+    for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {
 
-    for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {
-      if (EFI_IP6_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {
+      if (!NetIp6IsValidUnicast (NewDns + NewIndex)) {
         //
-        // If found break out.
+        // The dns server address must be unicast.
         //
-        break;
+        if (Tmp != NULL) {
+          FreePool (Tmp);
+        }
+        return EFI_INVALID_PARAMETER;
       }
-    }
 
-    if (OldIndex == OldDnsCount) {
-      OneAdded = TRUE;
+      if (OneAdded) {
+        //
+        // If any address in the new setting is not in the old settings, skip the
+        // comparision below.
+        //
+        continue;
+      }
+
+      for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {
+        if (EFI_IP6_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {
+          //
+          // If found break out.
+          //
+          break;
+        }
+      }
+
+      if (OldIndex == OldDnsCount) {
+        OneAdded = TRUE;
+      }
     }
-  }
 
-  if (!OneAdded && (DataSize == Item->DataSize)) {
+    if (!OneAdded && (DataSize == Item->DataSize)) {
+      //
+      // No new item is added and the size is the same.
+      //
+      Item->Status = EFI_SUCCESS;
+      return EFI_ABORTED;
+    } else {
+      if (Tmp != NULL) {
+        if (Item->Data.Ptr != NULL) {
+          FreePool (Item->Data.Ptr);
+        }
+        Item->Data.Ptr = Tmp;
+      }
+
+      CopyMem (Item->Data.Ptr, Data, DataSize);
+      Item->DataSize = DataSize;
+      Item->Status   = EFI_SUCCESS;
+    }
+  } else  {
     //
-    // No new item is added and the size is the same.
+    // DataSize is 0 and Data is NULL, clean up the DnsServer address. 
     //
-    Item->Status = EFI_SUCCESS;
-    return EFI_ABORTED;
-  } else {
-    if (Tmp != NULL) {
-      if (Item->Data.Ptr != NULL) {
-        FreePool (Item->Data.Ptr);
-      }
-      Item->Data.Ptr = Tmp;
+    if (Item->Data.Ptr != NULL) {
+      FreePool (Item->Data.Ptr);
     }
-
-    CopyMem (Item->Data.Ptr, Data, DataSize);
-    Item->DataSize = DataSize;
-    Item->Status   = EFI_SUCCESS;
-    return EFI_SUCCESS;
+    Item->Data.Ptr = NULL;
+    Item->DataSize = 0;
+    Item->Status   = EFI_NOT_FOUND;
   }
+
+  return EFI_SUCCESS;
 }
 
 /**
   Generate the operational state of the interface this IP6 config instance manages
   and output in EFI_IP6_CONFIG_INTERFACE_INFO.
@@ -1822,13 +1929,12 @@ Ip6ConfigOnDhcp6SbInstalled (
 
   @retval EFI_SUCCESS           The specified configuration data for the EFI IPv6
                                 network stack was set successfully.
   @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
                                 - This is NULL.
-                                - Data is NULL.
-                                - One or more fields in Data do not match the requirement of the
-                                  data type indicated by DataType.
+                                - One or more fields in Data and DataSizedo not match the 
+                                  requirement of the data type indicated by DataType.
   @retval EFI_WRITE_PROTECTED   The specified configuration data is read-only or the specified
                                 configuration data cannot be set under the current policy.
   @retval EFI_ACCESS_DENIED     Another set operation on the specified configuration
                                 data is already in process.
   @retval EFI_NOT_READY         An asynchronous process was invoked to set the specified
@@ -1852,11 +1958,11 @@ EfiIp6ConfigSetData (
   EFI_TPL              OldTpl;
   EFI_STATUS           Status;
   IP6_CONFIG_INSTANCE  *Instance;
   IP6_SERVICE          *IpSb;
 
-  if ((This == NULL) || (Data == NULL)) {
+  if ((This == NULL) || (Data == NULL && DataSize != 0) || (Data != NULL && DataSize == 0)) {
     return EFI_INVALID_PARAMETER;
   }
 
   if (DataType >= Ip6ConfigDataTypeMaximum) {
     return EFI_UNSUPPORTED;
-- 
1.9.5.msysgit.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel