From: Jiaxin Wu Date: Tue, 28 Feb 2017 00:35:26 +0000 (+0800) Subject: NetworkPkg/Ip6Dxe: Support SetData interface to clear specific configuration X-Git-Tag: edk2-stable201903~3660 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=bee7fe0ef950e2966cbdcd753be326f8a3c782f3 NetworkPkg/Ip6Dxe: Support SetData interface to clear specific configuration 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 Cc: Fu Siyuan Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Wu Jiaxin Reviewed-by: Ye Ting --- diff --git a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c index f17071656d..61418e2b90 100644 --- a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c +++ b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c @@ -953,10 +953,26 @@ Ip6ConfigSetManualAddress ( 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; } @@ -964,239 +980,302 @@ Ip6ConfigSetManualAddress ( 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; @@ -1244,7 +1323,15 @@ Ip6ConfigSetGateway ( 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; } @@ -1252,86 +1339,87 @@ Ip6ConfigSetGateway ( 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; } /** @@ -1373,7 +1461,12 @@ Ip6ConfigSetDnsServer ( 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; } @@ -1381,75 +1474,89 @@ Ip6ConfigSetDnsServer ( 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; - - if (NewDnsCount != OldDnsCount) { - Tmp = AllocatePool (DataSize); - if (Tmp == NULL) { - return EFI_OUT_OF_RESOURCES; - } - } else { - Tmp = NULL; - } + Item = &Instance->DataItem[Ip6ConfigDataTypeDnsServer]; - for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) { + 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; - 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; } /** @@ -1858,9 +1965,8 @@ Ip6ConfigOnDhcp6SbInstalled ( 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 @@ -1888,7 +1994,7 @@ EfiIp6ConfigSetData ( 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; }