NetworkPkg: Move Network library and drivers from MdeModulePkg to NetworkPkg
Signed-off-by: Liming Gao <liming.gao@intel.com> Cc: Siyuan Fu <siyuan.fu@intel.com> Cc: Jiaxin Wu <jiaxin.wu@intel.com> Reviewed-by: Jiaxin Wu <jiaxin.wu@intel.com> Reviewed-by: Siyuan Fu <siyuan.fu@intel.com>
This commit is contained in:
431
NetworkPkg/Dhcp4Dxe/ComponentName.c
Normal file
431
NetworkPkg/Dhcp4Dxe/ComponentName.c
Normal file
@@ -0,0 +1,431 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include "Dhcp4Impl.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Functions
|
||||
//
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the driver.
|
||||
|
||||
This function retrieves the user readable name of a driver in the form of a
|
||||
Unicode string. If the driver specified by This has a user readable name in
|
||||
the language specified by Language, then a pointer to the driver name is
|
||||
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||
by This does not support the language specified by Language,
|
||||
then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, and it must match one of the
|
||||
languages specified in SupportedLanguages. The
|
||||
number of languages supported by a driver is up
|
||||
to the driver writer. Language is specified
|
||||
in RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] DriverName A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
driver specified by This in the language
|
||||
specified by Language.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||
This and the language specified by Language was
|
||||
returned in DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER DriverName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DhcpComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the controller
|
||||
that is being managed by a driver.
|
||||
|
||||
This function retrieves the user readable name of the controller specified by
|
||||
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||
driver specified by This has a user readable name in the language specified by
|
||||
Language, then a pointer to the controller name is returned in ControllerName,
|
||||
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||
managing the controller specified by ControllerHandle and ChildHandle,
|
||||
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] ControllerHandle The handle of a controller that the driver
|
||||
specified by This is managing. This handle
|
||||
specifies the controller whose name is to be
|
||||
returned.
|
||||
|
||||
@param[in] ChildHandle The handle of the child controller to retrieve
|
||||
the name of. This is an optional parameter that
|
||||
may be NULL. It will be NULL for device
|
||||
drivers. It will also be NULL for a bus drivers
|
||||
that wish to retrieve the name of the bus
|
||||
controller. It will not be NULL for a bus
|
||||
driver that wishes to retrieve the name of a
|
||||
child controller.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, and it must match one of the
|
||||
languages specified in SupportedLanguages. The
|
||||
number of languages supported by a driver is up
|
||||
to the driver writer. Language is specified in
|
||||
RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] ControllerName A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
controller specified by ControllerHandle and
|
||||
ChildHandle in the language specified by
|
||||
Language from the point of view of the driver
|
||||
specified by This.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the user readable name in
|
||||
the language specified by Language for the
|
||||
driver specified by This was returned in
|
||||
DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
|
||||
EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DhcpComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// EFI Component Name Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gDhcp4ComponentName = {
|
||||
DhcpComponentNameGetDriverName,
|
||||
DhcpComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name 2 Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gDhcp4ComponentName2 = {
|
||||
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) DhcpComponentNameGetDriverName,
|
||||
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) DhcpComponentNameGetControllerName,
|
||||
"en"
|
||||
};
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mDhcpDriverNameTable[] = {
|
||||
{
|
||||
"eng;en",
|
||||
L"DHCP Protocol Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gDhcpControllerNameTable = NULL;
|
||||
|
||||
CHAR16 *mDhcp4ControllerName[] = {
|
||||
L"DHCPv4 (State=0, Stopped)",
|
||||
L"DHCPv4 (State=1, Init)",
|
||||
L"DHCPv4 (State=2, Selecting)",
|
||||
L"DHCPv4 (State=3, Requesting)",
|
||||
L"DHCPv4 (State=4, Bound)",
|
||||
L"DHCPv4 (State=5, Renewing)",
|
||||
L"DHCPv4 (State=6, Rebinding)",
|
||||
L"DHCPv4 (State=7, InitReboot)",
|
||||
L"DHCPv4 (State=8, Rebooting)"
|
||||
};
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the driver.
|
||||
|
||||
This function retrieves the user readable name of a driver in the form of a
|
||||
Unicode string. If the driver specified by This has a user readable name in
|
||||
the language specified by Language, then a pointer to the driver name is
|
||||
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||
by This does not support the language specified by Language,
|
||||
then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, and it must match one of the
|
||||
languages specified in SupportedLanguages. The
|
||||
number of languages supported by a driver is up
|
||||
to the driver writer. Language is specified
|
||||
in RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] DriverName A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
driver specified by This in the language
|
||||
specified by Language.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||
This and the language specified by Language was
|
||||
returned in DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER DriverName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DhcpComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
{
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mDhcpDriverNameTable,
|
||||
DriverName,
|
||||
(BOOLEAN)(This == &gDhcp4ComponentName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Update the component name for the Dhcp4 child handle.
|
||||
|
||||
@param Dhcp4[in] A pointer to the EFI_DHCP4_PROTOCOL.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS Update the ControllerNameTable of this instance successfully.
|
||||
@retval EFI_INVALID_PARAMETER The input parameter is invalid.
|
||||
@retval EFI_DEVICE_ERROR DHCP is in unknown state.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UpdateName (
|
||||
IN EFI_DHCP4_PROTOCOL *Dhcp4
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_DHCP4_MODE_DATA Dhcp4ModeData;
|
||||
|
||||
if (Dhcp4 == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Format the child name into the string buffer.
|
||||
//
|
||||
Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4ModeData);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (gDhcpControllerNameTable != NULL) {
|
||||
FreeUnicodeStringTable (gDhcpControllerNameTable);
|
||||
gDhcpControllerNameTable = NULL;
|
||||
}
|
||||
|
||||
if (Dhcp4ModeData.State > Dhcp4Rebooting) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Status = AddUnicodeString2 (
|
||||
"eng",
|
||||
gDhcp4ComponentName.SupportedLanguages,
|
||||
&gDhcpControllerNameTable,
|
||||
mDhcp4ControllerName[Dhcp4ModeData.State],
|
||||
TRUE
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return AddUnicodeString2 (
|
||||
"en",
|
||||
gDhcp4ComponentName2.SupportedLanguages,
|
||||
&gDhcpControllerNameTable,
|
||||
mDhcp4ControllerName[Dhcp4ModeData.State],
|
||||
FALSE
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the controller
|
||||
that is being managed by a driver.
|
||||
|
||||
This function retrieves the user readable name of the controller specified by
|
||||
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||
driver specified by This has a user readable name in the language specified by
|
||||
Language, then a pointer to the controller name is returned in ControllerName,
|
||||
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||
managing the controller specified by ControllerHandle and ChildHandle,
|
||||
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] ControllerHandle The handle of a controller that the driver
|
||||
specified by This is managing. This handle
|
||||
specifies the controller whose name is to be
|
||||
returned.
|
||||
|
||||
@param[in] ChildHandle The handle of the child controller to retrieve
|
||||
the name of. This is an optional parameter that
|
||||
may be NULL. It will be NULL for device
|
||||
drivers. It will also be NULL for a bus drivers
|
||||
that wish to retrieve the name of the bus
|
||||
controller. It will not be NULL for a bus
|
||||
driver that wishes to retrieve the name of a
|
||||
child controller.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, and it must match one of the
|
||||
languages specified in SupportedLanguages. The
|
||||
number of languages supported by a driver is up
|
||||
to the driver writer. Language is specified in
|
||||
RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] ControllerName A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
controller specified by ControllerHandle and
|
||||
ChildHandle in the language specified by
|
||||
Language from the point of view of the driver
|
||||
specified by This.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the user readable name in
|
||||
the language specified by Language for the
|
||||
driver specified by This was returned in
|
||||
DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
|
||||
EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DhcpComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_DHCP4_PROTOCOL *Dhcp4;
|
||||
|
||||
//
|
||||
// Only provide names for child handles.
|
||||
//
|
||||
if (ChildHandle == NULL) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure this driver produced ChildHandle
|
||||
//
|
||||
Status = EfiTestChildHandle (
|
||||
ControllerHandle,
|
||||
ChildHandle,
|
||||
&gEfiUdp4ProtocolGuid
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve an instance of a produced protocol from ChildHandle
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiDhcp4ProtocolGuid,
|
||||
(VOID **)&Dhcp4,
|
||||
NULL,
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Update the component name for this child handle.
|
||||
//
|
||||
Status = UpdateName (Dhcp4);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
gDhcpControllerNameTable,
|
||||
ControllerName,
|
||||
(BOOLEAN)(This == &gDhcp4ComponentName)
|
||||
);
|
||||
}
|
732
NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
Normal file
732
NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
Normal file
@@ -0,0 +1,732 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Dhcp4Impl.h"
|
||||
#include "Dhcp4Driver.h"
|
||||
|
||||
EFI_DRIVER_BINDING_PROTOCOL gDhcp4DriverBinding = {
|
||||
Dhcp4DriverBindingSupported,
|
||||
Dhcp4DriverBindingStart,
|
||||
Dhcp4DriverBindingStop,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
EFI_SERVICE_BINDING_PROTOCOL mDhcp4ServiceBindingTemplate = {
|
||||
Dhcp4ServiceBindingCreateChild,
|
||||
Dhcp4ServiceBindingDestroyChild
|
||||
};
|
||||
|
||||
/**
|
||||
This is the declaration of an EFI image entry point. This entry point is
|
||||
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
|
||||
both device drivers and bus drivers.
|
||||
|
||||
Entry point of the DHCP driver to install various protocols.
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for the UEFI image.
|
||||
@param[in] SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
return EfiLibInstallDriverBindingComponentName2 (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gDhcp4DriverBinding,
|
||||
ImageHandle,
|
||||
&gDhcp4ComponentName,
|
||||
&gDhcp4ComponentName2
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle. This service
|
||||
is called by the EFI boot service ConnectController(). In
|
||||
order to make drivers as small as possible, there are a few calling
|
||||
restrictions for this service. ConnectController() must
|
||||
follow these calling restrictions. If any other agent wishes to call
|
||||
Supported() it must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to test
|
||||
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS This driver supports this device
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on this device
|
||||
@retval other This driver does not support this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiUdp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Configure the default UDP child to receive all the DHCP traffics
|
||||
on this network interface.
|
||||
|
||||
@param[in] UdpIo The UDP IO to configure
|
||||
@param[in] Context The context to the function
|
||||
|
||||
@retval EFI_SUCCESS The UDP IO is successfully configured.
|
||||
@retval Others Failed to configure the UDP child.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DhcpConfigUdpIo (
|
||||
IN UDP_IO *UdpIo,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_UDP4_CONFIG_DATA UdpConfigData;
|
||||
|
||||
UdpConfigData.AcceptBroadcast = TRUE;
|
||||
UdpConfigData.AcceptPromiscuous = FALSE;
|
||||
UdpConfigData.AcceptAnyPort = FALSE;
|
||||
UdpConfigData.AllowDuplicatePort = TRUE;
|
||||
UdpConfigData.TypeOfService = 0;
|
||||
UdpConfigData.TimeToLive = 64;
|
||||
UdpConfigData.DoNotFragment = FALSE;
|
||||
UdpConfigData.ReceiveTimeout = 0;
|
||||
UdpConfigData.TransmitTimeout = 0;
|
||||
|
||||
UdpConfigData.UseDefaultAddress = FALSE;
|
||||
UdpConfigData.StationPort = DHCP_CLIENT_PORT;
|
||||
UdpConfigData.RemotePort = DHCP_SERVER_PORT;
|
||||
|
||||
ZeroMem (&UdpConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
ZeroMem (&UdpConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
|
||||
ZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
return UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfigData);;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Destroy the DHCP service. The Dhcp4 service may be partly initialized,
|
||||
or partly destroyed. If a resource is destroyed, it is marked as so in
|
||||
case the destroy failed and being called again later.
|
||||
|
||||
@param[in] DhcpSb The DHCP service instance to destroy.
|
||||
|
||||
@retval EFI_SUCCESS Always return success.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Dhcp4CloseService (
|
||||
IN DHCP_SERVICE *DhcpSb
|
||||
)
|
||||
{
|
||||
DhcpCleanLease (DhcpSb);
|
||||
|
||||
if (DhcpSb->UdpIo != NULL) {
|
||||
UdpIoFreeIo (DhcpSb->UdpIo);
|
||||
DhcpSb->UdpIo = NULL;
|
||||
}
|
||||
|
||||
if (DhcpSb->Timer != NULL) {
|
||||
gBS->SetTimer (DhcpSb->Timer, TimerCancel, 0);
|
||||
gBS->CloseEvent (DhcpSb->Timer);
|
||||
|
||||
DhcpSb->Timer = NULL;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Create a new DHCP service binding instance for the controller.
|
||||
|
||||
@param[in] Controller The controller to install DHCP service binding
|
||||
protocol onto
|
||||
@param[in] ImageHandle The driver's image handle
|
||||
@param[out] Service The variable to receive the created DHCP service
|
||||
instance.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource .
|
||||
@retval EFI_SUCCESS The DHCP service instance is created.
|
||||
@retval other Other error occurs.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Dhcp4CreateService (
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
OUT DHCP_SERVICE **Service
|
||||
)
|
||||
{
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
*Service = NULL;
|
||||
DhcpSb = AllocateZeroPool (sizeof (DHCP_SERVICE));
|
||||
|
||||
if (DhcpSb == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
DhcpSb->Signature = DHCP_SERVICE_SIGNATURE;
|
||||
DhcpSb->ServiceState = DHCP_UNCONFIGED;
|
||||
DhcpSb->Controller = Controller;
|
||||
DhcpSb->Image = ImageHandle;
|
||||
InitializeListHead (&DhcpSb->Children);
|
||||
DhcpSb->DhcpState = Dhcp4Stopped;
|
||||
DhcpSb->Xid = NET_RANDOM (NetRandomInitSeed ());
|
||||
CopyMem (
|
||||
&DhcpSb->ServiceBinding,
|
||||
&mDhcp4ServiceBindingTemplate,
|
||||
sizeof (EFI_SERVICE_BINDING_PROTOCOL)
|
||||
);
|
||||
//
|
||||
// Create various resources, UdpIo, Timer, and get Mac address
|
||||
//
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
||||
TPL_CALLBACK,
|
||||
DhcpOnTimerTick,
|
||||
DhcpSb,
|
||||
&DhcpSb->Timer
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
DhcpSb->UdpIo = UdpIoCreateIo (
|
||||
Controller,
|
||||
ImageHandle,
|
||||
DhcpConfigUdpIo,
|
||||
UDP_IO_UDP4_VERSION,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (DhcpSb->UdpIo == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
DhcpSb->HwLen = (UINT8) DhcpSb->UdpIo->SnpMode.HwAddressSize;
|
||||
DhcpSb->HwType = DhcpSb->UdpIo->SnpMode.IfType;
|
||||
CopyMem (&DhcpSb->Mac, &DhcpSb->UdpIo->SnpMode.CurrentAddress, sizeof (DhcpSb->Mac));
|
||||
|
||||
*Service = DhcpSb;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
Dhcp4CloseService (DhcpSb);
|
||||
FreePool (DhcpSb);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle. This service is called by the
|
||||
EFI boot service ConnectController(). In order to make
|
||||
drivers as small as possible, there are a few calling restrictions for
|
||||
this service. ConnectController() must follow these
|
||||
calling restrictions. If any other agent wishes to call Start() it
|
||||
must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to bind driver to
|
||||
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS This driver is added to ControllerHandle
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
|
||||
@retval other This driver does not support this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// First: test for the DHCP4 Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiDhcp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (Status == EFI_SUCCESS) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
Status = Dhcp4CreateService (ControllerHandle, This->DriverBindingHandle, &DhcpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
ASSERT (DhcpSb != NULL);
|
||||
|
||||
//
|
||||
// Start the receiving
|
||||
//
|
||||
Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
Status = gBS->SetTimer (DhcpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the Dhcp4ServiceBinding Protocol onto ControlerHandle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&ControllerHandle,
|
||||
&gEfiDhcp4ServiceBindingProtocolGuid,
|
||||
&DhcpSb->ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
||||
ON_ERROR:
|
||||
Dhcp4CloseService (DhcpSb);
|
||||
FreePool (DhcpSb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Callback function which provided by user to remove one node in NetDestroyLinkList process.
|
||||
|
||||
@param[in] Entry The entry to be removed.
|
||||
@param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
|
||||
|
||||
@retval EFI_SUCCESS The entry has been removed successfully.
|
||||
@retval Others Fail to remove the entry.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DestroyChildEntry (
|
||||
IN LIST_ENTRY *Entry,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
DHCP_PROTOCOL *Instance;
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
|
||||
if (Entry == NULL || Context == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = NET_LIST_USER_STRUCT_S (Entry, DHCP_PROTOCOL, Link, DHCP_PROTOCOL_SIGNATURE);
|
||||
ServiceBinding = (EFI_SERVICE_BINDING_PROTOCOL *) Context;
|
||||
|
||||
return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle. This service is called by the
|
||||
EFI boot service DisconnectController(). In order to
|
||||
make drivers as small as possible, there are a few calling
|
||||
restrictions for this service. DisconnectController()
|
||||
must follow these calling restrictions. If any other agent wishes
|
||||
to call Stop() it must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to stop driver on
|
||||
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
|
||||
children is zero stop the entire bus driver.
|
||||
@param[in] ChildHandleBuffer List of Child Handles to Stop.
|
||||
|
||||
@retval EFI_SUCCESS This driver is removed ControllerHandle
|
||||
@retval other This driver was not removed from this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
EFI_HANDLE NicHandle;
|
||||
EFI_STATUS Status;
|
||||
LIST_ENTRY *List;
|
||||
UINTN ListLength;
|
||||
|
||||
//
|
||||
// DHCP driver opens UDP child, So, the ControllerHandle is the
|
||||
// UDP child handle. locate the Nic handle first.
|
||||
//
|
||||
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
|
||||
|
||||
if (NicHandle == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
NicHandle,
|
||||
&gEfiDhcp4ServiceBindingProtocolGuid,
|
||||
(VOID **) &ServiceBinding,
|
||||
This->DriverBindingHandle,
|
||||
NicHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
DhcpSb = DHCP_SERVICE_FROM_THIS (ServiceBinding);
|
||||
if (!IsListEmpty (&DhcpSb->Children)) {
|
||||
//
|
||||
// Destroy all the children instances before destory the service.
|
||||
//
|
||||
List = &DhcpSb->Children;
|
||||
Status = NetDestroyLinkList (
|
||||
List,
|
||||
Dhcp4DestroyChildEntry,
|
||||
ServiceBinding,
|
||||
&ListLength
|
||||
);
|
||||
if (EFI_ERROR (Status) || ListLength != 0) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (NumberOfChildren == 0 && !IsListEmpty (&DhcpSb->Children)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (NumberOfChildren == 0 && IsListEmpty (&DhcpSb->Children)) {
|
||||
//
|
||||
// Destroy the service itself if no child instance left.
|
||||
//
|
||||
DhcpSb->ServiceState = DHCP_DESTROY;
|
||||
|
||||
gBS->UninstallProtocolInterface (
|
||||
NicHandle,
|
||||
&gEfiDhcp4ServiceBindingProtocolGuid,
|
||||
ServiceBinding
|
||||
);
|
||||
|
||||
Dhcp4CloseService (DhcpSb);
|
||||
|
||||
if (gDhcpControllerNameTable != NULL) {
|
||||
FreeUnicodeStringTable (gDhcpControllerNameTable);
|
||||
gDhcpControllerNameTable = NULL;
|
||||
}
|
||||
FreePool (DhcpSb);
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialize a new DHCP instance.
|
||||
|
||||
@param DhcpSb The dhcp service instance
|
||||
@param Instance The dhcp instance to initialize
|
||||
|
||||
**/
|
||||
VOID
|
||||
DhcpInitProtocol (
|
||||
IN DHCP_SERVICE *DhcpSb,
|
||||
IN OUT DHCP_PROTOCOL *Instance
|
||||
)
|
||||
{
|
||||
Instance->Signature = DHCP_PROTOCOL_SIGNATURE;
|
||||
CopyMem (&Instance->Dhcp4Protocol, &mDhcp4ProtocolTemplate, sizeof (Instance->Dhcp4Protocol));
|
||||
InitializeListHead (&Instance->Link);
|
||||
Instance->Handle = NULL;
|
||||
Instance->Service = DhcpSb;
|
||||
Instance->InDestroy = FALSE;
|
||||
Instance->CompletionEvent = NULL;
|
||||
Instance->RenewRebindEvent = NULL;
|
||||
Instance->Token = NULL;
|
||||
Instance->UdpIo = NULL;
|
||||
Instance->ElaspedTime = 0;
|
||||
NetbufQueInit (&Instance->ResponseQueue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates a child handle and installs a protocol.
|
||||
|
||||
The CreateChild() function installs a protocol on ChildHandle.
|
||||
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
|
||||
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
|
||||
|
||||
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param ChildHandle Pointer to the handle of the child to create. If it is NULL,
|
||||
then a new handle is created. If it is a pointer to an existing UEFI handle,
|
||||
then the protocol is added to the existing UEFI handle.
|
||||
|
||||
@retval EFI_SUCCES The protocol was added to ChildHandle.
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
|
||||
the child
|
||||
@retval other The child handle was not created
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
)
|
||||
{
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
DHCP_PROTOCOL *Instance;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
VOID *Udp4;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = AllocatePool (sizeof (*Instance));
|
||||
|
||||
if (Instance == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
DhcpSb = DHCP_SERVICE_FROM_THIS (This);
|
||||
DhcpInitProtocol (DhcpSb, Instance);
|
||||
|
||||
//
|
||||
// Install DHCP4 onto ChildHandle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiDhcp4ProtocolGuid,
|
||||
&Instance->Dhcp4Protocol,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Instance);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Instance->Handle = *ChildHandle;
|
||||
|
||||
//
|
||||
// Open the Udp4 protocol BY_CHILD.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
DhcpSb->UdpIo->UdpHandle,
|
||||
&gEfiUdp4ProtocolGuid,
|
||||
(VOID **) &Udp4,
|
||||
gDhcp4DriverBinding.DriverBindingHandle,
|
||||
Instance->Handle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
Instance->Handle,
|
||||
&gEfiDhcp4ProtocolGuid,
|
||||
&Instance->Dhcp4Protocol,
|
||||
NULL
|
||||
);
|
||||
|
||||
FreePool (Instance);
|
||||
return Status;
|
||||
}
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
InsertTailList (&DhcpSb->Children, &Instance->Link);
|
||||
DhcpSb->NumChildren++;
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destroys a child handle with a protocol installed on it.
|
||||
|
||||
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
|
||||
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
|
||||
last protocol on ChildHandle, then ChildHandle is destroyed.
|
||||
|
||||
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param ChildHandle Handle of the child to destroy
|
||||
|
||||
@retval EFI_SUCCES The protocol was removed from ChildHandle.
|
||||
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
|
||||
@retval EFI_INVALID_PARAMETER Child handle is NULL.
|
||||
@retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
|
||||
because its services are being used.
|
||||
@retval other The child handle was not destroyed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
)
|
||||
{
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
DHCP_PROTOCOL *Instance;
|
||||
EFI_DHCP4_PROTOCOL *Dhcp;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the private context data structures
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiDhcp4ProtocolGuid,
|
||||
(VOID **) &Dhcp,
|
||||
gDhcp4DriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Instance = DHCP_INSTANCE_FROM_THIS (Dhcp);
|
||||
DhcpSb = DHCP_SERVICE_FROM_THIS (This);
|
||||
|
||||
if (Instance->Service != DhcpSb) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// A child can be destroyed more than once. For example,
|
||||
// Dhcp4DriverBindingStop will destroy all of its children.
|
||||
// when caller driver is being stopped, it will destroy the
|
||||
// dhcp child it opens.
|
||||
//
|
||||
if (Instance->InDestroy) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
Instance->InDestroy = TRUE;
|
||||
|
||||
//
|
||||
// Close the Udp4 protocol.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
DhcpSb->UdpIo->UdpHandle,
|
||||
&gEfiUdp4ProtocolGuid,
|
||||
gDhcp4DriverBinding.DriverBindingHandle,
|
||||
ChildHandle
|
||||
);
|
||||
|
||||
//
|
||||
// Uninstall the DHCP4 protocol first to enable a top down destruction.
|
||||
//
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
ChildHandle,
|
||||
&gEfiDhcp4ProtocolGuid,
|
||||
Dhcp
|
||||
);
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Instance->InDestroy = FALSE;
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (DhcpSb->ActiveChild == Instance) {
|
||||
DhcpYieldControl (DhcpSb);
|
||||
}
|
||||
|
||||
RemoveEntryList (&Instance->Link);
|
||||
DhcpSb->NumChildren--;
|
||||
|
||||
if (Instance->UdpIo != NULL) {
|
||||
UdpIoCleanIo (Instance->UdpIo);
|
||||
gBS->CloseProtocol (
|
||||
Instance->UdpIo->UdpHandle,
|
||||
&gEfiUdp4ProtocolGuid,
|
||||
Instance->Service->Image,
|
||||
Instance->Handle
|
||||
);
|
||||
UdpIoFreeIo (Instance->UdpIo);
|
||||
Instance->UdpIo = NULL;
|
||||
Instance->Token = NULL;
|
||||
}
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
FreePool (Instance);
|
||||
return EFI_SUCCESS;
|
||||
}
|
146
NetworkPkg/Dhcp4Dxe/Dhcp4Driver.h
Normal file
146
NetworkPkg/Dhcp4Dxe/Dhcp4Driver.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/** @file
|
||||
Header for the DHCP4 driver.
|
||||
|
||||
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_DHCP4_DRIVER_H__
|
||||
#define __EFI_DHCP4_DRIVER_H__
|
||||
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gDhcp4ComponentName;
|
||||
extern EFI_COMPONENT_NAME2_PROTOCOL gDhcp4ComponentName2;
|
||||
extern EFI_UNICODE_STRING_TABLE *gDhcpControllerNameTable;
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle. This service
|
||||
is called by the EFI boot service ConnectController(). In
|
||||
order to make drivers as small as possible, there are a few calling
|
||||
restrictions for this service. ConnectController() must
|
||||
follow these calling restrictions. If any other agent wishes to call
|
||||
Supported() it must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to test
|
||||
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS This driver supports this device
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on this device
|
||||
@retval other This driver does not support this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle. This service is called by the
|
||||
EFI boot service ConnectController(). In order to make
|
||||
drivers as small as possible, there are a few calling restrictions for
|
||||
this service. ConnectController() must follow these
|
||||
calling restrictions. If any other agent wishes to call Start() it
|
||||
must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to bind driver to
|
||||
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS This driver is added to ControllerHandle
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
|
||||
@retval other This driver does not support this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle. This service is called by the
|
||||
EFI boot service DisconnectController(). In order to
|
||||
make drivers as small as possible, there are a few calling
|
||||
restrictions for this service. DisconnectController()
|
||||
must follow these calling restrictions. If any other agent wishes
|
||||
to call Stop() it must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to stop driver on
|
||||
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
|
||||
children is zero stop the entire bus driver.
|
||||
@param[in] ChildHandleBuffer List of Child Handles to Stop.
|
||||
|
||||
@retval EFI_SUCCESS This driver is removed ControllerHandle
|
||||
@retval other This driver was not removed from this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
/**
|
||||
Creates a child handle and installs a protocol.
|
||||
|
||||
The CreateChild() function installs a protocol on ChildHandle.
|
||||
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
|
||||
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
|
||||
|
||||
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param ChildHandle Pointer to the handle of the child to create. If it is NULL,
|
||||
then a new handle is created. If it is a pointer to an existing UEFI handle,
|
||||
then the protocol is added to the existing UEFI handle.
|
||||
|
||||
@retval EFI_SUCCES The protocol was added to ChildHandle.
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
|
||||
the child
|
||||
@retval other The child handle was not created
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
);
|
||||
|
||||
/**
|
||||
Destroys a child handle with a protocol installed on it.
|
||||
|
||||
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
|
||||
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
|
||||
last protocol on ChildHandle, then ChildHandle is destroyed.
|
||||
|
||||
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param ChildHandle Handle of the child to destroy
|
||||
|
||||
@retval EFI_SUCCES The protocol was removed from ChildHandle.
|
||||
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
|
||||
@retval EFI_INVALID_PARAMETER Child handle is NULL.
|
||||
@retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
|
||||
because its services are being used.
|
||||
@retval other The child handle was not destroyed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
);
|
||||
|
||||
#endif
|
66
NetworkPkg/Dhcp4Dxe/Dhcp4Dxe.inf
Normal file
66
NetworkPkg/Dhcp4Dxe/Dhcp4Dxe.inf
Normal file
@@ -0,0 +1,66 @@
|
||||
## @file
|
||||
# This module produces EFI DHCPv4 Protocol and EFI DHCPv4 Service Binding Protocol.
|
||||
#
|
||||
# This module produces EFI DHCPv4 Protocol upon EFI UDPv4 Protocol, to provide the
|
||||
# capability to collect configuration information for the EFI IPv4 Protocol drivers
|
||||
# and to provide DHCPv4 server and PXE boot server discovery services.
|
||||
#
|
||||
# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = Dhcp4Dxe
|
||||
MODULE_UNI_FILE = Dhcp4Dxe.uni
|
||||
FILE_GUID = 94734718-0BBC-47fb-96A5-EE7A5AE6A2AD
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = Dhcp4DriverEntryPoint
|
||||
UNLOAD_IMAGE = NetLibDefaultUnload
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 EBC
|
||||
#
|
||||
# DRIVER_BINDING = gDhcp4DriverBinding
|
||||
# COMPONENT_NAME = gDhcp4ComponentName
|
||||
# COMPONENT_NAME2 = gDhcp4ComponentName2
|
||||
#
|
||||
|
||||
[Sources]
|
||||
Dhcp4Impl.c
|
||||
Dhcp4Io.c
|
||||
Dhcp4Io.h
|
||||
ComponentName.c
|
||||
Dhcp4Driver.h
|
||||
Dhcp4Driver.c
|
||||
Dhcp4Option.c
|
||||
Dhcp4Option.h
|
||||
Dhcp4Impl.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
DebugLib
|
||||
NetLib
|
||||
UdpIoLib
|
||||
|
||||
|
||||
[Protocols]
|
||||
gEfiDhcp4ServiceBindingProtocolGuid ## BY_START
|
||||
gEfiUdp4ServiceBindingProtocolGuid ## TO_START
|
||||
gEfiDhcp4ProtocolGuid ## BY_START
|
||||
gEfiUdp4ProtocolGuid ## TO_START
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
Dhcp4DxeExtra.uni
|
18
NetworkPkg/Dhcp4Dxe/Dhcp4Dxe.uni
Normal file
18
NetworkPkg/Dhcp4Dxe/Dhcp4Dxe.uni
Normal file
@@ -0,0 +1,18 @@
|
||||
// /** @file
|
||||
// This module produces EFI DHCPv4 Protocol and EFI DHCPv4 Service Binding Protocol.
|
||||
//
|
||||
// This module produces EFI DHCPv4 Protocol upon EFI UDPv4 Protocol, to provide the
|
||||
// capability to collect configuration information for the EFI IPv4 Protocol drivers
|
||||
// and to provide DHCPv4 server and PXE boot server discovery services.
|
||||
//
|
||||
// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "EFI DHCPv4 Driver"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "This module produces EFI DHCPv4 Protocol using the EFI UDPv4 Protocol, providing the capability to collect configuration information for the EFI IPv4 Protocol drivers and providing DHCPv4 server and PXE boot server discovery services."
|
||||
|
14
NetworkPkg/Dhcp4Dxe/Dhcp4DxeExtra.uni
Normal file
14
NetworkPkg/Dhcp4Dxe/Dhcp4DxeExtra.uni
Normal file
@@ -0,0 +1,14 @@
|
||||
// /** @file
|
||||
// Dhcp4Dxe Localized Strings and Content
|
||||
//
|
||||
// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_PROPERTIES_MODULE_NAME
|
||||
#language en-US
|
||||
"DHCP v4 DXE Driver"
|
||||
|
||||
|
1802
NetworkPkg/Dhcp4Dxe/Dhcp4Impl.c
Normal file
1802
NetworkPkg/Dhcp4Dxe/Dhcp4Impl.c
Normal file
File diff suppressed because it is too large
Load Diff
206
NetworkPkg/Dhcp4Dxe/Dhcp4Impl.h
Normal file
206
NetworkPkg/Dhcp4Dxe/Dhcp4Impl.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/** @file
|
||||
EFI DHCP protocol implementation.
|
||||
RFCs supported are:
|
||||
RFC 2131: Dynamic Host Configuration Protocol
|
||||
RFC 2132: DHCP Options and BOOTP Vendor Extensions
|
||||
RFC 1534: Interoperation Between DHCP and BOOTP
|
||||
RFC 3396: Encoding Long Options in DHCP.
|
||||
|
||||
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_DHCP4_IMPL_H__
|
||||
#define __EFI_DHCP4_IMPL_H__
|
||||
|
||||
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Protocol/Dhcp4.h>
|
||||
#include <Protocol/Udp4.h>
|
||||
#include <IndustryStandard/Dhcp.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/NetLib.h>
|
||||
|
||||
typedef struct _DHCP_SERVICE DHCP_SERVICE;
|
||||
typedef struct _DHCP_PROTOCOL DHCP_PROTOCOL;
|
||||
|
||||
#include "Dhcp4Option.h"
|
||||
#include "Dhcp4Io.h"
|
||||
|
||||
#define DHCP_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'H', 'C', 'P')
|
||||
#define DHCP_PROTOCOL_SIGNATURE SIGNATURE_32 ('d', 'h', 'c', 'p')
|
||||
|
||||
#define DHCP_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20)
|
||||
|
||||
//
|
||||
// The state of the DHCP service. It starts as UNCONFIGED. If
|
||||
// and active child configures the service successfully, it
|
||||
// goes to CONFIGED. If the active child configures NULL, it
|
||||
// goes back to UNCONFIGED. It becomes DESTROY if it is (partly)
|
||||
// destroyed.
|
||||
//
|
||||
#define DHCP_UNCONFIGED 0
|
||||
#define DHCP_CONFIGED 1
|
||||
#define DHCP_DESTROY 2
|
||||
|
||||
|
||||
struct _DHCP_PROTOCOL {
|
||||
UINT32 Signature;
|
||||
EFI_DHCP4_PROTOCOL Dhcp4Protocol;
|
||||
LIST_ENTRY Link;
|
||||
EFI_HANDLE Handle;
|
||||
DHCP_SERVICE *Service;
|
||||
|
||||
BOOLEAN InDestroy;
|
||||
|
||||
EFI_EVENT CompletionEvent;
|
||||
EFI_EVENT RenewRebindEvent;
|
||||
|
||||
EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;
|
||||
UDP_IO *UdpIo; // The UDP IO used for TransmitReceive.
|
||||
UINT32 Timeout;
|
||||
UINT16 ElaspedTime;
|
||||
NET_BUF_QUEUE ResponseQueue;
|
||||
};
|
||||
|
||||
//
|
||||
// DHCP driver is specical in that it is a singleton. Although it
|
||||
// has a service binding, there can be only one active child.
|
||||
//
|
||||
struct _DHCP_SERVICE {
|
||||
UINT32 Signature;
|
||||
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
|
||||
|
||||
INTN ServiceState; // CONFIGED, UNCONFIGED, and DESTROY
|
||||
|
||||
EFI_HANDLE Controller;
|
||||
EFI_HANDLE Image;
|
||||
|
||||
LIST_ENTRY Children;
|
||||
UINTN NumChildren;
|
||||
|
||||
INTN DhcpState;
|
||||
EFI_STATUS IoStatus; // the result of last user operation
|
||||
UINT32 Xid;
|
||||
|
||||
IP4_ADDR ClientAddr; // lease IP or configured client address
|
||||
IP4_ADDR Netmask;
|
||||
IP4_ADDR ServerAddr;
|
||||
|
||||
EFI_DHCP4_PACKET *LastOffer; // The last received offer
|
||||
EFI_DHCP4_PACKET *Selected;
|
||||
DHCP_PARAMETER *Para;
|
||||
|
||||
UINT32 Lease;
|
||||
UINT32 T1;
|
||||
UINT32 T2;
|
||||
INTN ExtraRefresh; // This refresh is reqested by user
|
||||
|
||||
UDP_IO *UdpIo; // Udp child receiving all DHCP message
|
||||
UDP_IO *LeaseIoPort; // Udp child with lease IP
|
||||
EFI_DHCP4_PACKET *LastPacket; // The last sent packet for retransmission
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
UINT8 HwType;
|
||||
UINT8 HwLen;
|
||||
UINT8 ClientAddressSendOut[16];
|
||||
|
||||
DHCP_PROTOCOL *ActiveChild;
|
||||
EFI_DHCP4_CONFIG_DATA ActiveConfig;
|
||||
UINT32 UserOptionLen;
|
||||
|
||||
//
|
||||
// Timer event and various timer
|
||||
//
|
||||
EFI_EVENT Timer;
|
||||
|
||||
UINT32 PacketToLive; // Retransmission timer for our packets
|
||||
UINT32 LastTimeout; // Record the init value of PacketToLive every time
|
||||
INTN CurRetry;
|
||||
INTN MaxRetries;
|
||||
UINT32 LeaseLife;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
EFI_DHCP4_PACKET_OPTION **Option;
|
||||
UINT32 OptionCount;
|
||||
UINT32 Index;
|
||||
} DHCP_PARSE_CONTEXT;
|
||||
|
||||
#define DHCP_INSTANCE_FROM_THIS(Proto) \
|
||||
CR ((Proto), DHCP_PROTOCOL, Dhcp4Protocol, DHCP_PROTOCOL_SIGNATURE)
|
||||
|
||||
#define DHCP_SERVICE_FROM_THIS(Sb) \
|
||||
CR ((Sb), DHCP_SERVICE, ServiceBinding, DHCP_SERVICE_SIGNATURE)
|
||||
|
||||
extern EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate;
|
||||
|
||||
/**
|
||||
Give up the control of the DHCP service to let other child
|
||||
resume. Don't change the service's DHCP state and the Client
|
||||
address and option list configure as required by RFC2131.
|
||||
|
||||
@param DhcpSb The DHCP service instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
DhcpYieldControl (
|
||||
IN DHCP_SERVICE *DhcpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Complete a Dhcp4 transaction and signal the upper layer.
|
||||
|
||||
@param Instance Dhcp4 instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
PxeDhcpDone (
|
||||
IN DHCP_PROTOCOL *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Free the resource related to the configure parameters.
|
||||
DHCP driver will make a copy of the user's configure
|
||||
such as the time out value.
|
||||
|
||||
@param Config The DHCP configure data
|
||||
|
||||
**/
|
||||
VOID
|
||||
DhcpCleanConfigure (
|
||||
IN OUT EFI_DHCP4_CONFIG_DATA *Config
|
||||
);
|
||||
|
||||
/**
|
||||
Callback of Dhcp packet. Does nothing.
|
||||
|
||||
@param Arg The context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
DhcpDummyExtFree (
|
||||
IN VOID *Arg
|
||||
);
|
||||
|
||||
/**
|
||||
Set the elapsed time based on the given instance and the pointer to the
|
||||
elapsed time option.
|
||||
|
||||
@param[in] Elapsed The pointer to the position to append.
|
||||
@param[in] Instance The pointer to the Dhcp4 instance.
|
||||
**/
|
||||
VOID
|
||||
SetElapsedTime (
|
||||
IN UINT16 *Elapsed,
|
||||
IN DHCP_PROTOCOL *Instance
|
||||
);
|
||||
|
||||
#endif
|
1657
NetworkPkg/Dhcp4Dxe/Dhcp4Io.c
Normal file
1657
NetworkPkg/Dhcp4Dxe/Dhcp4Io.c
Normal file
File diff suppressed because it is too large
Load Diff
189
NetworkPkg/Dhcp4Dxe/Dhcp4Io.h
Normal file
189
NetworkPkg/Dhcp4Dxe/Dhcp4Io.h
Normal file
@@ -0,0 +1,189 @@
|
||||
/** @file
|
||||
The DHCP4 protocol implementation.
|
||||
|
||||
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_DHCP4_IO_H__
|
||||
#define __EFI_DHCP4_IO_H__
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
|
||||
#include <Library/NetLib.h>
|
||||
#include <Library/UdpIoLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
|
||||
|
||||
#define DHCP_WAIT_OFFER 3 // Time to wait the offers
|
||||
#define DHCP_DEFAULT_LEASE 7 * 24 * 60 * 60 // Seven days as default.
|
||||
#define DHCP_SERVER_PORT 67
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
|
||||
//
|
||||
// BOOTP header "op" field
|
||||
//
|
||||
#define BOOTP_REQUEST 1
|
||||
#define BOOTP_REPLY 2
|
||||
|
||||
//
|
||||
// DHCP message types
|
||||
//
|
||||
#define DHCP_MSG_DISCOVER 1
|
||||
#define DHCP_MSG_OFFER 2
|
||||
#define DHCP_MSG_REQUEST 3
|
||||
#define DHCP_MSG_DECLINE 4
|
||||
#define DHCP_MSG_ACK 5
|
||||
#define DHCP_MSG_NAK 6
|
||||
#define DHCP_MSG_RELEASE 7
|
||||
#define DHCP_MSG_INFORM 8
|
||||
|
||||
//
|
||||
// DHCP notify user type
|
||||
//
|
||||
#define DHCP_NOTIFY_COMPLETION 1
|
||||
#define DHCP_NOTIFY_RENEWREBIND 2
|
||||
#define DHCP_NOTIFY_ALL 3
|
||||
|
||||
#define DHCP_IS_BOOTP(Parameter) (((Parameter) == NULL) || ((Parameter)->DhcpType == 0))
|
||||
|
||||
#define DHCP_CONNECTED(State) \
|
||||
(((State) == Dhcp4Bound) || ((State) == (Dhcp4Renewing)) || ((State) == Dhcp4Rebinding))
|
||||
|
||||
/**
|
||||
Set the DHCP state. If CallUser is true, it will try to notify
|
||||
the user before change the state by DhcpNotifyUser. It returns
|
||||
EFI_ABORTED if the user return EFI_ABORTED, otherwise, it returns
|
||||
EFI_SUCCESS. If CallUser is FALSE, it isn't necessary to test
|
||||
the return value of this function.
|
||||
|
||||
@param DhcpSb The DHCP service instance
|
||||
@param State The new DHCP state to change to
|
||||
@param CallUser Whether we need to call user
|
||||
|
||||
@retval EFI_SUCCESS The state is changed
|
||||
@retval EFI_ABORTED The user asks to abort the DHCP process.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpSetState (
|
||||
IN OUT DHCP_SERVICE *DhcpSb,
|
||||
IN INTN State,
|
||||
IN BOOLEAN CallUser
|
||||
);
|
||||
|
||||
/**
|
||||
Build and transmit a DHCP message according to the current states.
|
||||
This function implement the Table 5. of RFC 2131. Always transits
|
||||
the state (as defined in Figure 5. of the same RFC) before sending
|
||||
a DHCP message. The table is adjusted accordingly.
|
||||
|
||||
@param[in] DhcpSb The DHCP service instance
|
||||
@param[in] Seed The seed packet which the new packet is based on
|
||||
@param[in] Para The DHCP parameter of the Seed packet
|
||||
@param[in] Type The message type to send
|
||||
@param[in] Msg The human readable message to include in the packet
|
||||
sent.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources for the packet
|
||||
@retval EFI_ACCESS_DENIED Failed to transmit the packet through UDP
|
||||
@retval EFI_SUCCESS The message is sent
|
||||
@retval other Other error occurs
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpSendMessage (
|
||||
IN DHCP_SERVICE *DhcpSb,
|
||||
IN EFI_DHCP4_PACKET *Seed,
|
||||
IN DHCP_PARAMETER *Para,
|
||||
IN UINT8 Type,
|
||||
IN UINT8 *Msg
|
||||
);
|
||||
|
||||
/**
|
||||
Each DHCP service has three timer. Two of them are count down timer.
|
||||
One for the packet retransmission. The other is to collect the offers.
|
||||
The third timer increaments the lease life which is compared to T1, T2,
|
||||
and lease to determine the time to renew and rebind the lease.
|
||||
DhcpOnTimerTick will be called once every second.
|
||||
|
||||
@param[in] Event The timer event
|
||||
@param[in] Context The context, which is the DHCP service instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
DhcpOnTimerTick (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Handle the received DHCP packets. This function drives the DHCP
|
||||
state machine.
|
||||
|
||||
@param UdpPacket The UDP packets received.
|
||||
@param EndPoint The local/remote UDP access point
|
||||
@param IoStatus The status of the UDP receive
|
||||
@param Context The opaque parameter to the function.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
DhcpInput (
|
||||
NET_BUF *UdpPacket,
|
||||
UDP_END_POINT *EndPoint,
|
||||
EFI_STATUS IoStatus,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Send an initial DISCOVER or REQUEST message according to the
|
||||
DHCP service's current state.
|
||||
|
||||
@param[in] DhcpSb The DHCP service instance
|
||||
|
||||
@retval EFI_SUCCESS The request has been sent
|
||||
@retval other Some error occurs when sending the request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpInitRequest (
|
||||
IN DHCP_SERVICE *DhcpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Clean up the DHCP related states, IoStatus isn't reset.
|
||||
|
||||
@param DhcpSb The DHCP instance service.
|
||||
|
||||
**/
|
||||
VOID
|
||||
DhcpCleanLease (
|
||||
IN DHCP_SERVICE *DhcpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Release the net buffer when packet is sent.
|
||||
|
||||
@param UdpPacket The UDP packets received.
|
||||
@param EndPoint The local/remote UDP access point
|
||||
@param IoStatus The status of the UDP receive
|
||||
@param Context The opaque parameter to the function.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
DhcpOnPacketSent (
|
||||
NET_BUF *Packet,
|
||||
UDP_END_POINT *EndPoint,
|
||||
EFI_STATUS IoStatus,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
#endif
|
890
NetworkPkg/Dhcp4Dxe/Dhcp4Option.c
Normal file
890
NetworkPkg/Dhcp4Dxe/Dhcp4Option.c
Normal file
@@ -0,0 +1,890 @@
|
||||
/** @file
|
||||
Function to validate, parse, process the DHCP options.
|
||||
|
||||
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Dhcp4Impl.h"
|
||||
|
||||
///
|
||||
/// A list of the format of DHCP Options sorted by option tag
|
||||
/// to validate a dhcp message. Refere the comments of the
|
||||
/// DHCP_OPTION_FORMAT structure.
|
||||
///
|
||||
DHCP_OPTION_FORMAT DhcpOptionFormats[] = {
|
||||
{DHCP4_TAG_NETMASK, DHCP_OPTION_IP, 1, 1 , TRUE},
|
||||
{DHCP4_TAG_TIME_OFFSET, DHCP_OPTION_INT32, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_ROUTER, DHCP_OPTION_IP, 1, -1 , TRUE},
|
||||
{DHCP4_TAG_TIME_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_NAME_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_DNS_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_LOG_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_COOKIE_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_LPR_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_IMPRESS_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_RL_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_HOSTNAME, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_BOOTFILE_LEN, DHCP_OPTION_INT16, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_DUMP, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_DOMAINNAME, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_SWAP_SERVER, DHCP_OPTION_IP, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_ROOTPATH, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_EXTEND_PATH, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
|
||||
{DHCP4_TAG_IPFORWARD, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_NONLOCAL_SRR, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_POLICY_SRR, DHCP_OPTION_IPPAIR, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_EMTU, DHCP_OPTION_INT16, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_TTL, DHCP_OPTION_INT8, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_PATHMTU_AGE, DHCP_OPTION_INT32, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_PATHMTU_PLATEAU,DHCP_OPTION_INT16, 1, -1 , FALSE},
|
||||
|
||||
{DHCP4_TAG_IFMTU, DHCP_OPTION_INT16, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_SUBNET_LOCAL, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_BROADCAST, DHCP_OPTION_IP, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_DISCOVER_MASK, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_SUPPLY_MASK, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_DISCOVER_ROUTE, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_ROUTER_SOLICIT, DHCP_OPTION_IP, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_STATIC_ROUTE, DHCP_OPTION_IPPAIR, 1, -1 , FALSE},
|
||||
|
||||
{DHCP4_TAG_TRAILER, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_ARPAGE, DHCP_OPTION_INT32, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_ETHER_ENCAP, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
|
||||
{DHCP4_TAG_TCP_TTL, DHCP_OPTION_INT8, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_KEEP_INTERVAL, DHCP_OPTION_INT32, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_KEEP_GARBAGE, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
|
||||
{DHCP4_TAG_NIS_DOMAIN, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_NIS_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_NTP_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_VENDOR, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_NBNS, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_NBDD, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_NBTYPE, DHCP_OPTION_INT8, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_NBSCOPE, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_XFONT, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_XDM, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
|
||||
{DHCP4_TAG_REQUEST_IP, DHCP_OPTION_IP, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_LEASE, DHCP_OPTION_INT32, 1, 1 , TRUE},
|
||||
{DHCP4_TAG_OVERLOAD, DHCP_OPTION_INT8, 1, 1 , TRUE},
|
||||
{DHCP4_TAG_MSG_TYPE, DHCP_OPTION_INT8, 1, 1 , TRUE},
|
||||
{DHCP4_TAG_SERVER_ID, DHCP_OPTION_IP, 1, 1 , TRUE},
|
||||
{DHCP4_TAG_PARA_LIST, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_MESSAGE, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_MAXMSG, DHCP_OPTION_INT16, 1, 1 , FALSE},
|
||||
{DHCP4_TAG_T1, DHCP_OPTION_INT32, 1, 1 , TRUE},
|
||||
{DHCP4_TAG_T2, DHCP_OPTION_INT32, 1, 1 , TRUE},
|
||||
{DHCP4_TAG_VENDOR_CLASS_ID,DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_CLIENT_ID, DHCP_OPTION_INT8, 2, -1 , FALSE},
|
||||
|
||||
{DHCP4_TAG_NISPLUS, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_NISPLUS_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
|
||||
{DHCP4_TAG_TFTP, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_BOOTFILE, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
|
||||
{DHCP4_TAG_MOBILEIP, DHCP_OPTION_IP, 0, -1 , FALSE},
|
||||
{DHCP4_TAG_SMTP, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_POP3, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_NNTP, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_WWW, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_FINGER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_IRC, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_STTALK, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP4_TAG_STDA, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
|
||||
{DHCP4_TAG_CLASSLESS_ROUTE,DHCP_OPTION_INT8, 5, -1 , FALSE},
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Binary search the DhcpOptionFormats array to find the format
|
||||
information about a specific option.
|
||||
|
||||
@param[in] Tag The option's tag.
|
||||
|
||||
@return The point to the option's format, NULL if not found.
|
||||
|
||||
**/
|
||||
DHCP_OPTION_FORMAT *
|
||||
DhcpFindOptionFormat (
|
||||
IN UINT8 Tag
|
||||
)
|
||||
{
|
||||
INTN Left;
|
||||
INTN Right;
|
||||
INTN Middle;
|
||||
|
||||
Left = 0;
|
||||
Right = sizeof (DhcpOptionFormats) / sizeof (DHCP_OPTION_FORMAT) - 1;
|
||||
|
||||
while (Right >= Left) {
|
||||
Middle = (Left + Right) / 2;
|
||||
|
||||
if (Tag == DhcpOptionFormats[Middle].Tag) {
|
||||
return &DhcpOptionFormats[Middle];
|
||||
}
|
||||
|
||||
if (Tag < DhcpOptionFormats[Middle].Tag) {
|
||||
Right = Middle - 1;
|
||||
} else {
|
||||
Left = Middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Validate whether a single DHCP option is valid according to its format.
|
||||
|
||||
@param[in] Format The option's format
|
||||
@param[in] OptValue The value of the option
|
||||
@param[in] Len The length of the option value
|
||||
|
||||
@retval TRUE The option is valid.
|
||||
@retval FALSE Otherwise.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
DhcpOptionIsValid (
|
||||
IN DHCP_OPTION_FORMAT *Format,
|
||||
IN UINT8 *OptValue,
|
||||
IN INTN Len
|
||||
)
|
||||
{
|
||||
INTN Unit;
|
||||
INTN Occur;
|
||||
INTN Index;
|
||||
|
||||
Unit = 0;
|
||||
|
||||
switch (Format->Type) {
|
||||
case DHCP_OPTION_SWITCH:
|
||||
case DHCP_OPTION_INT8:
|
||||
Unit = 1;
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_INT16:
|
||||
Unit = 2;
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_INT32:
|
||||
case DHCP_OPTION_IP:
|
||||
Unit = 4;
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_IPPAIR:
|
||||
Unit = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT (Unit != 0);
|
||||
|
||||
//
|
||||
// Validate that the option appears in the full units.
|
||||
//
|
||||
if ((Len % Unit) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Validate the occurance of the option unit is with in [MinOccur, MaxOccur]
|
||||
//
|
||||
Occur = Len / Unit;
|
||||
|
||||
if (((Format->MinOccur != -1) && (Occur < Format->MinOccur)) ||
|
||||
((Format->MaxOccur != -1) && (Occur > Format->MaxOccur))
|
||||
) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// If the option is of type switch, only 0/1 are valid values.
|
||||
//
|
||||
if (Format->Type == DHCP_OPTION_SWITCH) {
|
||||
for (Index = 0; Index < Occur; Index++) {
|
||||
if ((OptValue[Index] != 0) && (OptValue[Index] != 1)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Extract the client interested options, all the parameters are
|
||||
converted to host byte order.
|
||||
|
||||
@param[in] Tag The DHCP option tag
|
||||
@param[in] Len The length of the option
|
||||
@param[in] Data The value of the DHCP option
|
||||
@param[out] Para The variable to save the interested parameter
|
||||
|
||||
@retval EFI_SUCCESS The DHCP option is successfully extracted.
|
||||
@retval EFI_INVALID_PARAMETER The DHCP option is mal-formated
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpGetParameter (
|
||||
IN UINT8 Tag,
|
||||
IN INTN Len,
|
||||
IN UINT8 *Data,
|
||||
OUT DHCP_PARAMETER *Para
|
||||
)
|
||||
{
|
||||
switch (Tag) {
|
||||
case DHCP4_TAG_NETMASK:
|
||||
Para->NetMask = NetGetUint32 (Data);
|
||||
break;
|
||||
|
||||
case DHCP4_TAG_ROUTER:
|
||||
//
|
||||
// Return the first router to consumer which is the preferred one
|
||||
//
|
||||
Para->Router = NetGetUint32 (Data);
|
||||
break;
|
||||
|
||||
case DHCP4_TAG_LEASE:
|
||||
Para->Lease = NetGetUint32 (Data);
|
||||
break;
|
||||
|
||||
case DHCP4_TAG_OVERLOAD:
|
||||
Para->Overload = *Data;
|
||||
|
||||
if ((Para->Overload < 1) || (Para->Overload > 3)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP4_TAG_MSG_TYPE:
|
||||
Para->DhcpType = *Data;
|
||||
|
||||
if ((Para->DhcpType < 1) || (Para->DhcpType > 9)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP4_TAG_SERVER_ID:
|
||||
Para->ServerId = NetGetUint32 (Data);
|
||||
break;
|
||||
|
||||
case DHCP4_TAG_T1:
|
||||
Para->T1 = NetGetUint32 (Data);
|
||||
break;
|
||||
|
||||
case DHCP4_TAG_T2:
|
||||
Para->T2 = NetGetUint32 (Data);
|
||||
break;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Inspect all the options in a single buffer. DHCP options may be contained
|
||||
in several buffers, such as the BOOTP options filed, boot file or server
|
||||
name. Each option buffer is required to end with DHCP4_TAG_EOP.
|
||||
|
||||
@param[in] Buffer The buffer which contains DHCP options
|
||||
@param[in] BufLen The length of the buffer
|
||||
@param[in] Check The callback function for each option found
|
||||
@param[in] Context The opaque parameter for the Check
|
||||
@param[out] Overload Variable to save the value of DHCP4_TAG_OVERLOAD
|
||||
option.
|
||||
|
||||
@retval EFI_SUCCESS All the options are valid
|
||||
@retval EFI_INVALID_PARAMETER The options are mal-formated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpIterateBufferOptions (
|
||||
IN UINT8 *Buffer,
|
||||
IN INTN BufLen,
|
||||
IN DHCP_CHECK_OPTION Check OPTIONAL,
|
||||
IN VOID *Context,
|
||||
OUT UINT8 *Overload OPTIONAL
|
||||
)
|
||||
{
|
||||
INTN Cur;
|
||||
UINT8 Tag;
|
||||
UINT8 Len;
|
||||
|
||||
Cur = 0;
|
||||
|
||||
while (Cur < BufLen) {
|
||||
Tag = Buffer[Cur];
|
||||
|
||||
if (Tag == DHCP4_TAG_PAD) {
|
||||
Cur++;
|
||||
continue;
|
||||
} else if (Tag == DHCP4_TAG_EOP) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Cur++;
|
||||
|
||||
if (Cur == BufLen) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Len = Buffer[Cur++];
|
||||
|
||||
if (Cur + Len > BufLen) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Tag == DHCP4_TAG_OVERLOAD) && (Overload != NULL)) {
|
||||
if (Len != 1) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*Overload = Buffer[Cur];
|
||||
}
|
||||
|
||||
if ((Check != NULL) && EFI_ERROR (Check (Tag, Len, Buffer + Cur, Context))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Cur += Len;
|
||||
}
|
||||
|
||||
//
|
||||
// Each option buffer is expected to end with an EOP
|
||||
//
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Iterate through a DHCP message to visit each option. First inspect
|
||||
all the options in the OPTION field. Then if overloaded, inspect
|
||||
the options in FILENAME and SERVERNAME fields. One option may be
|
||||
encoded in several places. See RFC 3396 Encoding Long Options in DHCP
|
||||
|
||||
@param[in] Packet The DHCP packet to check the options for
|
||||
@param[in] Check The callback function to be called for each option
|
||||
found
|
||||
@param[in] Context The opaque parameter for Check
|
||||
|
||||
@retval EFI_SUCCESS The DHCP packet's options are well formated
|
||||
@retval EFI_INVALID_PARAMETER The DHCP packet's options are not well formated
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpIterateOptions (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
IN DHCP_CHECK_OPTION Check OPTIONAL,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 Overload;
|
||||
|
||||
Overload = 0;
|
||||
|
||||
Status = DhcpIterateBufferOptions (
|
||||
Packet->Dhcp4.Option,
|
||||
Packet->Length - sizeof (EFI_DHCP4_HEADER) - sizeof (UINT32),
|
||||
Check,
|
||||
Context,
|
||||
&Overload
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ((Overload == DHCP_OVERLOAD_FILENAME) || (Overload == DHCP_OVERLOAD_BOTH)) {
|
||||
Status = DhcpIterateBufferOptions (
|
||||
(UINT8 *) Packet->Dhcp4.Header.BootFileName,
|
||||
128,
|
||||
Check,
|
||||
Context,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Overload == DHCP_OVERLOAD_SVRNAME) || (Overload == DHCP_OVERLOAD_BOTH)) {
|
||||
Status = DhcpIterateBufferOptions (
|
||||
(UINT8 *) Packet->Dhcp4.Header.ServerName,
|
||||
64,
|
||||
Check,
|
||||
Context,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Call back function to DhcpIterateOptions to compute each option's
|
||||
length. It just adds the data length of all the occurances of this
|
||||
Tag. Context is an array of 256 DHCP_OPTION_COUNT.
|
||||
|
||||
@param[in] Tag The current option to check
|
||||
@param[in] Len The length of the option data
|
||||
@param[in] Data The option data
|
||||
@param[in] Context The context, which is a array of 256
|
||||
DHCP_OPTION_COUNT.
|
||||
|
||||
@retval EFI_SUCCESS It always returns EFI_SUCCESS.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpGetOptionLen (
|
||||
IN UINT8 Tag,
|
||||
IN UINT8 Len,
|
||||
IN UINT8 *Data,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
DHCP_OPTION_COUNT *OpCount;
|
||||
|
||||
OpCount = (DHCP_OPTION_COUNT *) Context;
|
||||
OpCount[Tag].Offset = (UINT16) (OpCount[Tag].Offset + Len);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Call back function to DhcpIterateOptions to consolidate each option's
|
||||
data. There are maybe several occurrence of the same option.
|
||||
|
||||
@param[in] Tag The option to consolidate its data
|
||||
@param[in] Len The length of option data
|
||||
@param[in] Data The data of the option's current occurance
|
||||
@param[in] Context The context, which is DHCP_OPTION_CONTEXT. This
|
||||
array is just a wrap to pass THREE parameters.
|
||||
|
||||
@retval EFI_SUCCESS It always returns EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpFillOption (
|
||||
IN UINT8 Tag,
|
||||
IN UINT8 Len,
|
||||
IN UINT8 *Data,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
DHCP_OPTION_CONTEXT *OptContext;
|
||||
DHCP_OPTION_COUNT *OptCount;
|
||||
DHCP_OPTION *Options;
|
||||
UINT8 *Buf;
|
||||
UINT8 Index;
|
||||
|
||||
OptContext = (DHCP_OPTION_CONTEXT *) Context;
|
||||
|
||||
OptCount = OptContext->OpCount;
|
||||
Index = OptCount[Tag].Index;
|
||||
Options = OptContext->Options;
|
||||
Buf = OptContext->Buf;
|
||||
|
||||
if (Options[Index].Data == NULL) {
|
||||
Options[Index].Tag = Tag;
|
||||
Options[Index].Data = Buf + OptCount[Tag].Offset;
|
||||
}
|
||||
|
||||
CopyMem (Buf + OptCount[Tag].Offset, Data, Len);
|
||||
|
||||
OptCount[Tag].Offset = (UINT16) (OptCount[Tag].Offset + Len);
|
||||
Options[Index].Len = (UINT16) (Options[Index].Len + Len);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the options of a DHCP packet. It supports RFC 3396: Encoding
|
||||
Long Options in DHCP. That is, it will combine all the option value
|
||||
of all the occurances of each option.
|
||||
A little bit of implemenation:
|
||||
It adopts the "Key indexed counting" algorithm. First, it allocates
|
||||
an array of 256 DHCP_OPTION_COUNTs because DHCP option tag is encoded
|
||||
as a UINT8. It then iterates the DHCP packet to get data length of
|
||||
each option by calling DhcpIterOptions with DhcpGetOptionLen. Now, it
|
||||
knows the number of present options and their length. It allocates a
|
||||
array of DHCP_OPTION and a continuous buffer after the array to put
|
||||
all the options' data. Each option's data is pointed to by the Data
|
||||
field in DHCP_OPTION structure. At last, it call DhcpIterateOptions
|
||||
with DhcpFillOption to fill each option's data to its position in the
|
||||
buffer.
|
||||
|
||||
@param[in] Packet The DHCP packet to parse the options
|
||||
@param[out] Count The number of valid dhcp options present in the
|
||||
packet
|
||||
@param[out] OptionPoint The array that contains the DHCP options. Caller
|
||||
should free it.
|
||||
|
||||
@retval EFI_NOT_FOUND Cannot find any option.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to parse the packet.
|
||||
@retval EFI_INVALID_PARAMETER The options are mal-formated
|
||||
@retval EFI_SUCCESS The options are parsed into OptionPoint
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpParseOption (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
OUT INTN *Count,
|
||||
OUT DHCP_OPTION **OptionPoint
|
||||
)
|
||||
{
|
||||
DHCP_OPTION_CONTEXT Context;
|
||||
DHCP_OPTION *Options;
|
||||
DHCP_OPTION_COUNT *OptCount;
|
||||
EFI_STATUS Status;
|
||||
UINT16 TotalLen;
|
||||
INTN OptNum;
|
||||
INTN Index;
|
||||
|
||||
ASSERT ((Count != NULL) && (OptionPoint != NULL));
|
||||
|
||||
//
|
||||
// First compute how many options and how long each option is
|
||||
// with the "Key indexed counting" algorithms.
|
||||
//
|
||||
OptCount = AllocateZeroPool (DHCP_MAX_OPTIONS * sizeof (DHCP_OPTION_COUNT));
|
||||
|
||||
if (OptCount == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = DhcpIterateOptions (Packet, DhcpGetOptionLen, OptCount);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Before the loop, Offset is the length of the option. After loop,
|
||||
// OptCount[Index].Offset specifies the offset into the continuous
|
||||
// option value buffer to put the data.
|
||||
//
|
||||
TotalLen = 0;
|
||||
OptNum = 0;
|
||||
|
||||
for (Index = 0; Index < DHCP_MAX_OPTIONS; Index++) {
|
||||
if (OptCount[Index].Offset != 0) {
|
||||
OptCount[Index].Index = (UINT8) OptNum;
|
||||
|
||||
TotalLen = (UINT16) (TotalLen + OptCount[Index].Offset);
|
||||
OptCount[Index].Offset = (UINT16) (TotalLen - OptCount[Index].Offset);
|
||||
|
||||
OptNum++;
|
||||
}
|
||||
}
|
||||
|
||||
*Count = OptNum;
|
||||
*OptionPoint = NULL;
|
||||
|
||||
if (OptNum == 0) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate a buffer to hold the DHCP options, and after that, a
|
||||
// continuous buffer to put all the options' data.
|
||||
//
|
||||
Options = AllocateZeroPool ((UINTN) (OptNum * sizeof (DHCP_OPTION)) + TotalLen);
|
||||
|
||||
if (Options == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Context.OpCount = OptCount;
|
||||
Context.Options = Options;
|
||||
Context.Buf = (UINT8 *) (Options + OptNum);
|
||||
|
||||
Status = DhcpIterateOptions (Packet, DhcpFillOption, &Context);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Options);
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
*OptionPoint = Options;
|
||||
|
||||
ON_EXIT:
|
||||
FreePool (OptCount);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Validate the packet's options. If necessary, allocate
|
||||
and fill in the interested parameters.
|
||||
|
||||
@param[in] Packet The packet to validate the options
|
||||
@param[out] Para The variable to save the DHCP parameters.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to validate the packet.
|
||||
@retval EFI_INVALID_PARAMETER The options are mal-formated
|
||||
@retval EFI_SUCCESS The options are parsed into OptionPoint
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpValidateOptions (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
OUT DHCP_PARAMETER **Para OPTIONAL
|
||||
)
|
||||
{
|
||||
DHCP_PARAMETER Parameter;
|
||||
DHCP_OPTION_FORMAT *Format;
|
||||
DHCP_OPTION *AllOption;
|
||||
DHCP_OPTION *Option;
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN Updated;
|
||||
INTN Count;
|
||||
INTN Index;
|
||||
|
||||
if (Para != NULL) {
|
||||
*Para = NULL;
|
||||
}
|
||||
|
||||
AllOption = NULL;
|
||||
|
||||
Status = DhcpParseOption (Packet, &Count, &AllOption);
|
||||
if (EFI_ERROR (Status) || (Count == 0)) {
|
||||
return Status;
|
||||
}
|
||||
ASSERT (AllOption != NULL);
|
||||
|
||||
Updated = FALSE;
|
||||
ZeroMem (&Parameter, sizeof (Parameter));
|
||||
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
Option = &AllOption[Index];
|
||||
|
||||
//
|
||||
// Find the format of the option then validate it.
|
||||
//
|
||||
Format = DhcpFindOptionFormat (Option->Tag);
|
||||
|
||||
if (Format == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!DhcpOptionIsValid (Format, Option->Data, Option->Len)) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the client interested parameters
|
||||
//
|
||||
if (Format->Alert && (Para != NULL)) {
|
||||
Updated = TRUE;
|
||||
Status = DhcpGetParameter (Option->Tag, Option->Len, Option->Data, &Parameter);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Updated && (Para != NULL)) {
|
||||
*Para = AllocateCopyPool (sizeof (DHCP_PARAMETER), &Parameter);
|
||||
if (*Para == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
FreePool (AllOption);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Append an option to the memory, if the option is longer than
|
||||
255 bytes, splits it into several options.
|
||||
|
||||
@param[out] Buf The buffer to append the option to
|
||||
@param[in] Tag The option's tag
|
||||
@param[in] DataLen The length of the option's data
|
||||
@param[in] Data The option's data
|
||||
|
||||
@return The position to append the next option
|
||||
|
||||
**/
|
||||
UINT8 *
|
||||
DhcpAppendOption (
|
||||
OUT UINT8 *Buf,
|
||||
IN UINT8 Tag,
|
||||
IN UINT16 DataLen,
|
||||
IN UINT8 *Data
|
||||
)
|
||||
{
|
||||
INTN Index;
|
||||
INTN Len;
|
||||
|
||||
ASSERT (DataLen != 0);
|
||||
|
||||
for (Index = 0; Index < (DataLen + 254) / 255; Index++) {
|
||||
Len = MIN (255, DataLen - Index * 255);
|
||||
|
||||
*(Buf++) = Tag;
|
||||
*(Buf++) = (UINT8) Len;
|
||||
CopyMem (Buf, Data + Index * 255, (UINTN) Len);
|
||||
|
||||
Buf += Len;
|
||||
}
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build a new DHCP packet from a seed packet. Options may be deleted or
|
||||
appended. The caller should free the NewPacket when finished using it.
|
||||
|
||||
@param[in] SeedPacket The seed packet to start with
|
||||
@param[in] DeleteCount The number of options to delete
|
||||
@param[in] DeleteList The options to delete from the packet
|
||||
@param[in] AppendCount The number of options to append
|
||||
@param[in] AppendList The options to append to the packet
|
||||
@param[out] NewPacket The new packet, allocated and built by this
|
||||
function.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
||||
@retval EFI_INVALID_PARAMETER The options in SeekPacket are mal-formated
|
||||
@retval EFI_SUCCESS The packet is build.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpBuild (
|
||||
IN EFI_DHCP4_PACKET *SeedPacket,
|
||||
IN UINT32 DeleteCount,
|
||||
IN UINT8 *DeleteList OPTIONAL,
|
||||
IN UINT32 AppendCount,
|
||||
IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,
|
||||
OUT EFI_DHCP4_PACKET **NewPacket
|
||||
)
|
||||
{
|
||||
DHCP_OPTION *Mark;
|
||||
DHCP_OPTION *SeedOptions;
|
||||
EFI_DHCP4_PACKET *Packet;
|
||||
EFI_STATUS Status;
|
||||
INTN Count;
|
||||
UINT32 Index;
|
||||
UINT32 Len;
|
||||
UINT8 *Buf;
|
||||
|
||||
//
|
||||
// Use an array of DHCP_OPTION to mark the existance
|
||||
// and position of each valid options.
|
||||
//
|
||||
Mark = AllocatePool (sizeof (DHCP_OPTION) * DHCP_MAX_OPTIONS);
|
||||
|
||||
if (Mark == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < DHCP_MAX_OPTIONS; Index++) {
|
||||
Mark[Index].Tag = (UINT8) Index;
|
||||
Mark[Index].Len = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Get list of the options from the seed packet, then put
|
||||
// them to the mark array according to their tags.
|
||||
//
|
||||
SeedOptions = NULL;
|
||||
Status = DhcpParseOption (SeedPacket, &Count, &SeedOptions);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
if (SeedOptions != NULL) {
|
||||
for (Index = 0; Index < (UINT32) Count; Index++) {
|
||||
Mark[SeedOptions[Index].Tag] = SeedOptions[Index];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Mark the option's length is zero if it is in the DeleteList.
|
||||
//
|
||||
for (Index = 0; Index < DeleteCount; Index++) {
|
||||
Mark[DeleteList[Index]].Len = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Add or replace the option if it is in the append list.
|
||||
//
|
||||
for (Index = 0; Index < AppendCount; Index++) {
|
||||
Mark[AppendList[Index]->OpCode].Len = AppendList[Index]->Length;
|
||||
Mark[AppendList[Index]->OpCode].Data = AppendList[Index]->Data;
|
||||
}
|
||||
|
||||
//
|
||||
// compute the new packet length. No need to add 1 byte for
|
||||
// EOP option since EFI_DHCP4_PACKET includes one extra byte
|
||||
// for option. It is necessary to split the option if it is
|
||||
// longer than 255 bytes.
|
||||
//
|
||||
Len = sizeof (EFI_DHCP4_PACKET);
|
||||
|
||||
for (Index = 0; Index < DHCP_MAX_OPTIONS; Index++) {
|
||||
if (Mark[Index].Len != 0) {
|
||||
Len += ((Mark[Index].Len + 254) / 255) * 2 + Mark[Index].Len;
|
||||
}
|
||||
}
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
Packet = (EFI_DHCP4_PACKET *) AllocatePool (Len);
|
||||
|
||||
if (Packet == NULL) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Packet->Size = Len;
|
||||
Packet->Length = 0;
|
||||
CopyMem (&Packet->Dhcp4.Header, &SeedPacket->Dhcp4.Header, sizeof (Packet->Dhcp4.Header));
|
||||
Packet->Dhcp4.Magik = DHCP_OPTION_MAGIC;
|
||||
Buf = Packet->Dhcp4.Option;
|
||||
|
||||
for (Index = 0; Index < DHCP_MAX_OPTIONS; Index++) {
|
||||
if (Mark[Index].Len != 0) {
|
||||
Buf = DhcpAppendOption (Buf, Mark[Index].Tag, Mark[Index].Len, Mark[Index].Data);
|
||||
}
|
||||
}
|
||||
|
||||
*(Buf++) = DHCP4_TAG_EOP;
|
||||
Packet->Length = sizeof (EFI_DHCP4_HEADER) + sizeof (UINT32)
|
||||
+ (UINT32) (Buf - Packet->Dhcp4.Option);
|
||||
|
||||
*NewPacket = Packet;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
if (SeedOptions != NULL) {
|
||||
FreePool (SeedOptions);
|
||||
}
|
||||
|
||||
FreePool (Mark);
|
||||
return Status;
|
||||
}
|
228
NetworkPkg/Dhcp4Dxe/Dhcp4Option.h
Normal file
228
NetworkPkg/Dhcp4Dxe/Dhcp4Option.h
Normal file
@@ -0,0 +1,228 @@
|
||||
/** @file
|
||||
To validate, parse and process the DHCP options.
|
||||
|
||||
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_DHCP4_OPTION_H__
|
||||
#define __EFI_DHCP4_OPTION_H__
|
||||
|
||||
///
|
||||
/// DHCP option tags (types)
|
||||
///
|
||||
|
||||
#define DHCP_OPTION_MAGIC 0x63538263 // Network byte order
|
||||
#define DHCP_MAX_OPTIONS 256
|
||||
|
||||
|
||||
//
|
||||
// DHCP option types, this is used to validate the DHCP options.
|
||||
//
|
||||
#define DHCP_OPTION_SWITCH 1
|
||||
#define DHCP_OPTION_INT8 2
|
||||
#define DHCP_OPTION_INT16 3
|
||||
#define DHCP_OPTION_INT32 4
|
||||
#define DHCP_OPTION_IP 5
|
||||
#define DHCP_OPTION_IPPAIR 6
|
||||
|
||||
//
|
||||
// Value of DHCP overload option
|
||||
//
|
||||
#define DHCP_OVERLOAD_FILENAME 1
|
||||
#define DHCP_OVERLOAD_SVRNAME 2
|
||||
#define DHCP_OVERLOAD_BOTH 3
|
||||
|
||||
///
|
||||
/// The DHCP option structure. This structure extends the EFI_DHCP_OPTION
|
||||
/// structure to support options longer than 255 bytes, such as classless route.
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Tag;
|
||||
UINT16 Len;
|
||||
UINT8 *Data;
|
||||
} DHCP_OPTION;
|
||||
|
||||
///
|
||||
/// Structures used to parse the DHCP options with RFC3396 support.
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Index;
|
||||
UINT16 Offset;
|
||||
} DHCP_OPTION_COUNT;
|
||||
|
||||
typedef struct {
|
||||
DHCP_OPTION_COUNT *OpCount;
|
||||
DHCP_OPTION *Options;
|
||||
UINT8 *Buf;
|
||||
} DHCP_OPTION_CONTEXT;
|
||||
|
||||
///
|
||||
/// The options that matters to DHCP driver itself. The user of
|
||||
/// DHCP clients may be interested in other options, such as
|
||||
/// classless route, who can parse the DHCP offer to get them.
|
||||
///
|
||||
typedef struct {
|
||||
IP4_ADDR NetMask; // DHCP4_TAG_NETMASK
|
||||
IP4_ADDR Router; // DHCP4_TAG_ROUTER, only the first router is used
|
||||
|
||||
//
|
||||
// DHCP specific options
|
||||
//
|
||||
UINT8 DhcpType; // DHCP4_TAG_MSG_TYPE
|
||||
UINT8 Overload; // DHCP4_TAG_OVERLOAD
|
||||
IP4_ADDR ServerId; // DHCP4_TAG_SERVER_ID
|
||||
UINT32 Lease; // DHCP4_TAG_LEASE
|
||||
UINT32 T1; // DHCP4_TAG_T1
|
||||
UINT32 T2; // DHCP4_TAG_T2
|
||||
} DHCP_PARAMETER;
|
||||
|
||||
///
|
||||
/// Structure used to describe and validate the format of DHCP options.
|
||||
/// Type is the options' data type, such as DHCP_OPTION_INT8. MinOccur
|
||||
/// is the minium occurance of this data type. MaxOccur is defined
|
||||
/// similarly. If MaxOccur is -1, it means that there is no limit on the
|
||||
/// maximum occurance. Alert tells whether DHCP client should further
|
||||
/// inspect the option to parse DHCP_PARAMETER.
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Tag;
|
||||
INTN Type;
|
||||
INTN MinOccur;
|
||||
INTN MaxOccur;
|
||||
BOOLEAN Alert;
|
||||
} DHCP_OPTION_FORMAT;
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(*DHCP_CHECK_OPTION) (
|
||||
IN UINT8 Tag,
|
||||
IN UINT8 Len,
|
||||
IN UINT8 *Data,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Iterate through a DHCP message to visit each option. First inspect
|
||||
all the options in the OPTION field. Then if overloaded, inspect
|
||||
the options in FILENAME and SERVERNAME fields. One option may be
|
||||
encoded in several places. See RFC 3396 Encoding Long Options in DHCP
|
||||
|
||||
@param[in] Packet The DHCP packet to check the options for
|
||||
@param[in] Check The callback function to be called for each option
|
||||
found
|
||||
@param[in] Context The opaque parameter for Check
|
||||
|
||||
@retval EFI_SUCCESS The DHCP packet's options are well formated
|
||||
@retval EFI_INVALID_PARAMETER The DHCP packet's options are not well formated
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpIterateOptions (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
IN DHCP_CHECK_OPTION Check OPTIONAL,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Validate the packet's options. If necessary, allocate
|
||||
and fill in the interested parameters.
|
||||
|
||||
@param[in] Packet The packet to validate the options
|
||||
@param[out] Para The variable to save the DHCP parameters.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to validate the packet.
|
||||
@retval EFI_INVALID_PARAMETER The options are mal-formated
|
||||
@retval EFI_SUCCESS The options are parsed into OptionPoint
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpValidateOptions (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
OUT DHCP_PARAMETER **Para OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Parse the options of a DHCP packet. It supports RFC 3396: Encoding
|
||||
Long Options in DHCP. That is, it will combine all the option value
|
||||
of all the occurances of each option.
|
||||
A little bit of implemenation:
|
||||
It adopts the "Key indexed counting" algorithm. First, it allocates
|
||||
an array of 256 DHCP_OPTION_COUNTs because DHCP option tag is encoded
|
||||
as a UINT8. It then iterates the DHCP packet to get data length of
|
||||
each option by calling DhcpIterOptions with DhcpGetOptionLen. Now, it
|
||||
knows the number of present options and their length. It allocates a
|
||||
array of DHCP_OPTION and a continuous buffer after the array to put
|
||||
all the options' data. Each option's data is pointed to by the Data
|
||||
field in DHCP_OPTION structure. At last, it call DhcpIterateOptions
|
||||
with DhcpFillOption to fill each option's data to its position in the
|
||||
buffer.
|
||||
|
||||
@param[in] Packet The DHCP packet to parse the options
|
||||
@param[out] Count The number of valid dhcp options present in the
|
||||
packet
|
||||
@param[out] OptionPoint The array that contains the DHCP options. Caller
|
||||
should free it.
|
||||
|
||||
@retval EFI_NOT_FOUND Cannot find any option.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to parse the packet.
|
||||
@retval EFI_INVALID_PARAMETER The options are mal-formated
|
||||
@retval EFI_SUCCESS The options are parsed into OptionPoint
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpParseOption (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
OUT INTN *Count,
|
||||
OUT DHCP_OPTION **OptionPoint
|
||||
);
|
||||
|
||||
/**
|
||||
Append an option to the memory, if the option is longer than
|
||||
255 bytes, splits it into several options.
|
||||
|
||||
@param[out] Buf The buffer to append the option to
|
||||
@param[in] Tag The option's tag
|
||||
@param[in] DataLen The length of the option's data
|
||||
@param[in] Data The option's data
|
||||
|
||||
@return The position to append the next option
|
||||
|
||||
**/
|
||||
UINT8 *
|
||||
DhcpAppendOption (
|
||||
OUT UINT8 *Buf,
|
||||
IN UINT8 Tag,
|
||||
IN UINT16 DataLen,
|
||||
IN UINT8 *Data
|
||||
);
|
||||
|
||||
/**
|
||||
Build a new DHCP packet from a seed packet. Options may be deleted or
|
||||
appended. The caller should free the NewPacket when finished using it.
|
||||
|
||||
@param[in] SeedPacket The seed packet to start with
|
||||
@param[in] DeleteCount The number of options to delete
|
||||
@param[in] DeleteList The options to delete from the packet
|
||||
@param[in] AppendCount The number of options to append
|
||||
@param[in] AppendList The options to append to the packet
|
||||
@param[out] NewPacket The new packet, allocated and built by this
|
||||
function.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
||||
@retval EFI_INVALID_PARAMETER The options in SeekPacket are mal-formated
|
||||
@retval EFI_SUCCESS The packet is build.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpBuild (
|
||||
IN EFI_DHCP4_PACKET *SeedPacket,
|
||||
IN UINT32 DeleteCount,
|
||||
IN UINT8 *DeleteList OPTIONAL,
|
||||
IN UINT32 AppendCount,
|
||||
IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,
|
||||
OUT EFI_DHCP4_PACKET **NewPacket
|
||||
);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user