From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 0013221C91278 for ; Tue, 25 Jul 2017 23:26:38 -0700 (PDT) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga105.fm.intel.com with ESMTP; 25 Jul 2017 23:28:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.40,413,1496127600"; d="scan'208";a="997280375" Received: from jiaxinwu-mobl2.ccr.corp.intel.com ([10.239.196.131]) by orsmga003.jf.intel.com with ESMTP; 25 Jul 2017 23:28:39 -0700 From: Jiaxin Wu To: edk2-devel@lists.01.org Cc: Ye Ting , Fu Siyuan , Wu Jiaxin Date: Wed, 26 Jul 2017 14:28:31 +0800 Message-Id: <1501050511-16884-4-git-send-email-jiaxin.wu@intel.com> X-Mailer: git-send-email 1.9.5.msysgit.1 In-Reply-To: <1501050511-16884-1-git-send-email-jiaxin.wu@intel.com> References: <1501050511-16884-1-git-send-email-jiaxin.wu@intel.com> Subject: [Patch 3/3] NetworkPkg/Ip6Dxe: Support SetData interface to clear specific configuration X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 26 Jul 2017 06:26:39 -0000 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 --- 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