X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=NetworkPkg%2FIp6Dxe%2FIp6ConfigImpl.c;h=f4b9374da2d0c85e3688fce47f28fe2e2c3e67db;hb=c1d6749b0ed3c58b7dc771e0f857995096107f44;hp=9a1e3d076f6a021829a8b28310a5ae828fca7be3;hpb=ae97201c55603b69289c5d2349238ea97b2cd35e;p=mirror_edk2.git diff --git a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c index 9a1e3d076f..f4b9374da2 100644 --- a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c +++ b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c @@ -1,7 +1,7 @@ /** @file The implementation of EFI IPv6 Configuration Protocol. - Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -47,12 +47,18 @@ Ip6ConfigOnPolicyChanged ( IN EFI_IP6_CONFIG_POLICY NewPolicy ) { - LIST_ENTRY *Entry; - LIST_ENTRY *Entry2; - LIST_ENTRY *Next; - IP6_INTERFACE *IpIf; - IP6_DAD_ENTRY *DadEntry; - + LIST_ENTRY *Entry; + LIST_ENTRY *Entry2; + LIST_ENTRY *Next; + IP6_INTERFACE *IpIf; + IP6_DAD_ENTRY *DadEntry; + IP6_DELAY_JOIN_LIST *DelayNode; + IP6_ADDRESS_INFO *AddrInfo; + IP6_PROTOCOL *Instance; + BOOLEAN Recovery; + + Recovery = FALSE; + // // Currently there are only two policies: Manual and Automatic. Regardless of // what transition is going on, i.e., Manual -> Automatic and Automatic -> @@ -79,25 +85,63 @@ Ip6ConfigOnPolicyChanged ( ); } - // - // All IPv6 children that use global unicast address as it's source address - // should be destryoed now. The survivers are those use the link-local address - // or the unspecified address as the source address. - // TODO: Conduct a check here. - Ip6RemoveAddr ( - IpSb, - &IpSb->DefaultInterface->AddressList, - &IpSb->DefaultInterface->AddressCount, - NULL, - 0 - ); + if (!IsListEmpty (&IpSb->DefaultInterface->AddressList) && IpSb->DefaultInterface->AddressCount > 0) { + // + // If any IPv6 children (Instance) in configured state and use global unicast address, it will be + // destroyed in Ip6RemoveAddr() function later. Then, the upper layer driver's Stop() function will be + // called, which may break the upper layer network stacks. So, the driver should take the responsibility + // for the recovery by using ConnectController() after Ip6RemoveAddr(). + // Here, just check whether need to recover the upper layer network stacks later. + // + NET_LIST_FOR_EACH (Entry, &IpSb->DefaultInterface->AddressList) { + AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE); + if (!IsListEmpty (&IpSb->Children)) { + NET_LIST_FOR_EACH (Entry2, &IpSb->Children) { + Instance = NET_LIST_USER_STRUCT_S (Entry2, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE); + if ((Instance->State == IP6_STATE_CONFIGED) && EFI_IP6_EQUAL (&Instance->ConfigData.StationAddress, &AddrInfo->Address)) { + Recovery = TRUE; + break; + } + } + } + } + + // + // All IPv6 children that use global unicast address as it's source address + // should be destroyed now. The survivers are those use the link-local address + // or the unspecified address as the source address. + // TODO: Conduct a check here. + Ip6RemoveAddr ( + IpSb, + &IpSb->DefaultInterface->AddressList, + &IpSb->DefaultInterface->AddressCount, + NULL, + 0 + ); + + if (IpSb->Controller != NULL && Recovery) { + // + // ConnectController() to recover the upper layer network stacks. + // + gBS->ConnectController (IpSb->Controller, NULL, NULL, TRUE); + } + } + NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) { // - // remove all pending DAD entries for the global addresses. + // remove all pending delay node and DAD entries for the global addresses. // 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); @@ -112,7 +156,7 @@ Ip6ConfigOnPolicyChanged ( if (NewPolicy == Ip6ConfigPolicyAutomatic) { // - // Set paramters to trigger router solicitation sending in timer handler. + // Set parameters to trigger router solicitation sending in timer handler. // IpSb->RouterAdvertiseReceived = FALSE; IpSb->SolicitTimer = IP6_MAX_RTR_SOLICITATIONS; @@ -121,7 +165,6 @@ Ip6ConfigOnPolicyChanged ( // IpSb->Ticks = (UINT32) IP6_GET_TICKS (IP6_ONE_SECOND_IN_MS); } - } /** @@ -210,9 +253,9 @@ Ip6ConfigStartStatefulAutoConfig ( // with DNS SERVERS. // Oro = (EFI_DHCP6_PACKET_OPTION *) OptBuf; - Oro->OpCode = HTONS (IP6_CONFIG_DHCP6_OPTION_ORO); + Oro->OpCode = HTONS (DHCP6_OPT_ORO); Oro->OpLen = HTONS (2); - *((UINT16 *) &Oro->Data[0]) = HTONS (IP6_CONFIG_DHCP6_OPTION_DNS_SERVERS); + *((UINT16 *) &Oro->Data[0]) = HTONS (DHCP6_OPT_DNS_SERVERS); OptList[0] = Oro; Status = EFI_SUCCESS; @@ -656,36 +699,35 @@ Ip6ConfigSetPolicy ( return EFI_ABORTED; } else { - - if (NewPolicy == Ip6ConfigPolicyAutomatic) { - // - // Clean the ManualAddress, Gateway and DnsServers, shrink the variable - // data size, and fire up all the related events. - // - DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress]; - if (DataItem->Data.Ptr != NULL) { - FreePool (DataItem->Data.Ptr); - } - DataItem->Data.Ptr = NULL; - DataItem->DataSize = 0; - DataItem->Status = EFI_NOT_FOUND; - NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL); - - DataItem = &Instance->DataItem[Ip6ConfigDataTypeGateway]; - if (DataItem->Data.Ptr != NULL) { - FreePool (DataItem->Data.Ptr); - } - DataItem->Data.Ptr = NULL; - DataItem->DataSize = 0; - DataItem->Status = EFI_NOT_FOUND; - NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL); - - DataItem = &Instance->DataItem[Ip6ConfigDataTypeDnsServer]; - DataItem->Data.Ptr = NULL; - DataItem->DataSize = 0; - DataItem->Status = EFI_NOT_FOUND; - NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL); - } else { + // + // Clean the ManualAddress, Gateway and DnsServers, shrink the variable + // data size, and fire up all the related events. + // + DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress]; + if (DataItem->Data.Ptr != NULL) { + FreePool (DataItem->Data.Ptr); + } + DataItem->Data.Ptr = NULL; + DataItem->DataSize = 0; + DataItem->Status = EFI_NOT_FOUND; + NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL); + + DataItem = &Instance->DataItem[Ip6ConfigDataTypeGateway]; + if (DataItem->Data.Ptr != NULL) { + FreePool (DataItem->Data.Ptr); + } + DataItem->Data.Ptr = NULL; + DataItem->DataSize = 0; + DataItem->Status = EFI_NOT_FOUND; + NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL); + + DataItem = &Instance->DataItem[Ip6ConfigDataTypeDnsServer]; + DataItem->Data.Ptr = NULL; + DataItem->DataSize = 0; + DataItem->Status = EFI_NOT_FOUND; + NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL); + + if (NewPolicy == Ip6ConfigPolicyManual) { // // The policy is changed from automatic to manual. Stop the DHCPv6 process // and destroy the DHCPv6 child. @@ -748,7 +790,7 @@ Ip6ConfigSetDadXmits ( /** The callback function for Ip6SetAddr. The prototype is defined as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed - for the manual address set by Ip6ConfigSetMaunualAddress. + for the manual address set by Ip6ConfigSetManualAddress. @param[in] IsDadPassed If TRUE, Duplicate Address Detection passed. @param[in] TargetAddress The tentative IPv6 address to be checked. @@ -776,6 +818,10 @@ Ip6ManualAddrDadCallback ( Item = &Instance->DataItem[Ip6ConfigDataTypeManualAddress]; ManualAddr = NULL; + if (Item->DataSize == 0) { + return; + } + for (Index = 0; Index < Item->DataSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS); Index++) { // // Find the original tag used to place into the NET_MAP. @@ -884,7 +930,7 @@ Ip6ManualAddrDadCallback ( **/ EFI_STATUS -Ip6ConfigSetMaunualAddress ( +Ip6ConfigSetManualAddress ( IN IP6_CONFIG_INSTANCE *Instance, IN UINTN DataSize, IN VOID *Data @@ -907,10 +953,26 @@ Ip6ConfigSetMaunualAddress ( 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; } @@ -918,239 +980,302 @@ Ip6ConfigSetMaunualAddress ( 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++; } + } - 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); + + 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; + // + // Artificially mark this address passed DAD be'coz it is already in use. + // + Ip6ManualAddrDadCallback (TRUE, &NewAddress->Address, Instance); + } else { // - // Save the prefix length. + // 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; @@ -1198,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; } @@ -1206,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; } /** @@ -1319,7 +1453,6 @@ Ip6ConfigSetDnsServer ( { UINTN OldIndex; UINTN NewIndex; - UINTN Index1; EFI_IPv6_ADDRESS *OldDns; EFI_IPv6_ADDRESS *NewDns; UINTN OldDnsCount; @@ -1328,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; } @@ -1336,80 +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. - // - FreePool (Tmp); - return EFI_INVALID_PARAMETER; + if (NewDnsCount != OldDnsCount) { + Tmp = AllocatePool (DataSize); + if (Tmp == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } else { + Tmp = NULL; } - for (Index1 = NewIndex + 1; Index1 < NewDnsCount; Index1++) { - if (EFI_IP6_EQUAL (NewDns + NewIndex, NewDns + Index1)) { - FreePool (Tmp); + for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) { + + if (!NetIp6IsValidUnicast (NewDns + NewIndex)) { + // + // The dns server address must be unicast. + // + if (Tmp != NULL) { + FreePool (Tmp); + } return EFI_INVALID_PARAMETER; } - } - - 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 (OneAdded) { // - // If found break out. + // If any address in the new setting is not in the old settings, skip the + // comparision below. // - break; + continue; } - } - if (OldIndex == OldDnsCount) { - OneAdded = TRUE; + 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; } /** @@ -1426,11 +1573,12 @@ Ip6ConfigInitIfInfo ( OUT EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo ) { - IfInfo->Name[0] = L'e'; - IfInfo->Name[1] = L't'; - IfInfo->Name[2] = L'h'; - IfInfo->Name[3] = (CHAR16) (L'0' + IpSb->Ip6ConfigInstance.IfIndex); - IfInfo->Name[4] = 0; + UnicodeSPrint ( + IfInfo->Name, + sizeof (IfInfo->Name), + L"eth%d", + IpSb->Ip6ConfigInstance.IfIndex + ); IfInfo->IfType = IpSb->SnpMode.IfType; IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize; @@ -1499,7 +1647,7 @@ Ip6ConfigParseDhcpReply ( CopyMem (&OpCode, &OptList[Index]->OpCode, sizeof (OpCode)); OpCode = NTOHS (OpCode); - if (OpCode == IP6_CONFIG_DHCP6_OPTION_DNS_SERVERS) { + if (OpCode == DHCP6_OPT_DNS_SERVERS) { CopyMem (&Length, &OptList[Index]->OpLen, sizeof (Length)); Length = NTOHS (Length); @@ -1817,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 @@ -1847,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; } @@ -2200,7 +2347,7 @@ Ip6ConfigInitInstance ( DataItem->SetData = Ip6ConfigSetPolicy; DataItem->Data.Ptr = &Instance->Policy; DataItem->DataSize = sizeof (Instance->Policy); - Instance->Policy = Ip6ConfigPolicyAutomatic; + Instance->Policy = Ip6ConfigPolicyManual; SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED); DataItem = &Instance->DataItem[Ip6ConfigDataTypeDupAddrDetectTransmits]; @@ -2211,7 +2358,7 @@ Ip6ConfigInitInstance ( SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED); DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress]; - DataItem->SetData = Ip6ConfigSetMaunualAddress; + DataItem->SetData = Ip6ConfigSetManualAddress; DataItem->Status = EFI_NOT_FOUND; DataItem = &Instance->DataItem[Ip6ConfigDataTypeGateway];