/** @file\r
The implementation of EFI IPv6 Configuration Protocol.\r
\r
- Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
IN EFI_IP6_CONFIG_POLICY NewPolicy\r
)\r
{\r
- LIST_ENTRY *Entry;\r
- LIST_ENTRY *Entry2;\r
- LIST_ENTRY *Next;\r
- IP6_INTERFACE *IpIf;\r
- IP6_DAD_ENTRY *DadEntry;\r
-\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Entry2;\r
+ LIST_ENTRY *Next;\r
+ IP6_INTERFACE *IpIf;\r
+ IP6_DAD_ENTRY *DadEntry;\r
+ IP6_DELAY_JOIN_LIST *DelayNode;\r
+ IP6_ADDRESS_INFO *AddrInfo;\r
+ IP6_PROTOCOL *Instance;\r
+ BOOLEAN Recovery;\r
+\r
+ Recovery = FALSE;\r
+ \r
//\r
// Currently there are only two policies: Manual and Automatic. Regardless of\r
// what transition is going on, i.e., Manual -> Automatic and Automatic ->\r
);\r
}\r
\r
- //\r
- // All IPv6 children that use global unicast address as it's source address\r
- // should be destryoed now. The survivers are those use the link-local address\r
- // or the unspecified address as the source address.\r
- // TODO: Conduct a check here.\r
- Ip6RemoveAddr (\r
- IpSb,\r
- &IpSb->DefaultInterface->AddressList,\r
- &IpSb->DefaultInterface->AddressCount,\r
- NULL,\r
- 0\r
- );\r
+ if (!IsListEmpty (&IpSb->DefaultInterface->AddressList) && IpSb->DefaultInterface->AddressCount > 0) {\r
+ // \r
+ // If any IPv6 children (Instance) in configured state and use global unicast address, it will be \r
+ // destroyed in Ip6RemoveAddr() function later. Then, the upper layer driver's Stop() function will be \r
+ // called, which may break the upper layer network stacks. So, the driver should take the responsibility \r
+ // for the recovery by using ConnectController() after Ip6RemoveAddr(). \r
+ // Here, just check whether need to recover the upper layer network stacks later.\r
+ //\r
+ NET_LIST_FOR_EACH (Entry, &IpSb->DefaultInterface->AddressList) { \r
+ AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);\r
+ if (!IsListEmpty (&IpSb->Children)) {\r
+ NET_LIST_FOR_EACH (Entry2, &IpSb->Children) {\r
+ Instance = NET_LIST_USER_STRUCT_S (Entry2, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);\r
+ if ((Instance->State == IP6_STATE_CONFIGED) && EFI_IP6_EQUAL (&Instance->ConfigData.StationAddress, &AddrInfo->Address)) {\r
+ Recovery = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ //\r
+ // All IPv6 children that use global unicast address as it's source address\r
+ // should be destroyed now. The survivers are those use the link-local address\r
+ // or the unspecified address as the source address.\r
+ // TODO: Conduct a check here.\r
+ Ip6RemoveAddr (\r
+ IpSb,\r
+ &IpSb->DefaultInterface->AddressList,\r
+ &IpSb->DefaultInterface->AddressCount,\r
+ NULL,\r
+ 0\r
+ );\r
+ \r
+ if (IpSb->Controller != NULL && Recovery) {\r
+ //\r
+ // ConnectController() to recover the upper layer network stacks.\r
+ //\r
+ gBS->ConnectController (IpSb->Controller, NULL, NULL, TRUE);\r
+ }\r
+ }\r
+\r
\r
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
//\r
- // remove all pending DAD entries for the global addresses.\r
+ // remove all pending delay node and DAD entries for the global addresses.\r
//\r
IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);\r
\r
+ NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DelayJoinList) {\r
+ DelayNode = NET_LIST_USER_STRUCT (Entry2, IP6_DELAY_JOIN_LIST, Link);\r
+ if (!NetIp6IsLinkLocalAddr (&DelayNode->AddressInfo->Address)) {\r
+ RemoveEntryList (&DelayNode->Link);\r
+ FreePool (DelayNode);\r
+ }\r
+ }\r
+\r
NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DupAddrDetectList) {\r
DadEntry = NET_LIST_USER_STRUCT_S (Entry2, IP6_DAD_ENTRY, Link, IP6_DAD_ENTRY_SIGNATURE);\r
\r
\r
if (NewPolicy == Ip6ConfigPolicyAutomatic) {\r
//\r
- // Set paramters to trigger router solicitation sending in timer handler.\r
+ // Set parameters to trigger router solicitation sending in timer handler.\r
//\r
IpSb->RouterAdvertiseReceived = FALSE;\r
IpSb->SolicitTimer = IP6_MAX_RTR_SOLICITATIONS;\r
//\r
IpSb->Ticks = (UINT32) IP6_GET_TICKS (IP6_ONE_SECOND_IN_MS);\r
}\r
-\r
}\r
\r
/**\r
// with DNS SERVERS.\r
//\r
Oro = (EFI_DHCP6_PACKET_OPTION *) OptBuf;\r
- Oro->OpCode = HTONS (IP6_CONFIG_DHCP6_OPTION_ORO);\r
+ Oro->OpCode = HTONS (DHCP6_OPT_ORO);\r
Oro->OpLen = HTONS (2);\r
- *((UINT16 *) &Oro->Data[0]) = HTONS (IP6_CONFIG_DHCP6_OPTION_DNS_SERVERS);\r
+ *((UINT16 *) &Oro->Data[0]) = HTONS (DHCP6_OPT_DNS_SERVERS);\r
OptList[0] = Oro;\r
\r
Status = EFI_SUCCESS;\r
\r
return EFI_ABORTED;\r
} else {\r
-\r
- if (NewPolicy == Ip6ConfigPolicyAutomatic) {\r
- //\r
- // Clean the ManualAddress, Gateway and DnsServers, shrink the variable\r
- // data size, and fire up all the related events.\r
- //\r
- DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];\r
- if (DataItem->Data.Ptr != NULL) {\r
- FreePool (DataItem->Data.Ptr);\r
- }\r
- DataItem->Data.Ptr = NULL;\r
- DataItem->DataSize = 0;\r
- DataItem->Status = EFI_NOT_FOUND;\r
- NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL);\r
-\r
- DataItem = &Instance->DataItem[Ip6ConfigDataTypeGateway];\r
- if (DataItem->Data.Ptr != NULL) {\r
- FreePool (DataItem->Data.Ptr);\r
- }\r
- DataItem->Data.Ptr = NULL;\r
- DataItem->DataSize = 0;\r
- DataItem->Status = EFI_NOT_FOUND;\r
- NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL);\r
-\r
- DataItem = &Instance->DataItem[Ip6ConfigDataTypeDnsServer];\r
- DataItem->Data.Ptr = NULL;\r
- DataItem->DataSize = 0;\r
- DataItem->Status = EFI_NOT_FOUND;\r
- NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL);\r
- } else {\r
+ //\r
+ // Clean the ManualAddress, Gateway and DnsServers, shrink the variable\r
+ // data size, and fire up all the related events.\r
+ //\r
+ DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ FreePool (DataItem->Data.Ptr);\r
+ }\r
+ DataItem->Data.Ptr = NULL;\r
+ DataItem->DataSize = 0;\r
+ DataItem->Status = EFI_NOT_FOUND;\r
+ NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL);\r
+\r
+ DataItem = &Instance->DataItem[Ip6ConfigDataTypeGateway];\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ FreePool (DataItem->Data.Ptr);\r
+ }\r
+ DataItem->Data.Ptr = NULL;\r
+ DataItem->DataSize = 0;\r
+ DataItem->Status = EFI_NOT_FOUND;\r
+ NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL);\r
+\r
+ DataItem = &Instance->DataItem[Ip6ConfigDataTypeDnsServer];\r
+ DataItem->Data.Ptr = NULL;\r
+ DataItem->DataSize = 0;\r
+ DataItem->Status = EFI_NOT_FOUND;\r
+ NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL);\r
+ \r
+ if (NewPolicy == Ip6ConfigPolicyManual) {\r
//\r
// The policy is changed from automatic to manual. Stop the DHCPv6 process\r
// and destroy the DHCPv6 child.\r
/**\r
The callback function for Ip6SetAddr. The prototype is defined\r
as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed\r
- for the manual address set by Ip6ConfigSetMaunualAddress.\r
+ for the manual address set by Ip6ConfigSetManualAddress.\r
\r
@param[in] IsDadPassed If TRUE, Duplicate Address Detection passed.\r
@param[in] TargetAddress The tentative IPv6 address to be checked.\r
Item = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];\r
ManualAddr = NULL;\r
\r
+ if (Item->DataSize == 0) {\r
+ return;\r
+ }\r
+\r
for (Index = 0; Index < Item->DataSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS); Index++) {\r
//\r
// Find the original tag used to place into the NET_MAP.\r
\r
**/\r
EFI_STATUS\r
-Ip6ConfigSetMaunualAddress (\r
+Ip6ConfigSetManualAddress (\r
IN IP6_CONFIG_INSTANCE *Instance,\r
IN UINTN DataSize,\r
IN VOID *Data\r
IP6_PREFIX_LIST_ENTRY *PrefixEntry;\r
EFI_STATUS Status;\r
BOOLEAN IsUpdated;\r
+ LIST_ENTRY *Next;\r
+ IP6_DAD_ENTRY *DadEntry;\r
+ IP6_DELAY_JOIN_LIST *DelayNode;\r
+\r
+ NewAddress = NULL;\r
+ TmpAddress = NULL;\r
+ CurrentAddrInfo = NULL;\r
+ Copy = NULL;\r
+ Entry = NULL;\r
+ Entry2 = NULL;\r
+ IpIf = NULL;\r
+ PrefixEntry = NULL;\r
+ Next = NULL;\r
+ DadEntry = NULL;\r
+ DelayNode = NULL;\r
+ Status = EFI_SUCCESS;\r
\r
ASSERT (Instance->DataItem[Ip6ConfigDataTypeManualAddress].Status != EFI_NOT_READY);\r
\r
- if (((DataSize % sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)) != 0) || (DataSize == 0)) {\r
+ if ((DataSize != 0) && ((DataSize % sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)) != 0)) {\r
return EFI_BAD_BUFFER_SIZE;\r
}\r
\r
return EFI_WRITE_PROTECTED;\r
}\r
\r
- NewAddressCount = DataSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);\r
- NewAddress = (EFI_IP6_CONFIG_MANUAL_ADDRESS *) Data;\r
+ IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);\r
\r
- for (Index1 = 0; Index1 < NewAddressCount; Index1++, NewAddress++) {\r
+ DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];\r
\r
- if (NetIp6IsLinkLocalAddr (&NewAddress->Address) ||\r
- !NetIp6IsValidUnicast (&NewAddress->Address) ||\r
- (NewAddress->PrefixLength > 128)\r
- ) {\r
- //\r
- // make sure the IPv6 address is unicast and not link-local address &&\r
- // the prefix length is valid.\r
- //\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ if (Data != NULL && DataSize != 0) {\r
+ NewAddressCount = DataSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);\r
+ NewAddress = (EFI_IP6_CONFIG_MANUAL_ADDRESS *) Data;\r
\r
- TmpAddress = NewAddress + 1;\r
- for (Index2 = Index1 + 1; Index2 < NewAddressCount; Index2++, TmpAddress++) {\r
- //\r
- // Any two addresses in the array can't be equal.\r
- //\r
- if (EFI_IP6_EQUAL (&TmpAddress->Address, &NewAddress->Address)) {\r
+ for (Index1 = 0; Index1 < NewAddressCount; Index1++, NewAddress++) {\r
\r
+ if (NetIp6IsLinkLocalAddr (&NewAddress->Address) ||\r
+ !NetIp6IsValidUnicast (&NewAddress->Address) ||\r
+ (NewAddress->PrefixLength > 128)\r
+ ) {\r
+ //\r
+ // make sure the IPv6 address is unicast and not link-local address &&\r
+ // the prefix length is valid.\r
+ //\r
return EFI_INVALID_PARAMETER;\r
}\r
+\r
+ TmpAddress = NewAddress + 1;\r
+ for (Index2 = Index1 + 1; Index2 < NewAddressCount; Index2++, TmpAddress++) {\r
+ //\r
+ // Any two addresses in the array can't be equal.\r
+ //\r
+ if (EFI_IP6_EQUAL (&TmpAddress->Address, &NewAddress->Address)) {\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
}\r
- }\r
\r
- IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);\r
+ //\r
+ // Build the current source address list.\r
+ //\r
+ InitializeListHead (&CurrentSourceList);\r
+ CurrentSourceCount = 0;\r
\r
- //\r
- // Build the current source address list.\r
- //\r
- InitializeListHead (&CurrentSourceList);\r
- CurrentSourceCount = 0;\r
+ NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
+ IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);\r
\r
- NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
- IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);\r
+ NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {\r
+ CurrentAddrInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);\r
\r
- NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {\r
- CurrentAddrInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);\r
+ Copy = AllocateCopyPool (sizeof (IP6_ADDRESS_INFO), CurrentAddrInfo);\r
+ if (Copy == NULL) {\r
+ break;\r
+ }\r
\r
- Copy = AllocateCopyPool (sizeof (IP6_ADDRESS_INFO), CurrentAddrInfo);\r
- if (Copy == NULL) {\r
- break;\r
+ InsertTailList (&CurrentSourceList, &Copy->Link);\r
+ CurrentSourceCount++;\r
}\r
+ }\r
+\r
+ //\r
+ // Update the value... a long journey starts\r
+ //\r
+ NewAddress = AllocateCopyPool (DataSize, Data);\r
+ if (NewAddress == NULL) {\r
+ Ip6RemoveAddr (NULL, &CurrentSourceList, &CurrentSourceCount, NULL, 0);\r
+\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
- InsertTailList (&CurrentSourceList, &Copy->Link);\r
- CurrentSourceCount++;\r
+ //\r
+ // Store the new data, and init the DataItem status to EFI_NOT_READY because\r
+ // we may have an asynchronous configuration process.\r
+ //\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ FreePool (DataItem->Data.Ptr);\r
}\r
- }\r
+ DataItem->Data.Ptr = NewAddress;\r
+ DataItem->DataSize = DataSize;\r
+ DataItem->Status = EFI_NOT_READY;\r
\r
- //\r
- // Update the value... a long journey starts\r
- //\r
- NewAddress = AllocateCopyPool (DataSize, Data);\r
- if (NewAddress == NULL) {\r
- Ip6RemoveAddr (NULL, &CurrentSourceList, &CurrentSourceCount, NULL, 0);\r
+ //\r
+ // Trigger DAD, it's an asynchronous process.\r
+ //\r
+ IsUpdated = FALSE;\r
\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ for (Index1 = 0; Index1 < NewAddressCount; Index1++, NewAddress++) {\r
+ if (Ip6IsOneOfSetAddress (IpSb, &NewAddress->Address, NULL, &CurrentAddrInfo)) {\r
+ ASSERT (CurrentAddrInfo != NULL);\r
+ //\r
+ // Remove this already existing source address from the CurrentSourceList\r
+ // built before.\r
+ //\r
+ Ip6RemoveAddr (\r
+ NULL,\r
+ &CurrentSourceList,\r
+ &CurrentSourceCount,\r
+ &CurrentAddrInfo->Address,\r
+ 128\r
+ );\r
\r
- //\r
- // Store the new data, and init the DataItem status to EFI_NOT_READY because\r
- // we may have an asynchronous configuration process.\r
- //\r
- DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];\r
- if (DataItem->Data.Ptr != NULL) {\r
- FreePool (DataItem->Data.Ptr);\r
- }\r
- DataItem->Data.Ptr = NewAddress;\r
- DataItem->DataSize = DataSize;\r
- DataItem->Status = EFI_NOT_READY;\r
+ //\r
+ // If the new address's prefix length is not specified, just use the previous configured\r
+ // prefix length for this address.\r
+ //\r
+ if (NewAddress->PrefixLength == 0) {\r
+ NewAddress->PrefixLength = CurrentAddrInfo->PrefixLength;\r
+ }\r
\r
- //\r
- // Trigger DAD, it's an asynchronous process.\r
- //\r
- IsUpdated = FALSE;\r
+ //\r
+ // This manual address is already in use, see whether prefix length is changed.\r
+ //\r
+ if (NewAddress->PrefixLength != CurrentAddrInfo->PrefixLength) {\r
+ //\r
+ // Remove the on-link prefix table, the route entry will be removed\r
+ // implicitly.\r
+ //\r
+ PrefixEntry = Ip6FindPrefixListEntry (\r
+ IpSb,\r
+ TRUE,\r
+ CurrentAddrInfo->PrefixLength,\r
+ &CurrentAddrInfo->Address\r
+ );\r
+ if (PrefixEntry != NULL) {\r
+ Ip6DestroyPrefixListEntry (IpSb, PrefixEntry, TRUE, FALSE);\r
+ }\r
\r
- for (Index1 = 0; Index1 < NewAddressCount; Index1++, NewAddress++) {\r
- if (Ip6IsOneOfSetAddress (IpSb, &NewAddress->Address, NULL, &CurrentAddrInfo)) {\r
- ASSERT (CurrentAddrInfo != NULL);\r
- //\r
- // Remove this already existing source address from the CurrentSourceList\r
- // built before.\r
- //\r
- Ip6RemoveAddr (\r
- NULL,\r
- &CurrentSourceList,\r
- &CurrentSourceCount,\r
- &CurrentAddrInfo->Address,\r
- 128\r
- );\r
+ //\r
+ // Save the prefix length.\r
+ //\r
+ CurrentAddrInfo->PrefixLength = NewAddress->PrefixLength;\r
+ IsUpdated = TRUE;\r
+ }\r
\r
- //\r
- // This manual address is already in use, see whether prefix length is changed.\r
- //\r
- if (NewAddress->PrefixLength != CurrentAddrInfo->PrefixLength) {\r
//\r
- // Remove the on-link prefix table, the route entry will be removed\r
- // implicitly.\r
+ // create a new on-link prefix entry.\r
//\r
PrefixEntry = Ip6FindPrefixListEntry (\r
IpSb,\r
TRUE,\r
- CurrentAddrInfo->PrefixLength,\r
- &CurrentAddrInfo->Address\r
+ NewAddress->PrefixLength,\r
+ &NewAddress->Address\r
);\r
- if (PrefixEntry != NULL) {\r
- Ip6DestroyPrefixListEntry (IpSb, PrefixEntry, TRUE, FALSE);\r
+ if (PrefixEntry == NULL) {\r
+ Ip6CreatePrefixListEntry (\r
+ IpSb,\r
+ TRUE,\r
+ (UINT32) IP6_INFINIT_LIFETIME,\r
+ (UINT32) IP6_INFINIT_LIFETIME,\r
+ NewAddress->PrefixLength,\r
+ &NewAddress->Address\r
+ );\r
}\r
\r
+ CurrentAddrInfo->IsAnycast = NewAddress->IsAnycast;\r
+ //\r
+ // Artificially mark this address passed DAD be'coz it is already in use.\r
+ //\r
+ Ip6ManualAddrDadCallback (TRUE, &NewAddress->Address, Instance);\r
+ } else {\r
//\r
- // Save the prefix length.\r
+ // A new address.\r
//\r
- CurrentAddrInfo->PrefixLength = NewAddress->PrefixLength;\r
IsUpdated = TRUE;\r
+\r
+ //\r
+ // Set the new address, this will trigger DAD and activate the address if\r
+ // DAD succeeds.\r
+ //\r
+ Ip6SetAddress (\r
+ IpSb->DefaultInterface,\r
+ &NewAddress->Address,\r
+ NewAddress->IsAnycast,\r
+ NewAddress->PrefixLength,\r
+ (UINT32) IP6_INFINIT_LIFETIME,\r
+ (UINT32) IP6_INFINIT_LIFETIME,\r
+ Ip6ManualAddrDadCallback,\r
+ Instance\r
+ );\r
}\r
+ }\r
+\r
+ //\r
+ // Check the CurrentSourceList, it now contains those addresses currently in\r
+ // use and will be removed.\r
+ //\r
+ IpIf = IpSb->DefaultInterface;\r
+\r
+ while (!IsListEmpty (&CurrentSourceList)) {\r
+ IsUpdated = TRUE;\r
+\r
+ CurrentAddrInfo = NET_LIST_HEAD (&CurrentSourceList, IP6_ADDRESS_INFO, Link);\r
\r
//\r
- // create a new on-link prefix entry.\r
+ // This local address is going to be removed, the IP instances that are\r
+ // currently using it will be destroyed.\r
+ //\r
+ Ip6RemoveAddr (\r
+ IpSb,\r
+ &IpIf->AddressList,\r
+ &IpIf->AddressCount,\r
+ &CurrentAddrInfo->Address,\r
+ 128\r
+ );\r
+\r
+ //\r
+ // Remove the on-link prefix table, the route entry will be removed\r
+ // implicitly.\r
//\r
PrefixEntry = Ip6FindPrefixListEntry (\r
IpSb,\r
TRUE,\r
- NewAddress->PrefixLength,\r
- &NewAddress->Address\r
+ CurrentAddrInfo->PrefixLength,\r
+ &CurrentAddrInfo->Address\r
);\r
- if (PrefixEntry == NULL) {\r
- Ip6CreatePrefixListEntry (\r
- IpSb,\r
- TRUE,\r
- (UINT32) IP6_INFINIT_LIFETIME,\r
- (UINT32) IP6_INFINIT_LIFETIME,\r
- NewAddress->PrefixLength,\r
- &NewAddress->Address\r
- );\r
+ if (PrefixEntry != NULL) {\r
+ Ip6DestroyPrefixListEntry (IpSb, PrefixEntry, TRUE, FALSE);\r
}\r
\r
- CurrentAddrInfo->IsAnycast = NewAddress->IsAnycast;\r
- //\r
- // Artificially mark this address passed DAD be'coz it is already in use.\r
- //\r
- Ip6ManualAddrDadCallback (TRUE, &NewAddress->Address, Instance);\r
+ RemoveEntryList (&CurrentAddrInfo->Link);\r
+ FreePool (CurrentAddrInfo);\r
+ }\r
+\r
+ if (IsUpdated) {\r
+ if (DataItem->Status == EFI_NOT_READY) {\r
+ //\r
+ // If DAD is disabled on this interface, the configuration process is\r
+ // actually synchronous, and the data item's status will be changed to\r
+ // the final status before we reach here, just check it.\r
+ //\r
+ Status = EFI_NOT_READY;\r
+ } else {\r
+ Status = EFI_SUCCESS;\r
+ }\r
} else {\r
//\r
- // A new address.\r
+ // No update is taken, reset the status to success and return EFI_ABORTED.\r
//\r
- IsUpdated = TRUE;\r
+ DataItem->Status = EFI_SUCCESS;\r
+ Status = EFI_ABORTED;\r
+ }\r
+ } else {\r
+ //\r
+ // DataSize is 0 and Data is NULL, clean up the manual address.\r
+ //\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ FreePool (DataItem->Data.Ptr);\r
+ }\r
+ DataItem->Data.Ptr = NULL;\r
+ DataItem->DataSize = 0;\r
+ DataItem->Status = EFI_NOT_FOUND;\r
\r
- //\r
- // Set the new address, this will trigger DAD and activate the address if\r
- // DAD succeeds.\r
- //\r
- Ip6SetAddress (\r
- IpSb->DefaultInterface,\r
- &NewAddress->Address,\r
- NewAddress->IsAnycast,\r
- NewAddress->PrefixLength,\r
+ Ip6CleanDefaultRouterList (IpSb);\r
+ Ip6CleanPrefixListTable (IpSb, &IpSb->OnlinkPrefix);\r
+ Ip6CleanPrefixListTable (IpSb, &IpSb->AutonomousPrefix);\r
+ Ip6CleanAssembleTable (&IpSb->Assemble);\r
+\r
+ if (IpSb->LinkLocalOk) {\r
+ Ip6CreatePrefixListEntry (\r
+ IpSb,\r
+ TRUE,\r
(UINT32) IP6_INFINIT_LIFETIME,\r
(UINT32) IP6_INFINIT_LIFETIME,\r
- Ip6ManualAddrDadCallback,\r
- Instance\r
+ IP6_LINK_LOCAL_PREFIX_LENGTH,\r
+ &IpSb->LinkLocalAddr\r
);\r
}\r
- }\r
\r
- //\r
- // Check the CurrentSourceList, it now contains those addresses currently in\r
- // use and will be removed.\r
- //\r
- IpIf = IpSb->DefaultInterface;\r
-\r
- while (!IsListEmpty (&CurrentSourceList)) {\r
- IsUpdated = TRUE;\r
-\r
- CurrentAddrInfo = NET_LIST_HEAD (&CurrentSourceList, IP6_ADDRESS_INFO, Link);\r
-\r
- //\r
- // This local address is going to be removed, the IP instances that are\r
- // currently using it will be destroyed.\r
- //\r
Ip6RemoveAddr (\r
IpSb,\r
- &IpIf->AddressList,\r
- &IpIf->AddressCount,\r
- &CurrentAddrInfo->Address,\r
- 128\r
+ &IpSb->DefaultInterface->AddressList,\r
+ &IpSb->DefaultInterface->AddressCount,\r
+ NULL,\r
+ 0\r
);\r
\r
- //\r
- // Remove the on-link prefix table, the route entry will be removed\r
- // implicitly.\r
- //\r
- PrefixEntry = Ip6FindPrefixListEntry (\r
- IpSb,\r
- TRUE,\r
- CurrentAddrInfo->PrefixLength,\r
- &CurrentAddrInfo->Address\r
- );\r
- if (PrefixEntry != NULL) {\r
- Ip6DestroyPrefixListEntry (IpSb, PrefixEntry, TRUE, FALSE);\r
- }\r
-\r
- RemoveEntryList (&CurrentAddrInfo->Link);\r
- FreePool (CurrentAddrInfo);\r
- }\r
-\r
- if (IsUpdated) {\r
- if (DataItem->Status == EFI_NOT_READY) {\r
+ NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
//\r
- // If DAD is disabled on this interface, the configuration process is\r
- // actually synchronous, and the data item's status will be changed to\r
- // the final status before we reach here, just check it.\r
+ // Remove all pending delay node and DAD entries for the global addresses.\r
//\r
- Status = EFI_NOT_READY;\r
- } else {\r
- Status = EFI_SUCCESS;\r
+ IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);\r
+\r
+ NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DelayJoinList) {\r
+ DelayNode = NET_LIST_USER_STRUCT (Entry2, IP6_DELAY_JOIN_LIST, Link);\r
+ if (!NetIp6IsLinkLocalAddr (&DelayNode->AddressInfo->Address)) {\r
+ RemoveEntryList (&DelayNode->Link);\r
+ FreePool (DelayNode);\r
+ }\r
+ }\r
+\r
+ NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DupAddrDetectList) {\r
+ DadEntry = NET_LIST_USER_STRUCT_S (Entry2, IP6_DAD_ENTRY, Link, IP6_DAD_ENTRY_SIGNATURE);\r
+\r
+ if (!NetIp6IsLinkLocalAddr (&DadEntry->AddressInfo->Address)) {\r
+ //\r
+ // Fail this DAD entry if the address is not link-local.\r
+ //\r
+ Ip6OnDADFinished (FALSE, IpIf, DadEntry);\r
+ }\r
+ }\r
}\r
- } else {\r
- //\r
- // No update is taken, reset the status to success and return EFI_ABORTED.\r
- //\r
- DataItem->Status = EFI_SUCCESS;\r
- Status = EFI_ABORTED;\r
}\r
\r
return Status;\r
IP6_DEFAULT_ROUTER *DefaultRouter;\r
VOID *Tmp;\r
\r
- if ((DataSize % sizeof (EFI_IPv6_ADDRESS) != 0) || (DataSize == 0)) {\r
+ OldGateway = NULL;\r
+ NewGateway = NULL;\r
+ Item = NULL;\r
+ DefaultRouter = NULL;\r
+ Tmp = NULL;\r
+ OneRemoved = FALSE;\r
+ OneAdded = FALSE;\r
+\r
+ if ((DataSize != 0) && (DataSize % sizeof (EFI_IPv6_ADDRESS) != 0)) {\r
return EFI_BAD_BUFFER_SIZE;\r
}\r
\r
return EFI_WRITE_PROTECTED;\r
}\r
\r
- NewGateway = (EFI_IPv6_ADDRESS *) Data;\r
- NewGatewayCount = DataSize / sizeof (EFI_IPv6_ADDRESS);\r
- for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
-\r
- if (!NetIp6IsValidUnicast (NewGateway + Index1)) {\r
-\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {\r
- if (EFI_IP6_EQUAL (NewGateway + Index1, NewGateway + Index2)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
- }\r
-\r
IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);\r
Item = &Instance->DataItem[Ip6ConfigDataTypeGateway];\r
OldGateway = Item->Data.Gateway;\r
OldGatewayCount = Item->DataSize / sizeof (EFI_IPv6_ADDRESS);\r
- OneRemoved = FALSE;\r
- OneAdded = FALSE;\r
-\r
- if (NewGatewayCount != OldGatewayCount) {\r
- Tmp = AllocatePool (DataSize);\r
- if (Tmp == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- } else {\r
- Tmp = NULL;\r
- }\r
\r
for (Index1 = 0; Index1 < OldGatewayCount; Index1++) {\r
//\r
- // Find the gateways that are no long in the new setting and remove them.\r
+ // Remove this default router.\r
//\r
- for (Index2 = 0; Index2 < NewGatewayCount; Index2++) {\r
- if (EFI_IP6_EQUAL (OldGateway + Index1, NewGateway + Index2)) {\r
- OneRemoved = TRUE;\r
- break;\r
+ DefaultRouter = Ip6FindDefaultRouter (IpSb, OldGateway + Index1);\r
+ if (DefaultRouter != NULL) {\r
+ Ip6DestroyDefaultRouter (IpSb, DefaultRouter);\r
+ OneRemoved = TRUE;\r
+ }\r
+ }\r
+\r
+ if (Data != NULL && DataSize != 0) {\r
+ NewGateway = (EFI_IPv6_ADDRESS *) Data;\r
+ NewGatewayCount = DataSize / sizeof (EFI_IPv6_ADDRESS);\r
+ for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
+\r
+ if (!NetIp6IsValidUnicast (NewGateway + Index1)) {\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {\r
+ if (EFI_IP6_EQUAL (NewGateway + Index1, NewGateway + Index2)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
}\r
}\r
\r
- if (Index2 == NewGatewayCount) {\r
- //\r
- // Remove this default router.\r
- //\r
- DefaultRouter = Ip6FindDefaultRouter (IpSb, OldGateway + Index1);\r
- if (DefaultRouter != NULL) {\r
- Ip6DestroyDefaultRouter (IpSb, DefaultRouter);\r
+ if (NewGatewayCount != OldGatewayCount) {\r
+ Tmp = AllocatePool (DataSize);\r
+ if (Tmp == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
+ } else {\r
+ Tmp = NULL;\r
}\r
- }\r
\r
- for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
+ for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
\r
- DefaultRouter = Ip6FindDefaultRouter (IpSb, NewGateway + Index1);\r
- if (DefaultRouter == NULL) {\r
- Ip6CreateDefaultRouter (IpSb, NewGateway + Index1, IP6_INF_ROUTER_LIFETIME);\r
- OneAdded = TRUE;\r
+ DefaultRouter = Ip6FindDefaultRouter (IpSb, NewGateway + Index1);\r
+ if (DefaultRouter == NULL) {\r
+ Ip6CreateDefaultRouter (IpSb, NewGateway + Index1, IP6_INF_ROUTER_LIFETIME);\r
+ OneAdded = TRUE;\r
+ }\r
}\r
- }\r
\r
- if (!OneRemoved && !OneAdded) {\r
- Item->Status = EFI_SUCCESS;\r
- return EFI_ABORTED;\r
- } else {\r
+ if (!OneRemoved && !OneAdded) {\r
+ Item->Status = EFI_SUCCESS;\r
+ return EFI_ABORTED;\r
+ } else {\r
\r
- if (Tmp != NULL) {\r
- if (Item->Data.Ptr != NULL) {\r
- FreePool (Item->Data.Ptr);\r
+ if (Tmp != NULL) {\r
+ if (Item->Data.Ptr != NULL) {\r
+ FreePool (Item->Data.Ptr);\r
+ }\r
+ Item->Data.Ptr = Tmp;\r
}\r
- Item->Data.Ptr = Tmp;\r
- }\r
\r
- CopyMem (Item->Data.Ptr, Data, DataSize);\r
- Item->DataSize = DataSize;\r
- Item->Status = EFI_SUCCESS;\r
- return EFI_SUCCESS;\r
+ CopyMem (Item->Data.Ptr, Data, DataSize);\r
+ Item->DataSize = DataSize;\r
+ Item->Status = EFI_SUCCESS;\r
+ return EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ //\r
+ // DataSize is 0 and Data is NULL, clean up the Gateway address.\r
+ //\r
+ if (Item->Data.Ptr != NULL) {\r
+ FreePool (Item->Data.Ptr);\r
+ }\r
+ Item->Data.Ptr = NULL;\r
+ Item->DataSize = 0;\r
+ Item->Status = EFI_NOT_FOUND;\r
}\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
{\r
UINTN OldIndex;\r
UINTN NewIndex;\r
- UINTN Index1;\r
EFI_IPv6_ADDRESS *OldDns;\r
EFI_IPv6_ADDRESS *NewDns;\r
UINTN OldDnsCount;\r
BOOLEAN OneAdded;\r
VOID *Tmp;\r
\r
- if ((DataSize % sizeof (EFI_IPv6_ADDRESS) != 0) || (DataSize == 0)) {\r
+ OldDns = NULL;\r
+ NewDns = NULL;\r
+ Item = NULL;\r
+ Tmp = NULL;\r
+\r
+ if ((DataSize != 0) && (DataSize % sizeof (EFI_IPv6_ADDRESS) != 0)) {\r
return EFI_BAD_BUFFER_SIZE;\r
}\r
\r
return EFI_WRITE_PROTECTED;\r
}\r
\r
- Item = &Instance->DataItem[Ip6ConfigDataTypeDnsServer];\r
- NewDns = (EFI_IPv6_ADDRESS *) Data;\r
- OldDns = Item->Data.DnsServers;\r
- NewDnsCount = DataSize / sizeof (EFI_IPv6_ADDRESS);\r
- OldDnsCount = Item->DataSize / sizeof (EFI_IPv6_ADDRESS);\r
- OneAdded = FALSE;\r
-\r
- if (NewDnsCount != OldDnsCount) {\r
- Tmp = AllocatePool (DataSize);\r
- if (Tmp == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- } else {\r
- Tmp = NULL;\r
- }\r
+ Item = &Instance->DataItem[Ip6ConfigDataTypeDnsServer];\r
\r
- for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {\r
+ if (Data != NULL && DataSize != 0) {\r
+ NewDns = (EFI_IPv6_ADDRESS *) Data;\r
+ OldDns = Item->Data.DnsServers;\r
+ NewDnsCount = DataSize / sizeof (EFI_IPv6_ADDRESS);\r
+ OldDnsCount = Item->DataSize / sizeof (EFI_IPv6_ADDRESS);\r
+ OneAdded = FALSE;\r
\r
- if (!NetIp6IsValidUnicast (NewDns + NewIndex)) {\r
- //\r
- // The dns server address must be unicast.\r
- //\r
- FreePool (Tmp);\r
- return EFI_INVALID_PARAMETER;\r
+ if (NewDnsCount != OldDnsCount) {\r
+ Tmp = AllocatePool (DataSize);\r
+ if (Tmp == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ Tmp = NULL;\r
}\r
\r
- for (Index1 = NewIndex + 1; Index1 < NewDnsCount; Index1++) {\r
- if (EFI_IP6_EQUAL (NewDns + NewIndex, NewDns + Index1)) {\r
- FreePool (Tmp);\r
+ for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {\r
+\r
+ if (!NetIp6IsValidUnicast (NewDns + NewIndex)) {\r
+ //\r
+ // The dns server address must be unicast.\r
+ //\r
+ if (Tmp != NULL) {\r
+ FreePool (Tmp);\r
+ }\r
return EFI_INVALID_PARAMETER;\r
}\r
- }\r
-\r
- if (OneAdded) {\r
- //\r
- // If any address in the new setting is not in the old settings, skip the\r
- // comparision below.\r
- //\r
- continue;\r
- }\r
\r
- for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {\r
- if (EFI_IP6_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {\r
+ if (OneAdded) {\r
//\r
- // If found break out.\r
+ // If any address in the new setting is not in the old settings, skip the\r
+ // comparision below.\r
//\r
- break;\r
+ continue;\r
}\r
- }\r
\r
- if (OldIndex == OldDnsCount) {\r
- OneAdded = TRUE;\r
+ for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {\r
+ if (EFI_IP6_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {\r
+ //\r
+ // If found break out.\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (OldIndex == OldDnsCount) {\r
+ OneAdded = TRUE;\r
+ }\r
}\r
- }\r
\r
- if (!OneAdded && (DataSize == Item->DataSize)) {\r
+ if (!OneAdded && (DataSize == Item->DataSize)) {\r
+ //\r
+ // No new item is added and the size is the same.\r
+ //\r
+ Item->Status = EFI_SUCCESS;\r
+ return EFI_ABORTED;\r
+ } else {\r
+ if (Tmp != NULL) {\r
+ if (Item->Data.Ptr != NULL) {\r
+ FreePool (Item->Data.Ptr);\r
+ }\r
+ Item->Data.Ptr = Tmp;\r
+ }\r
+\r
+ CopyMem (Item->Data.Ptr, Data, DataSize);\r
+ Item->DataSize = DataSize;\r
+ Item->Status = EFI_SUCCESS;\r
+ }\r
+ } else {\r
//\r
- // No new item is added and the size is the same.\r
+ // DataSize is 0 and Data is NULL, clean up the DnsServer address. \r
//\r
- Item->Status = EFI_SUCCESS;\r
- return EFI_ABORTED;\r
- } else {\r
- if (Tmp != NULL) {\r
- if (Item->Data.Ptr != NULL) {\r
- FreePool (Item->Data.Ptr);\r
- }\r
- Item->Data.Ptr = Tmp;\r
+ if (Item->Data.Ptr != NULL) {\r
+ FreePool (Item->Data.Ptr);\r
}\r
-\r
- CopyMem (Item->Data.Ptr, Data, DataSize);\r
- Item->DataSize = DataSize;\r
- Item->Status = EFI_SUCCESS;\r
- return EFI_SUCCESS;\r
+ Item->Data.Ptr = NULL;\r
+ Item->DataSize = 0;\r
+ Item->Status = EFI_NOT_FOUND;\r
}\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
OUT EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo\r
)\r
{\r
- IfInfo->Name[0] = L'e';\r
- IfInfo->Name[1] = L't';\r
- IfInfo->Name[2] = L'h';\r
- IfInfo->Name[3] = (CHAR16) (L'0' + IpSb->Ip6ConfigInstance.IfIndex);\r
- IfInfo->Name[4] = 0;\r
+ UnicodeSPrint (\r
+ IfInfo->Name,\r
+ sizeof (IfInfo->Name),\r
+ L"eth%d",\r
+ IpSb->Ip6ConfigInstance.IfIndex\r
+ );\r
\r
IfInfo->IfType = IpSb->SnpMode.IfType;\r
IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize;\r
CopyMem (&OpCode, &OptList[Index]->OpCode, sizeof (OpCode));\r
OpCode = NTOHS (OpCode);\r
\r
- if (OpCode == IP6_CONFIG_DHCP6_OPTION_DNS_SERVERS) {\r
+ if (OpCode == DHCP6_OPT_DNS_SERVERS) {\r
CopyMem (&Length, &OptList[Index]->OpLen, sizeof (Length));\r
Length = NTOHS (Length);\r
\r
//\r
// Decline those duplicates.\r
//\r
- Instance->Dhcp6->Decline (\r
- Instance->Dhcp6,\r
- Instance->DeclineAddressCount,\r
- Instance->DeclineAddress\r
- );\r
+ if (Instance->Dhcp6 != NULL) {\r
+ Instance->Dhcp6->Decline (\r
+ Instance->Dhcp6,\r
+ Instance->DeclineAddressCount,\r
+ Instance->DeclineAddress\r
+ );\r
+ }\r
}\r
\r
if (Instance->DeclineAddress != NULL) {\r
network stack was set successfully.\r
@retval EFI_INVALID_PARAMETER One or more of the following are TRUE:\r
- This is NULL.\r
- - Data is NULL.\r
- - One or more fields in Data do not match the requirement of the\r
- data type indicated by DataType.\r
+ - One or more fields in Data and DataSizedo not match the \r
+ requirement of the data type indicated by DataType.\r
@retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified\r
configuration data cannot be set under the current policy.\r
@retval EFI_ACCESS_DENIED Another set operation on the specified configuration\r
IP6_CONFIG_INSTANCE *Instance;\r
IP6_SERVICE *IpSb;\r
\r
- if ((This == NULL) || (Data == NULL)) {\r
+ if ((This == NULL) || (Data == NULL && DataSize != 0) || (Data != NULL && DataSize == 0)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
DataItem->SetData = Ip6ConfigSetPolicy;\r
DataItem->Data.Ptr = &Instance->Policy;\r
DataItem->DataSize = sizeof (Instance->Policy);\r
- Instance->Policy = Ip6ConfigPolicyAutomatic;\r
+ Instance->Policy = Ip6ConfigPolicyManual;\r
SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);\r
\r
DataItem = &Instance->DataItem[Ip6ConfigDataTypeDupAddrDetectTransmits];\r
SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);\r
\r
DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];\r
- DataItem->SetData = Ip6ConfigSetMaunualAddress;\r
+ DataItem->SetData = Ip6ConfigSetManualAddress;\r
DataItem->Status = EFI_NOT_FOUND;\r
\r
DataItem = &Instance->DataItem[Ip6ConfigDataTypeGateway];\r