mirror of https://github.com/acidanthera/audk.git
MdeModulePkg Ip4Dxe: Ip4Config2 to request DHCP Option6 DNS server IP
Ip4Config2 protocol implementation must request for DNS server info when the policy is set to DHCP. And when a DHCP server responds to it with a list of DNS server addresses, it must parse it and set it for the instance. Without this, nobody can do a Ip4Config->GetData for DNS server IPs before calling Dns->Configure(). This will mean a DHCP is initiated when calling Dns->Configure(), thus causing serious performance issues. This patch attempts to address this issue. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@hpe.com> Reviewed-by: Ye Ting <ting.ye@intel.com> Reviewed-by: Samer El-Haj-Mahmoud <elhaj@hpe.com> Reviewed-by: Fu Siyuan <siyuan.fu@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18560 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
33ecfa8af9
commit
9feefde0cb
|
@ -2,6 +2,7 @@
|
|||
The implementation of EFI IPv4 Configuration II Protocol.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
|
@ -677,6 +678,126 @@ Ip4Config2CleanDhcp4 (
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This worker function sets the DNS server list for the EFI IPv4 network
|
||||
stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
|
||||
manages. The DNS server addresses must be unicast IPv4 addresses.
|
||||
|
||||
@param[in] Instance The pointer to the IP4 config2 instance data.
|
||||
@param[in] DataSize The size of the buffer pointed to by Data in bytes.
|
||||
@param[in] Data The data buffer to set, points to an array of
|
||||
EFI_IPv4_ADDRESS instances.
|
||||
|
||||
@retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
|
||||
@retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
|
||||
@retval EFI_ABORTED The DNS server addresses to be set equal the current
|
||||
configuration.
|
||||
@retval EFI_SUCCESS The specified configuration data for the EFI IPv4
|
||||
network stack was set.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Config2SetDnsServerWorker (
|
||||
IN IP4_CONFIG2_INSTANCE *Instance,
|
||||
IN UINTN DataSize,
|
||||
IN VOID *Data
|
||||
)
|
||||
{
|
||||
UINTN OldIndex;
|
||||
UINTN NewIndex;
|
||||
UINTN Index1;
|
||||
EFI_IPv4_ADDRESS *OldDns;
|
||||
EFI_IPv4_ADDRESS *NewDns;
|
||||
UINTN OldDnsCount;
|
||||
UINTN NewDnsCount;
|
||||
IP4_CONFIG2_DATA_ITEM *Item;
|
||||
BOOLEAN OneAdded;
|
||||
VOID *Tmp;
|
||||
IP4_ADDR DnsAddress;
|
||||
|
||||
if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer];
|
||||
NewDns = (EFI_IPv4_ADDRESS *) Data;
|
||||
OldDns = Item->Data.DnsServers;
|
||||
NewDnsCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
|
||||
OldDnsCount = Item->DataSize / sizeof (EFI_IPv4_ADDRESS);
|
||||
OneAdded = FALSE;
|
||||
|
||||
if (NewDnsCount != OldDnsCount) {
|
||||
Tmp = AllocatePool (DataSize);
|
||||
if (Tmp == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
} else {
|
||||
Tmp = NULL;
|
||||
}
|
||||
|
||||
for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {
|
||||
CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR));
|
||||
|
||||
if (!NetIp4IsUnicast (NTOHL (DnsAddress), 0)) {
|
||||
//
|
||||
// The dns server address must be unicast.
|
||||
//
|
||||
FreePool (Tmp);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
for (Index1 = NewIndex + 1; Index1 < NewDnsCount; Index1++) {
|
||||
if (EFI_IP4_EQUAL (NewDns + NewIndex, NewDns + Index1)) {
|
||||
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_IP4_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {
|
||||
//
|
||||
// If found break out.
|
||||
//
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (OldIndex == OldDnsCount) {
|
||||
OneAdded = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Callback function when DHCP process finished. It will save the
|
||||
|
@ -701,6 +822,9 @@ Ip4Config2OnDhcp4Complete (
|
|||
IP4_ADDR StationAddress;
|
||||
IP4_ADDR SubnetMask;
|
||||
IP4_ADDR GatewayAddress;
|
||||
UINT32 Index;
|
||||
UINT32 OptionCount;
|
||||
EFI_DHCP4_PACKET_OPTION **OptionList;
|
||||
|
||||
Instance = (IP4_CONFIG2_INSTANCE *) Context;
|
||||
ASSERT (Instance->Dhcp4 != NULL);
|
||||
|
@ -724,6 +848,44 @@ Ip4Config2OnDhcp4Complete (
|
|||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse the ACK to get required DNS server information.
|
||||
//
|
||||
OptionCount = 0;
|
||||
OptionList = NULL;
|
||||
|
||||
Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList);
|
||||
if (Status != EFI_BUFFER_TOO_SMALL) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
OptionList = AllocateZeroPool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));
|
||||
if (OptionList == NULL) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (OptionList);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < OptionCount; Index++) {
|
||||
//
|
||||
// Look for DNS Server opcode (6).
|
||||
//
|
||||
if (OptionList[Index]->OpCode == DHCP_TAG_DNS_SERVER) {
|
||||
if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
Ip4Config2SetDnsServerWorker (Instance, OptionList[Index]->Length, &OptionList[Index]->Data[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreePool (OptionList);
|
||||
|
||||
Instance->DhcpSuccess = TRUE;
|
||||
}
|
||||
|
||||
|
@ -831,9 +993,10 @@ Ip4StartAutoConfig (
|
|||
// yields the control of this DHCP service to us.
|
||||
//
|
||||
ParaList.Head.OpCode = DHCP_TAG_PARA_LIST;
|
||||
ParaList.Head.Length = 2;
|
||||
ParaList.Head.Length = 3;
|
||||
ParaList.Head.Data[0] = DHCP_TAG_NETMASK;
|
||||
ParaList.Route = DHCP_TAG_ROUTER;
|
||||
ParaList.Dns = DHCP_TAG_DNS_SERVER;
|
||||
OptionList[0] = &ParaList.Head;
|
||||
Dhcp4Mode.ConfigData.OptionCount = 1;
|
||||
Dhcp4Mode.ConfigData.OptionList = OptionList;
|
||||
|
@ -1293,102 +1456,11 @@ Ip4Config2SetDnsServer (
|
|||
IN VOID *Data
|
||||
)
|
||||
{
|
||||
UINTN OldIndex;
|
||||
UINTN NewIndex;
|
||||
UINTN Index1;
|
||||
EFI_IPv4_ADDRESS *OldDns;
|
||||
EFI_IPv4_ADDRESS *NewDns;
|
||||
UINTN OldDnsCount;
|
||||
UINTN NewDnsCount;
|
||||
IP4_CONFIG2_DATA_ITEM *Item;
|
||||
BOOLEAN OneAdded;
|
||||
VOID *Tmp;
|
||||
IP4_ADDR DnsAddress;
|
||||
|
||||
if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
if (Instance->Policy != Ip4Config2PolicyStatic) {
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer];
|
||||
NewDns = (EFI_IPv4_ADDRESS *) Data;
|
||||
OldDns = Item->Data.DnsServers;
|
||||
NewDnsCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
|
||||
OldDnsCount = Item->DataSize / sizeof (EFI_IPv4_ADDRESS);
|
||||
OneAdded = FALSE;
|
||||
|
||||
if (NewDnsCount != OldDnsCount) {
|
||||
Tmp = AllocatePool (DataSize);
|
||||
if (Tmp == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
} else {
|
||||
Tmp = NULL;
|
||||
}
|
||||
|
||||
for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {
|
||||
CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR));
|
||||
|
||||
if (!NetIp4IsUnicast (NTOHL (DnsAddress), 0)) {
|
||||
//
|
||||
// The dns server address must be unicast.
|
||||
//
|
||||
FreePool (Tmp);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
for (Index1 = NewIndex + 1; Index1 < NewDnsCount; Index1++) {
|
||||
if (EFI_IP4_EQUAL (NewDns + NewIndex, NewDns + Index1)) {
|
||||
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_IP4_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {
|
||||
//
|
||||
// If found break out.
|
||||
//
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (OldIndex == OldDnsCount) {
|
||||
OneAdded = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
return Ip4Config2SetDnsServerWorker (Instance, DataSize, Data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
Definitions for EFI IPv4 Configuration II Protocol implementation.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
|
@ -27,7 +28,7 @@
|
|||
#define DHCP_TAG_PARA_LIST 55
|
||||
#define DHCP_TAG_NETMASK 1
|
||||
#define DHCP_TAG_ROUTER 3
|
||||
|
||||
#define DHCP_TAG_DNS_SERVER 6
|
||||
|
||||
#define DATA_ATTRIB_SET(Attrib, Bits) (BOOLEAN)((Attrib) & (Bits))
|
||||
#define SET_DATA_ATTRIB(Attrib, Bits) ((Attrib) |= (Bits))
|
||||
|
@ -207,6 +208,7 @@ struct _IP4_CONFIG2_INSTANCE {
|
|||
typedef struct {
|
||||
EFI_DHCP4_PACKET_OPTION Head;
|
||||
UINT8 Route;
|
||||
UINT8 Dns;
|
||||
} IP4_CONFIG2_DHCP4_OPTION;
|
||||
#pragma pack()
|
||||
|
||||
|
|
Loading…
Reference in New Issue