/** @file\r
The implementation of EFI IPv4 Configuration II Protocol.\r
\r
- Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
- (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
+ Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<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
IpSb->DefaultRouteTable = RouteTable;\r
Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
\r
- if (IpSb->State == IP4_SERVICE_CONFIGED) {\r
+ if (IpSb->State == IP4_SERVICE_CONFIGED || IpSb->State == IP4_SERVICE_STARTED) {\r
IpSb->State = IP4_SERVICE_UNSTARTED;\r
}\r
\r
// Start the dhcp configuration.\r
//\r
if (NewPolicy == Ip4Config2PolicyDhcp) {\r
- IpSb->Reconfig = TRUE;\r
Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);\r
}\r
\r
//\r
Count = 0;\r
\r
- for (Index = IP4_MASK_NUM - 1; Index >= 0; Index--) {\r
+ for (Index = IP4_MASK_MAX; Index >= 0; Index--) {\r
\r
NET_LIST_FOR_EACH (Entry, &(IpSb->DefaultRouteTable->RouteArea[Index])) {\r
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);\r
{\r
UINTN OldIndex;\r
UINTN NewIndex;\r
- UINTN Index1;\r
EFI_IPv4_ADDRESS *OldDns;\r
EFI_IPv4_ADDRESS *NewDns;\r
UINTN OldDnsCount;\r
\r
for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {\r
CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR));\r
-\r
- if (!NetIp4IsUnicast (NTOHL (DnsAddress), 0)) {\r
+ if (IP4_IS_UNSPECIFIED (NTOHL (DnsAddress)) || IP4_IS_LOCAL_BROADCAST (NTOHL (DnsAddress))) {\r
//\r
// The dns server address must be unicast.\r
//\r
- FreePool (Tmp);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- for (Index1 = NewIndex + 1; Index1 < NewDnsCount; Index1++) {\r
- if (EFI_IP4_EQUAL (NewDns + NewIndex, NewDns + Index1)) {\r
+ if (Tmp != NULL) {\r
FreePool (Tmp);\r
- return EFI_INVALID_PARAMETER;\r
}\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
if (OneAdded) {\r
//\r
// Look for DNS Server opcode (6).\r
//\r
- if (OptionList[Index]->OpCode == DHCP_TAG_DNS_SERVER) {\r
+ if (OptionList[Index]->OpCode == DHCP4_TAG_DNS_SERVER) {\r
if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) {\r
break;\r
}\r
\r
@param[in] Instance The IP4 config2 instance to configure\r
\r
- @retval EFI_SUCCESS The auto configuration is successfull started\r
+ @retval EFI_SUCCESS The auto configuration is successfully started\r
@retval Others Failed to start auto configuration.\r
\r
**/\r
// DHCP configuration to avoid problems if some DHCP client\r
// yields the control of this DHCP service to us.\r
//\r
- ParaList.Head.OpCode = DHCP_TAG_PARA_LIST;\r
+ ParaList.Head.OpCode = DHCP4_TAG_PARA_LIST;\r
ParaList.Head.Length = 3;\r
- ParaList.Head.Data[0] = DHCP_TAG_NETMASK;\r
- ParaList.Route = DHCP_TAG_ROUTER;\r
- ParaList.Dns = DHCP_TAG_DNS_SERVER;\r
+ ParaList.Head.Data[0] = DHCP4_TAG_NETMASK;\r
+ ParaList.Route = DHCP4_TAG_ROUTER;\r
+ ParaList.Dns = DHCP4_TAG_DNS_SERVER;\r
OptionList[0] = &ParaList.Head;\r
Dhcp4Mode.ConfigData.OptionCount = 1;\r
Dhcp4Mode.ConfigData.OptionList = OptionList;\r
IN VOID *Data OPTIONAL\r
)\r
{\r
-\r
IP4_SERVICE *IpSb;\r
UINTN Length;\r
IP4_CONFIG2_DATA_ITEM *Item;\r
}\r
\r
if (NewPolicy == Instance->Policy) {\r
- return EFI_ABORTED;\r
+ if (NewPolicy != Ip4Config2PolicyDhcp || Instance->DhcpSuccess) {\r
+ return EFI_ABORTED;\r
+ }\r
} else {\r
- if (NewPolicy == Ip4Config2PolicyDhcp) {\r
- //\r
- // The policy is changed from static to dhcp:\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[Ip4Config2DataTypeManualAddress];\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, Ip4Config2SignalEvent, NULL);\r
+ //\r
+ // The policy is changed. Clean the ManualAddress, Gateway and DnsServers, \r
+ // shrink the variable data size, and fire up all the related events.\r
+ //\r
+ DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\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, Ip4Config2SignalEvent, NULL);\r
\r
- DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];\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, Ip4Config2SignalEvent, NULL);\r
+ DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];\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, Ip4Config2SignalEvent, NULL);\r
\r
- DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\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, Ip4Config2SignalEvent, NULL);\r
+ DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\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, Ip4Config2SignalEvent, NULL);\r
+ \r
+ if (NewPolicy == Ip4Config2PolicyDhcp) {\r
+ SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_VOLATILE);\r
} else {\r
//\r
// The policy is changed from dhcp to static. Stop the DHCPv4 process\r
//\r
if (Instance->Dhcp4Event != NULL) {\r
gBS->CloseEvent (Instance->Dhcp4Event);\r
+ Instance->Dhcp4Event = NULL;\r
}\r
}\r
}\r
\r
NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data);\r
\r
+ StationAddress = EFI_NTOHL (NewAddress.Address);\r
+ SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);\r
+\r
+ if (NetGetMaskLength (SubnetMask) == IP4_MASK_NUM) {\r
+ return EFI_INVALID_PARAMETER;\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
DataItem->DataSize = DataSize;\r
DataItem->Status = EFI_NOT_READY;\r
\r
- StationAddress = EFI_NTOHL (NewAddress.Address);\r
- SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);\r
-\r
IpSb->Reconfig = TRUE;\r
Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_EXIT;\r
- } \r
\r
- DataItem->Status = EFI_SUCCESS; \r
+ DataItem->Status = Status; \r
\r
-ON_EXIT:\r
- if (EFI_ERROR (DataItem->Status)) {\r
+ if (EFI_ERROR (DataItem->Status) && DataItem->Status != EFI_NOT_READY) {\r
if (Ptr != NULL) {\r
FreePool (Ptr);\r
}\r
DataItem->Data.Ptr = NULL; \r
}\r
\r
- return EFI_SUCCESS;\r
+ return Status;\r
}\r
\r
/**\r
return EFI_WRITE_PROTECTED;\r
}\r
\r
+ IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
\r
NewGateway = (EFI_IPv4_ADDRESS *) Data;\r
NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS);\r
for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));\r
- \r
- if (!NetIp4IsUnicast (NTOHL (Gateway), 0)) {\r
\r
+ if ((IpSb->DefaultInterface->SubnetMask != 0) && \r
+ !NetIp4IsUnicast (NTOHL (Gateway), IpSb->DefaultInterface->SubnetMask)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
}\r
}\r
\r
- IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
OldGateway = DataItem->Data.Gateway;\r
OldGatewayCount = DataItem->DataSize / sizeof (EFI_IPv4_ADDRESS);\r
IN VOID *Data\r
)\r
{\r
+ IP4_CONFIG2_DATA_ITEM *Item;\r
+\r
+ Item = NULL;\r
+\r
if (Instance->Policy != Ip4Config2PolicyStatic) {\r
return EFI_WRITE_PROTECTED;\r
}\r
\r
+ Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
+\r
+ if (DATA_ATTRIB_SET (Item->Attribute, DATA_ATTRIB_VOLATILE)) {\r
+ REMOVE_DATA_ATTRIB (Item->Attribute, DATA_ATTRIB_VOLATILE);\r
+ }\r
+\r
return Ip4Config2SetDnsServerWorker (Instance, DataSize, Data);\r
}\r
\r
OUT EFI_IP4_CONFIG2_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->Ip4Config2Instance.IfIndex);\r
- IfInfo->Name[4] = 0;\r
+ UnicodeSPrint (\r
+ IfInfo->Name,\r
+ EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE,\r
+ L"eth%d",\r
+ IpSb->Ip4Config2Instance.IfIndex\r
+ );\r
\r
IfInfo->IfType = IpSb->SnpMode.IfType;\r
IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize;\r
DataItem->SetData = Ip4Config2SetPolicy;\r
DataItem->Data.Ptr = &Instance->Policy;\r
DataItem->DataSize = sizeof (Instance->Policy);\r
- Instance->Policy = Ip4Config2PolicyDhcp;\r
+ Instance->Policy = Ip4Config2PolicyStatic;\r
SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);\r
\r
DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
\r
//\r
// Try to read the config data from NV variable.\r
+ // If not found, write initialized config data into NV variable \r
+ // as a default config data.\r
//\r
Status = Ip4Config2ReadConfigData (IpSb->MacString, Instance);\r
if (Status == EFI_NOT_FOUND) {\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
-\r
- //\r
- // Try to set the configured parameter.\r
- //\r
- for (Index = Ip4Config2DataTypePolicy; Index < Ip4Config2DataTypeMaximum; Index++) {\r
- DataItem = &IpSb->Ip4Config2Instance.DataItem[Index];\r
- if (DataItem->Data.Ptr != NULL) {\r
- DataItem->SetData (\r
- &IpSb->Ip4Config2Instance,\r
- DataItem->DataSize,\r
- DataItem->Data.Ptr\r
- );\r
- }\r
- }\r
-\r
+ \r
Instance->Ip4Config2.SetData = EfiIp4Config2SetData;\r
Instance->Ip4Config2.GetData = EfiIp4Config2GetData;\r
Instance->Ip4Config2.RegisterDataNotify = EfiIp4Config2RegisterDataNotify;\r
//\r
if (Instance->Dhcp4Event != NULL) {\r
gBS->CloseEvent (Instance->Dhcp4Event);\r
+ Instance->Dhcp4Event = NULL;\r
}\r
\r
for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {\r
RemoveEntryList (&Instance->Link);\r
}\r
\r
+/**\r
+ The event handle for IP4 auto reconfiguration. The original default\r
+ interface and route table will be removed as the default.\r
+\r
+ @param[in] Context The IP4 service binding instance.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ip4AutoReconfigCallBackDpc (\r
+ IN VOID *Context\r
+ )\r
+{\r
+ IP4_SERVICE *IpSb;\r
+\r
+ IpSb = (IP4_SERVICE *) Context;\r
+ NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
+\r
+ if (IpSb->State > IP4_SERVICE_UNSTARTED) {\r
+ IpSb->State = IP4_SERVICE_UNSTARTED;\r
+ }\r
+ \r
+ IpSb->Reconfig = TRUE;\r
+\r
+ Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);\r
+\r
+ return ;\r
+}\r
+\r
+\r
+/**\r
+ Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.\r
+\r
+ @param Event The event that is signalled.\r
+ @param Context The IP4 service binding instance.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ip4AutoReconfigCallBack (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ //\r
+ // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK\r
+ //\r
+ QueueDpc (TPL_CALLBACK, Ip4AutoReconfigCallBackDpc, Context);\r
+}\r
+\r