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:
428
NetworkPkg/Ip4Dxe/ComponentName.c
Normal file
428
NetworkPkg/Ip4Dxe/ComponentName.c
Normal file
@@ -0,0 +1,428 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.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
|
||||
Ip4ComponentNameGetDriverName (
|
||||
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
|
||||
Ip4ComponentNameGetControllerName (
|
||||
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 gIp4ComponentName = {
|
||||
Ip4ComponentNameGetDriverName,
|
||||
Ip4ComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name 2 Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIp4ComponentName2 = {
|
||||
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Ip4ComponentNameGetDriverName,
|
||||
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Ip4ComponentNameGetControllerName,
|
||||
"en"
|
||||
};
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIp4DriverNameTable[] = {
|
||||
{
|
||||
"eng;en",
|
||||
L"IP4 Network Service Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gIp4ControllerNameTable = NULL;
|
||||
|
||||
/**
|
||||
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
|
||||
Ip4ComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
{
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mIp4DriverNameTable,
|
||||
DriverName,
|
||||
(BOOLEAN)(This == &gIp4ComponentName)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Update the component name for the IP4 child handle.
|
||||
|
||||
@param Ip4[in] A pointer to the EFI_IP4_PROTOCOL.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS Update the ControllerNameTable of this instance successfully.
|
||||
@retval EFI_INVALID_PARAMETER The input parameter is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UpdateName (
|
||||
IN EFI_IP4_PROTOCOL *Ip4
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CHAR16 HandleName[80];
|
||||
EFI_IP4_MODE_DATA Ip4ModeData;
|
||||
|
||||
if (Ip4 == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Format the child name into the string buffer as:
|
||||
// IPv4 (SrcIP=127.0.0.1, DestIP=127.0.0.1)
|
||||
//
|
||||
Status = Ip4->GetModeData (Ip4, &Ip4ModeData, NULL, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (!Ip4ModeData.IsStarted || !Ip4ModeData.IsConfigured) {
|
||||
UnicodeSPrint (HandleName, sizeof (HandleName), L"IPv4 (Not started)");
|
||||
} else {
|
||||
UnicodeSPrint (HandleName, sizeof (HandleName),
|
||||
L"IPv4 (SrcIP=%d.%d.%d.%d)",
|
||||
Ip4ModeData.ConfigData.StationAddress.Addr[0],
|
||||
Ip4ModeData.ConfigData.StationAddress.Addr[1],
|
||||
Ip4ModeData.ConfigData.StationAddress.Addr[2],
|
||||
Ip4ModeData.ConfigData.StationAddress.Addr[3]
|
||||
);
|
||||
}
|
||||
|
||||
if (gIp4ControllerNameTable != NULL) {
|
||||
FreeUnicodeStringTable (gIp4ControllerNameTable);
|
||||
gIp4ControllerNameTable = NULL;
|
||||
}
|
||||
Status = AddUnicodeString2 (
|
||||
"eng",
|
||||
gIp4ComponentName.SupportedLanguages,
|
||||
&gIp4ControllerNameTable,
|
||||
HandleName,
|
||||
TRUE
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return AddUnicodeString2 (
|
||||
"en",
|
||||
gIp4ComponentName2.SupportedLanguages,
|
||||
&gIp4ControllerNameTable,
|
||||
HandleName,
|
||||
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
|
||||
Ip4ComponentNameGetControllerName (
|
||||
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_IP4_PROTOCOL *Ip4;
|
||||
|
||||
//
|
||||
// Only provide names for child handles.
|
||||
//
|
||||
if (ChildHandle == NULL) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure this driver produced ChildHandle
|
||||
//
|
||||
Status = EfiTestChildHandle (
|
||||
ControllerHandle,
|
||||
ChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve an instance of a produced protocol from ChildHandle
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
(VOID **)&Ip4,
|
||||
NULL,
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Update the component name for this child handle.
|
||||
//
|
||||
Status = UpdateName (Ip4);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
gIp4ControllerNameTable,
|
||||
ControllerName,
|
||||
(BOOLEAN)(This == &gIp4ComponentName)
|
||||
);
|
||||
}
|
||||
|
306
NetworkPkg/Ip4Dxe/Ip4Common.c
Normal file
306
NetworkPkg/Ip4Dxe/Ip4Common.c
Normal file
@@ -0,0 +1,306 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Return the cast type (Unicast/Boradcast) specific to an
|
||||
interface. All the addresses are host byte ordered.
|
||||
|
||||
@param[in] IpAddr The IP address to classify in host byte order
|
||||
@param[in] IpIf The interface that IpAddr received from
|
||||
|
||||
@return The cast type of this IP address specific to the interface.
|
||||
@retval IP4_LOCAL_HOST The IpAddr equals to the interface's address
|
||||
@retval IP4_SUBNET_BROADCAST The IpAddr is a directed subnet boradcast to the
|
||||
interface
|
||||
@retval IP4_NET_BROADCAST The IpAddr is a network broadcast to the interface
|
||||
@retval 0 Otherwise.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4GetNetCast (
|
||||
IN IP4_ADDR IpAddr,
|
||||
IN IP4_INTERFACE *IpIf
|
||||
)
|
||||
{
|
||||
if (IpAddr == IpIf->Ip) {
|
||||
return IP4_LOCAL_HOST;
|
||||
|
||||
} else if (IpAddr == IpIf->SubnetBrdcast) {
|
||||
return IP4_SUBNET_BROADCAST;
|
||||
|
||||
} else if (IpAddr == IpIf->NetBrdcast) {
|
||||
return IP4_NET_BROADCAST;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find the cast type of the packet related to the local host.
|
||||
This isn't the same as link layer cast type. For example, DHCP
|
||||
server may send local broadcast to the local unicast MAC.
|
||||
|
||||
@param[in] IpSb The IP4 service binding instance that received the
|
||||
packet
|
||||
@param[in] Dst The destination address in the packet (host byte
|
||||
order)
|
||||
@param[in] Src The source address in the packet (host byte order)
|
||||
|
||||
@return The cast type for the Dst, it will return on the first non-promiscuous
|
||||
cast type to a configured interface. If the packet doesn't match any of
|
||||
the interface, multicast address and local broadcast address are checked.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4GetHostCast (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
INTN Type;
|
||||
INTN Class;
|
||||
|
||||
Type = 0;
|
||||
|
||||
if (IpSb->MnpConfigData.EnablePromiscuousReceive) {
|
||||
Type = IP4_PROMISCUOUS;
|
||||
}
|
||||
|
||||
//
|
||||
// Go through the interface list of the IP service, most likely.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
//
|
||||
// Skip the unconfigured interface and invalid source address:
|
||||
// source address can't be broadcast.
|
||||
//
|
||||
if (!IpIf->Configured || IP4_IS_BROADCAST (Ip4GetNetCast (Src, IpIf))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((Class = Ip4GetNetCast (Dst, IpIf)) > Type) {
|
||||
return Class;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If it is local broadcast address. The source address must
|
||||
// be a unicast address on one of the direct connected network.
|
||||
// If it is a multicast address, accept it only if we are in
|
||||
// the group.
|
||||
//
|
||||
if (Dst == IP4_ALLONE_ADDRESS) {
|
||||
IpIf = Ip4FindNet (IpSb, Src);
|
||||
|
||||
if (IpIf != NULL && !IP4_IS_BROADCAST (Ip4GetNetCast (Src, IpIf))) {
|
||||
return IP4_LOCAL_BROADCAST;
|
||||
}
|
||||
|
||||
} else if (IP4_IS_MULTICAST (Dst) && Ip4FindGroup (&IpSb->IgmpCtrl, Dst) != NULL) {
|
||||
return IP4_MULTICAST;
|
||||
}
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find an interface whose configured IP address is Ip.
|
||||
|
||||
@param[in] IpSb The IP4 service binding instance
|
||||
@param[in] Ip The Ip address (host byte order) to find
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindInterface (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && (IpIf->Ip == Ip)) {
|
||||
return IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find an interface that Ip is on that connected network.
|
||||
|
||||
@param[in] IpSb The IP4 service binding instance
|
||||
@param[in] Ip The Ip address (host byte order) to find
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindNet (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && IP4_NET_EQUAL (Ip, IpIf->Ip, IpIf->SubnetMask)) {
|
||||
return IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find an interface of the service with the same Ip/Netmask pair.
|
||||
|
||||
@param[in] IpSb Ip4 service binding instance
|
||||
@param[in] Ip The Ip adress to find (host byte order)
|
||||
@param[in] Netmask The network to find (host byte order)
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindStationAddress (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip,
|
||||
IN IP4_ADDR Netmask
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && (IpIf->Ip == Ip) && (IpIf->SubnetMask == Netmask)) {
|
||||
return IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the MAC address for a multicast IP address. Call
|
||||
Mnp's McastIpToMac to find the MAC address in stead of
|
||||
hard code the NIC to be Ethernet.
|
||||
|
||||
@param[in] Mnp The Mnp instance to get the MAC address.
|
||||
@param[in] Multicast The multicast IP address to translate.
|
||||
@param[out] Mac The buffer to hold the translated address.
|
||||
|
||||
@retval EFI_SUCCESS if the multicast IP is successfully translated to a
|
||||
multicast MAC address.
|
||||
@retval other Otherwise some error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4GetMulticastMac (
|
||||
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
|
||||
IN IP4_ADDR Multicast,
|
||||
OUT EFI_MAC_ADDRESS *Mac
|
||||
)
|
||||
{
|
||||
EFI_IP_ADDRESS EfiIp;
|
||||
|
||||
EFI_IP4 (EfiIp.v4) = HTONL (Multicast);
|
||||
return Mnp->McastIpToMac (Mnp, FALSE, &EfiIp, Mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Convert the multibyte field in IP header's byter order.
|
||||
In spite of its name, it can also be used to convert from
|
||||
host to network byte order.
|
||||
|
||||
@param[in] Head The IP head to convert
|
||||
|
||||
@return Point to the converted IP head
|
||||
|
||||
**/
|
||||
IP4_HEAD *
|
||||
Ip4NtohHead (
|
||||
IN IP4_HEAD *Head
|
||||
)
|
||||
{
|
||||
Head->TotalLen = NTOHS (Head->TotalLen);
|
||||
Head->Id = NTOHS (Head->Id);
|
||||
Head->Fragment = NTOHS (Head->Fragment);
|
||||
Head->Src = NTOHL (Head->Src);
|
||||
Head->Dst = NTOHL (Head->Dst);
|
||||
|
||||
return Head;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Validate that Ip/Netmask pair is OK to be used as station
|
||||
address. Only continuous netmasks are supported. and check
|
||||
that StationAddress is a unicast address on the newtwork.
|
||||
|
||||
@param[in] Ip The IP address to validate.
|
||||
@param[in] Netmask The netmaks of the IP.
|
||||
|
||||
@retval TRUE The Ip/Netmask pair is valid.
|
||||
@retval FALSE The Ip/Netmask pair is invalid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip4StationAddressValid (
|
||||
IN IP4_ADDR Ip,
|
||||
IN IP4_ADDR Netmask
|
||||
)
|
||||
{
|
||||
//
|
||||
// Only support the station address with 0.0.0.0/0 to enable DHCP client.
|
||||
//
|
||||
if (Netmask == IP4_ALLZERO_ADDRESS) {
|
||||
return (BOOLEAN) (Ip == IP4_ALLZERO_ADDRESS);
|
||||
}
|
||||
|
||||
//
|
||||
// Only support the continuous net masks
|
||||
//
|
||||
if (NetGetMaskLength (Netmask) == (IP4_MASK_MAX + 1)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Station address can't be class D or class E address
|
||||
//
|
||||
if (NetGetIpClass (Ip) > IP4_ADDR_CLASSC) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return NetIp4IsUnicast (Ip, Netmask);
|
||||
}
|
217
NetworkPkg/Ip4Dxe/Ip4Common.h
Normal file
217
NetworkPkg/Ip4Dxe/Ip4Common.h
Normal file
@@ -0,0 +1,217 @@
|
||||
/** @file
|
||||
Common definition for IP4.
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_COMMON_H__
|
||||
#define __EFI_IP4_COMMON_H__
|
||||
|
||||
typedef struct _IP4_INTERFACE IP4_INTERFACE;
|
||||
typedef struct _IP4_PROTOCOL IP4_PROTOCOL;
|
||||
typedef struct _IP4_SERVICE IP4_SERVICE;
|
||||
|
||||
#define IP4_ETHER_PROTO 0x0800
|
||||
|
||||
//
|
||||
// The packet is received as link level broadcast/multicast/promiscuous.
|
||||
//
|
||||
#define IP4_LINK_BROADCAST 0x00000001
|
||||
#define IP4_LINK_MULTICAST 0x00000002
|
||||
#define IP4_LINK_PROMISC 0x00000004
|
||||
|
||||
//
|
||||
// IP4 address cast type classfication. Keep it true that any
|
||||
// type bigger than or equal to LOCAL_BROADCAST is broadcast.
|
||||
//
|
||||
#define IP4_PROMISCUOUS 1
|
||||
#define IP4_LOCAL_HOST 2
|
||||
#define IP4_MULTICAST 3
|
||||
#define IP4_LOCAL_BROADCAST 4 // Destination is 255.255.255.255
|
||||
#define IP4_SUBNET_BROADCAST 5
|
||||
#define IP4_NET_BROADCAST 6
|
||||
|
||||
//
|
||||
// IP4 header flags
|
||||
//
|
||||
#define IP4_HEAD_DF_MASK 0x4000
|
||||
#define IP4_HEAD_MF_MASK 0x2000
|
||||
#define IP4_HEAD_OFFSET_MASK 0x1fff
|
||||
|
||||
#define IP4_ALLZERO_ADDRESS 0x00000000u
|
||||
#define IP4_ALLONE_ADDRESS 0xFFFFFFFFu
|
||||
#define IP4_ALLSYSTEM_ADDRESS 0xE0000001u
|
||||
#define IP4_ALLROUTER_ADDRESS 0xE0000002u
|
||||
|
||||
///
|
||||
/// Compose the fragment field to be used in the IP4 header.
|
||||
///
|
||||
#define IP4_HEAD_FRAGMENT_FIELD(Df, Mf, Offset) \
|
||||
((UINT16)(((Df) ? IP4_HEAD_DF_MASK : 0) | ((Mf) ? IP4_HEAD_MF_MASK : 0) | (((Offset) >> 3) & IP4_HEAD_OFFSET_MASK)))
|
||||
|
||||
#define IP4_LAST_FRAGMENT(FragmentField) \
|
||||
(((FragmentField) & IP4_HEAD_MF_MASK) == 0)
|
||||
|
||||
#define IP4_FIRST_FRAGMENT(FragmentField) \
|
||||
((BOOLEAN)(((FragmentField) & IP4_HEAD_OFFSET_MASK) == 0))
|
||||
|
||||
#define IP4_DO_NOT_FRAGMENT(FragmentField) \
|
||||
((BOOLEAN)(((FragmentField) & IP4_HEAD_DF_MASK) == IP4_HEAD_DF_MASK))
|
||||
|
||||
#define IP4_IS_BROADCAST(CastType) ((CastType) >= IP4_LOCAL_BROADCAST)
|
||||
|
||||
///
|
||||
/// Conver the Microsecond to second. IP transmit/receive time is
|
||||
/// in the unit of microsecond. IP ticks once per second.
|
||||
///
|
||||
#define IP4_US_TO_SEC(Us) (((Us) + 999999) / 1000000)
|
||||
|
||||
/**
|
||||
Return the cast type (Unicast/Boradcast) specific to an
|
||||
interface. All the addresses are host byte ordered.
|
||||
|
||||
@param[in] IpAddr The IP address to classify in host byte order
|
||||
@param[in] IpIf The interface that IpAddr received from
|
||||
|
||||
@return The cast type of this IP address specific to the interface.
|
||||
@retval IP4_LOCAL_HOST The IpAddr equals to the interface's address
|
||||
@retval IP4_SUBNET_BROADCAST The IpAddr is a directed subnet boradcast to the
|
||||
interface
|
||||
@retval IP4_NET_BROADCAST The IpAddr is a network broadcast to the interface
|
||||
@retval 0 Otherwise.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4GetNetCast (
|
||||
IN IP4_ADDR IpAddr,
|
||||
IN IP4_INTERFACE *IpIf
|
||||
);
|
||||
|
||||
/**
|
||||
Find the cast type of the packet related to the local host.
|
||||
This isn't the same as link layer cast type. For example, DHCP
|
||||
server may send local broadcast to the local unicast MAC.
|
||||
|
||||
@param[in] IpSb The IP4 service binding instance that received the
|
||||
packet
|
||||
@param[in] Dst The destination address in the packet (host byte
|
||||
order)
|
||||
@param[in] Src The source address in the packet (host byte order)
|
||||
|
||||
@return The cast type for the Dst, it will return on the first non-promiscuous
|
||||
cast type to a configured interface. If the packet doesn't match any of
|
||||
the interface, multicast address and local broadcast address are checked.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4GetHostCast (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src
|
||||
);
|
||||
|
||||
/**
|
||||
Find an interface whose configured IP address is Ip.
|
||||
|
||||
@param[in] IpSb The IP4 service binding instance
|
||||
@param[in] Ip The Ip address (host byte order) to find
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindInterface (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip
|
||||
);
|
||||
|
||||
/**
|
||||
Find an interface that Ip is on that connected network.
|
||||
|
||||
@param[in] IpSb The IP4 service binding instance
|
||||
@param[in] Ip The Ip address (host byte order) to find
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindNet (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip
|
||||
);
|
||||
|
||||
/**
|
||||
Find an interface of the service with the same Ip/Netmask pair.
|
||||
|
||||
@param[in] IpSb Ip4 service binding instance
|
||||
@param[in] Ip The Ip adress to find (host byte order)
|
||||
@param[in] Netmask The network to find (host byte order)
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindStationAddress (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip,
|
||||
IN IP4_ADDR Netmask
|
||||
);
|
||||
|
||||
/**
|
||||
Get the MAC address for a multicast IP address. Call
|
||||
Mnp's McastIpToMac to find the MAC address in stead of
|
||||
hard code the NIC to be Ethernet.
|
||||
|
||||
@param[in] Mnp The Mnp instance to get the MAC address.
|
||||
@param[in] Multicast The multicast IP address to translate.
|
||||
@param[out] Mac The buffer to hold the translated address.
|
||||
|
||||
@retval EFI_SUCCESS if the multicast IP is successfully translated to a
|
||||
multicast MAC address.
|
||||
@retval other Otherwise some error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4GetMulticastMac (
|
||||
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
|
||||
IN IP4_ADDR Multicast,
|
||||
OUT EFI_MAC_ADDRESS *Mac
|
||||
);
|
||||
|
||||
/**
|
||||
Convert the multibyte field in IP header's byter order.
|
||||
In spite of its name, it can also be used to convert from
|
||||
host to network byte order.
|
||||
|
||||
@param[in] Head The IP head to convert
|
||||
|
||||
@return Point to the converted IP head
|
||||
|
||||
**/
|
||||
IP4_HEAD *
|
||||
Ip4NtohHead (
|
||||
IN IP4_HEAD *Head
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Validate that Ip/Netmask pair is OK to be used as station
|
||||
address. Only continuous netmasks are supported. and check
|
||||
that StationAddress is a unicast address on the newtwork.
|
||||
|
||||
@param[in] Ip The IP address to validate.
|
||||
@param[in] Netmask The netmaks of the IP.
|
||||
|
||||
@retval TRUE The Ip/Netmask pair is valid.
|
||||
@retval FALSE The Ip/Netmask pair is invalid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip4StationAddressValid (
|
||||
IN IP4_ADDR Ip,
|
||||
IN IP4_ADDR Netmask
|
||||
);
|
||||
|
||||
#endif
|
94
NetworkPkg/Ip4Dxe/Ip4Config2.vfr
Normal file
94
NetworkPkg/Ip4Dxe/Ip4Config2.vfr
Normal file
@@ -0,0 +1,94 @@
|
||||
/** @file
|
||||
Vfr file for IP4Dxe.
|
||||
|
||||
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
#include "Ip4NvData.h"
|
||||
|
||||
#define EFI_NETWORK_DEVICE_CLASS 0x04
|
||||
|
||||
formset
|
||||
guid = IP4_CONFIG2_NVDATA_GUID,
|
||||
title = STRING_TOKEN(STR_IP4_CONFIG2_FORM_TITLE),
|
||||
help = STRING_TOKEN(STR_IP4_CONFIG2_FORM_HELP),
|
||||
class = EFI_NETWORK_DEVICE_CLASS,
|
||||
subclass = 0x03,
|
||||
|
||||
varstore IP4_CONFIG2_IFR_NVDATA,
|
||||
name = IP4_CONFIG2_IFR_NVDATA,
|
||||
guid = IP4_CONFIG2_NVDATA_GUID;
|
||||
|
||||
form formid = FORMID_MAIN_FORM,
|
||||
title = STRING_TOKEN(STR_IP4_DEVICE_FORM_TITLE);
|
||||
|
||||
checkbox varid = IP4_CONFIG2_IFR_NVDATA.Configure,
|
||||
prompt = STRING_TOKEN(STR_IP4_CONFIGURE),
|
||||
help = STRING_TOKEN(STR_IP4_CONFIGURE_HELP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_ENABLE,
|
||||
endcheckbox;
|
||||
|
||||
suppressif ideqval IP4_CONFIG2_IFR_NVDATA.Configure == 0x00;
|
||||
|
||||
checkbox varid = IP4_CONFIG2_IFR_NVDATA.DhcpEnable,
|
||||
prompt = STRING_TOKEN(STR_IP4_ENABLE_DHCP),
|
||||
help = STRING_TOKEN(STR_IP4_ENABLE_DHCP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_DHCP_ENABLE,
|
||||
endcheckbox;
|
||||
endif;
|
||||
|
||||
suppressif ideqval IP4_CONFIG2_IFR_NVDATA.DhcpEnable == 0x01 OR ideqval IP4_CONFIG2_IFR_NVDATA.Configure == 0x00;
|
||||
|
||||
string varid = IP4_CONFIG2_IFR_NVDATA.StationAddress,
|
||||
prompt = STRING_TOKEN(STR_IP4_LOCAL_IP_ADDRESS),
|
||||
help = STRING_TOKEN(STR_IP4_IP_ADDRESS_HELP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_LOCAL_IP,
|
||||
minsize = IP_MIN_SIZE,
|
||||
maxsize = IP_MAX_SIZE,
|
||||
endstring;
|
||||
|
||||
string varid = IP4_CONFIG2_IFR_NVDATA.SubnetMask,
|
||||
prompt = STRING_TOKEN(STR_IP4_LOCAL_MASK),
|
||||
help = STRING_TOKEN(STR_IP4_MASK_HELP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_SUBNET_MASK,
|
||||
minsize = IP_MIN_SIZE,
|
||||
maxsize = IP_MAX_SIZE,
|
||||
endstring;
|
||||
|
||||
string varid = IP4_CONFIG2_IFR_NVDATA.GatewayAddress,
|
||||
prompt = STRING_TOKEN(STR_IP4_LOCAL_GATEWAY),
|
||||
help = STRING_TOKEN(STR_IP4_GATEWAY_HELP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_GATE_WAY,
|
||||
minsize = IP_MIN_SIZE,
|
||||
maxsize = IP_MAX_SIZE,
|
||||
endstring;
|
||||
|
||||
string varid = IP4_CONFIG2_IFR_NVDATA.DnsAddress,
|
||||
prompt = STRING_TOKEN(STR_IP4_LOCAL_DNS),
|
||||
help = STRING_TOKEN(STR_IP4_DNS_HELP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_DNS,
|
||||
minsize = IP_MIN_SIZE,
|
||||
maxsize = ADDRESS_STR_MAX_SIZE,
|
||||
endstring;
|
||||
|
||||
endif;
|
||||
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
text
|
||||
help = STRING_TOKEN(STR_SAVE_CHANGES),
|
||||
text = STRING_TOKEN(STR_SAVE_CHANGES),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_SAVE_CHANGES;
|
||||
|
||||
endform;
|
||||
|
||||
endformset;
|
||||
|
2168
NetworkPkg/Ip4Dxe/Ip4Config2Impl.c
Normal file
2168
NetworkPkg/Ip4Dxe/Ip4Config2Impl.c
Normal file
File diff suppressed because it is too large
Load Diff
294
NetworkPkg/Ip4Dxe/Ip4Config2Impl.h
Normal file
294
NetworkPkg/Ip4Dxe/Ip4Config2Impl.h
Normal file
@@ -0,0 +1,294 @@
|
||||
/** @file
|
||||
Definitions for EFI IPv4 Configuration II Protocol implementation.
|
||||
|
||||
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __IP4_CONFIG2_IMPL_H__
|
||||
#define __IP4_CONFIG2_IMPL_H__
|
||||
|
||||
#define IP4_CONFIG2_INSTANCE_SIGNATURE SIGNATURE_32 ('I', 'P', 'C', '2')
|
||||
#define IP4_FORM_CALLBACK_INFO_SIGNATURE SIGNATURE_32 ('I', 'F', 'C', 'I')
|
||||
|
||||
#define IP4_CONFIG2_VARIABLE_ATTRIBUTE (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)
|
||||
|
||||
#define DATA_ATTRIB_SIZE_FIXED 0x1
|
||||
#define DATA_ATTRIB_VOLATILE 0x2
|
||||
|
||||
#define DATA_ATTRIB_SET(Attrib, Bits) (BOOLEAN)((Attrib) & (Bits))
|
||||
#define SET_DATA_ATTRIB(Attrib, Bits) ((Attrib) |= (Bits))
|
||||
#define REMOVE_DATA_ATTRIB(Attrib, Bits) ((Attrib) &= (~Bits))
|
||||
|
||||
typedef struct _IP4_CONFIG2_INSTANCE IP4_CONFIG2_INSTANCE;
|
||||
|
||||
#define IP4_CONFIG2_INSTANCE_FROM_PROTOCOL(Proto) \
|
||||
CR ((Proto), \
|
||||
IP4_CONFIG2_INSTANCE, \
|
||||
Ip4Config2, \
|
||||
IP4_CONFIG2_INSTANCE_SIGNATURE \
|
||||
)
|
||||
|
||||
#define IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE(Instance) \
|
||||
CR ((Instance), \
|
||||
IP4_SERVICE, \
|
||||
Ip4Config2Instance, \
|
||||
IP4_SERVICE_SIGNATURE \
|
||||
)
|
||||
|
||||
#define IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Callback) \
|
||||
CR ((Callback), \
|
||||
IP4_CONFIG2_INSTANCE, \
|
||||
CallbackInfo, \
|
||||
IP4_CONFIG2_INSTANCE_SIGNATURE \
|
||||
)
|
||||
|
||||
#define IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(ConfigAccess) \
|
||||
CR ((ConfigAccess), \
|
||||
IP4_FORM_CALLBACK_INFO, \
|
||||
HiiConfigAccessProtocol, \
|
||||
IP4_FORM_CALLBACK_INFO_SIGNATURE \
|
||||
)
|
||||
|
||||
/**
|
||||
The prototype of work function for EfiIp4Config2SetData().
|
||||
|
||||
@param[in] Instance The pointer to the IP4 config2 instance data.
|
||||
@param[in] DataSize In bytes, the size of the buffer pointed to by Data.
|
||||
@param[in] Data The data buffer to set.
|
||||
|
||||
@retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type,
|
||||
8 bytes.
|
||||
@retval EFI_SUCCESS The specified configuration data for the EFI IPv4
|
||||
network stack was set successfully.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(*IP4_CONFIG2_SET_DATA) (
|
||||
IN IP4_CONFIG2_INSTANCE *Instance,
|
||||
IN UINTN DataSize,
|
||||
IN VOID *Data
|
||||
);
|
||||
|
||||
/**
|
||||
The prototype of work function for EfiIp4Config2GetData().
|
||||
|
||||
@param[in] Instance The pointer to the IP4 config2 instance data.
|
||||
@param[in, out] DataSize On input, in bytes, the size of Data. On output, in
|
||||
bytes, the size of buffer required to store the specified
|
||||
configuration data.
|
||||
@param[in] Data The data buffer in which the configuration data is returned.
|
||||
Ignored if DataSize is ZERO.
|
||||
|
||||
@retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
|
||||
configuration data, and the required size is
|
||||
returned in DataSize.
|
||||
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(*IP4_CONFIG2_GET_DATA) (
|
||||
IN IP4_CONFIG2_INSTANCE *Instance,
|
||||
IN OUT UINTN *DataSize,
|
||||
IN VOID *Data OPTIONAL
|
||||
);
|
||||
|
||||
typedef union {
|
||||
VOID *Ptr;
|
||||
EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo;
|
||||
EFI_IP4_CONFIG2_POLICY *Policy;
|
||||
EFI_IP4_CONFIG2_MANUAL_ADDRESS *ManualAddress;
|
||||
EFI_IPv4_ADDRESS *Gateway;
|
||||
EFI_IPv4_ADDRESS *DnsServers;
|
||||
} IP4_CONFIG2_DATA;
|
||||
|
||||
typedef struct {
|
||||
IP4_CONFIG2_SET_DATA SetData;
|
||||
IP4_CONFIG2_GET_DATA GetData;
|
||||
EFI_STATUS Status;
|
||||
UINT8 Attribute;
|
||||
NET_MAP EventMap;
|
||||
IP4_CONFIG2_DATA Data;
|
||||
UINTN DataSize;
|
||||
} IP4_CONFIG2_DATA_ITEM;
|
||||
|
||||
typedef struct {
|
||||
UINT16 Offset;
|
||||
UINT32 DataSize;
|
||||
EFI_IP4_CONFIG2_DATA_TYPE DataType;
|
||||
} IP4_CONFIG2_DATA_RECORD;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
//
|
||||
// heap data that contains the data for each data record.
|
||||
//
|
||||
// EFI_IP4_CONFIG2_POLICY Policy;
|
||||
// UINT32 ManualaddressCount;
|
||||
// UINT32 GatewayCount;
|
||||
// UINT32 DnsServersCount;
|
||||
// EFI_IP4_CONFIG2_MANUAL_ADDRESS ManualAddress[];
|
||||
// EFI_IPv4_ADDRESS Gateway[];
|
||||
// EFI_IPv4_ADDRESS DnsServers[];
|
||||
//
|
||||
typedef struct {
|
||||
UINT16 Checksum;
|
||||
UINT16 DataRecordCount;
|
||||
IP4_CONFIG2_DATA_RECORD DataRecord[1];
|
||||
} IP4_CONFIG2_VARIABLE;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
typedef struct {
|
||||
EFI_IP4_CONFIG2_POLICY Policy; ///< manual or automatic
|
||||
EFI_IP4_CONFIG2_MANUAL_ADDRESS *ManualAddress; ///< IP addresses
|
||||
UINT32 ManualAddressCount; ///< IP addresses count
|
||||
EFI_IPv4_ADDRESS *GatewayAddress; ///< Gateway address
|
||||
UINT32 GatewayAddressCount; ///< Gateway address count
|
||||
EFI_IPv4_ADDRESS *DnsAddress; ///< DNS server address
|
||||
UINT32 DnsAddressCount; ///< DNS server address count
|
||||
} IP4_CONFIG2_NVDATA;
|
||||
|
||||
typedef struct _IP4_FORM_CALLBACK_INFO {
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE ChildHandle;
|
||||
EFI_HII_CONFIG_ACCESS_PROTOCOL HiiConfigAccessProtocol;
|
||||
EFI_DEVICE_PATH_PROTOCOL *HiiVendorDevicePath;
|
||||
EFI_HII_HANDLE RegisteredHandle;
|
||||
} IP4_FORM_CALLBACK_INFO;
|
||||
|
||||
struct _IP4_CONFIG2_INSTANCE {
|
||||
UINT32 Signature;
|
||||
BOOLEAN Configured;
|
||||
LIST_ENTRY Link;
|
||||
UINT16 IfIndex;
|
||||
|
||||
EFI_IP4_CONFIG2_PROTOCOL Ip4Config2;
|
||||
|
||||
EFI_IP4_CONFIG2_INTERFACE_INFO InterfaceInfo;
|
||||
EFI_IP4_CONFIG2_POLICY Policy;
|
||||
IP4_CONFIG2_DATA_ITEM DataItem[Ip4Config2DataTypeMaximum];
|
||||
|
||||
EFI_EVENT Dhcp4SbNotifyEvent;
|
||||
VOID *Registration;
|
||||
EFI_HANDLE Dhcp4Handle;
|
||||
EFI_DHCP4_PROTOCOL *Dhcp4;
|
||||
BOOLEAN DhcpSuccess;
|
||||
BOOLEAN OtherInfoOnly;
|
||||
EFI_EVENT Dhcp4Event;
|
||||
UINT32 FailedIaAddressCount;
|
||||
EFI_IPv4_ADDRESS *DeclineAddress;
|
||||
UINT32 DeclineAddressCount;
|
||||
|
||||
IP4_FORM_CALLBACK_INFO CallbackInfo;
|
||||
|
||||
IP4_CONFIG2_NVDATA Ip4NvData;
|
||||
};
|
||||
|
||||
//
|
||||
// Configure the DHCP to request the routers and netmask
|
||||
// from server. The DHCP4_TAG_NETMASK is included in Head.
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
EFI_DHCP4_PACKET_OPTION Head;
|
||||
UINT8 Route;
|
||||
UINT8 Dns;
|
||||
} IP4_CONFIG2_DHCP4_OPTION;
|
||||
#pragma pack()
|
||||
|
||||
/**
|
||||
Read the configuration data from variable storage according to the VarName and
|
||||
gEfiIp4Config2ProtocolGuid. It checks the integrity of variable data. If the
|
||||
data is corrupted, it clears the variable data to ZERO. Othewise, it outputs the
|
||||
configuration data to IP4_CONFIG2_INSTANCE.
|
||||
|
||||
@param[in] VarName The pointer to the variable name
|
||||
@param[in, out] Instance The pointer to the IP4 config2 instance data.
|
||||
|
||||
@retval EFI_NOT_FOUND The variable can not be found or already corrupted.
|
||||
@retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
|
||||
@retval EFI_SUCCESS The configuration data was retrieved successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Config2ReadConfigData (
|
||||
IN CHAR16 *VarName,
|
||||
IN OUT IP4_CONFIG2_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Start the DHCP configuration for this IP service instance.
|
||||
It will locates the EFI_IP4_CONFIG2_PROTOCOL, then start the
|
||||
DHCP configuration.
|
||||
|
||||
@param[in] Instance The IP4 config2 instance to configure.
|
||||
|
||||
@retval EFI_SUCCESS The auto configuration is successfully started.
|
||||
@retval Others Failed to start auto configuration.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4StartAutoConfig (
|
||||
IN IP4_CONFIG2_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize an IP4_CONFIG2_INSTANCE.
|
||||
|
||||
@param[out] Instance The buffer of IP4_CONFIG2_INSTANCE to be initialized.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
|
||||
@retval EFI_SUCCESS The IP4_CONFIG2_INSTANCE initialized successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Config2InitInstance (
|
||||
OUT IP4_CONFIG2_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Release an IP4_CONFIG2_INSTANCE.
|
||||
|
||||
@param[in, out] Instance The buffer of IP4_CONFIG2_INSTANCE to be freed.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4Config2CleanInstance (
|
||||
IN OUT IP4_CONFIG2_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.
|
||||
|
||||
@param Event The event that is signalled.
|
||||
@param Context The IP4 service binding instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip4AutoReconfigCallBack (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Destroy the Dhcp4 child in IP4_CONFIG2_INSTANCE and release the resources.
|
||||
|
||||
@param[in, out] Instance The buffer of IP4 config2 instance to be freed.
|
||||
|
||||
@retval EFI_SUCCESS The child was successfully destroyed.
|
||||
@retval Others Failed to destroy the child.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Config2DestroyDhcp4 (
|
||||
IN OUT IP4_CONFIG2_INSTANCE *Instance
|
||||
);
|
||||
|
||||
#endif
|
1444
NetworkPkg/Ip4Dxe/Ip4Config2Nv.c
Normal file
1444
NetworkPkg/Ip4Dxe/Ip4Config2Nv.c
Normal file
File diff suppressed because it is too large
Load Diff
45
NetworkPkg/Ip4Dxe/Ip4Config2Nv.h
Normal file
45
NetworkPkg/Ip4Dxe/Ip4Config2Nv.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/** @file
|
||||
The header file of IP4Config2Nv.c
|
||||
|
||||
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _IP4_CONFIG2NV_H_
|
||||
#define _IP4_CONFIG2NV_H_
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
extern UINT8 Ip4Config2Bin[];
|
||||
extern UINT8 Ip4DxeStrings[];
|
||||
|
||||
#define NIC_ITEM_CONFIG_SIZE (sizeof (IP4_CONFIG2_INSTANCE) + (sizeof (EFI_IPv4_ADDRESS) * MAX_IP4_CONFIG_DNS))
|
||||
|
||||
/**
|
||||
Install HII Config Access protocol for network device and allocate resource.
|
||||
|
||||
@param[in, out] Instance The IP4 config2 Instance.
|
||||
|
||||
@retval EFI_SUCCESS The HII Config Access protocol is installed.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
||||
@retval Others Other errors as indicated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Config2FormInit (
|
||||
IN OUT IP4_CONFIG2_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Uninstall the HII Config Access protocol for network devices and free up the resources.
|
||||
|
||||
@param[in, out] Instance The IP4 config2 instance to unload a form.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4Config2FormUnload (
|
||||
IN OUT IP4_CONFIG2_INSTANCE *Instance
|
||||
);
|
||||
|
||||
#endif
|
1069
NetworkPkg/Ip4Dxe/Ip4Driver.c
Normal file
1069
NetworkPkg/Ip4Dxe/Ip4Driver.c
Normal file
File diff suppressed because it is too large
Load Diff
184
NetworkPkg/Ip4Dxe/Ip4Driver.h
Normal file
184
NetworkPkg/Ip4Dxe/Ip4Driver.h
Normal file
@@ -0,0 +1,184 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_DRIVER_H__
|
||||
#define __EFI_IP4_DRIVER_H__
|
||||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
|
||||
extern EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding;
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gIp4ComponentName;
|
||||
extern EFI_COMPONENT_NAME2_PROTOCOL gIp4ComponentName2;
|
||||
extern EFI_UNICODE_STRING_TABLE *gIp4ControllerNameTable;
|
||||
|
||||
typedef struct {
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
UINTN NumberOfChildren;
|
||||
EFI_HANDLE *ChildHandleBuffer;
|
||||
} IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT;
|
||||
|
||||
//
|
||||
// Function prototype for the driver's entry point
|
||||
//
|
||||
/**
|
||||
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.
|
||||
|
||||
The entry point for IP4 driver which install the driver
|
||||
binding and component name protocol on its image.
|
||||
|
||||
@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
|
||||
Ip4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
//
|
||||
// Function prototypes for the Drivr Binding Protocol
|
||||
//
|
||||
/**
|
||||
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
|
||||
Ip4DriverBindingSupported (
|
||||
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
|
||||
Ip4DriverBindingStart (
|
||||
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
|
||||
Ip4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
//
|
||||
// Function prototypes for the ServiceBinding Protocol
|
||||
//
|
||||
/**
|
||||
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
|
||||
Ip4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN OUT 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
|
||||
Ip4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
);
|
||||
#endif
|
109
NetworkPkg/Ip4Dxe/Ip4Dxe.inf
Normal file
109
NetworkPkg/Ip4Dxe/Ip4Dxe.inf
Normal file
@@ -0,0 +1,109 @@
|
||||
## @file
|
||||
# This module produces EFI IPv4 Protocol and EFI IPv4 Service Binding Protocol.
|
||||
#
|
||||
# This module produces EFI IPv4 Protocol upon EFI MNP Protocol and EFI ARP Protocol,
|
||||
# to provide basic network IPv4 packet I/O services, which includes support for a
|
||||
# subset of the Internet Control Message Protocol (ICMP) and may include support for
|
||||
# the Internet Group Management Protocol (IGMP).
|
||||
#
|
||||
# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = Ip4Dxe
|
||||
MODULE_UNI_FILE = Ip4Dxe.uni
|
||||
FILE_GUID = 9FB1A1F3-3B71-4324-B39A-745CBB015FFF
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = Ip4DriverEntryPoint
|
||||
UNLOAD_IMAGE = NetLibDefaultUnload
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 EBC
|
||||
#
|
||||
# DRIVER_BINDING = gIp4DriverBinding
|
||||
# COMPONENT_NAME = gIp4ComponentName
|
||||
# COMPONENT_NAME2 = gIp4ComponentName2
|
||||
#
|
||||
|
||||
[Sources]
|
||||
Ip4Driver.c
|
||||
Ip4Option.h
|
||||
Ip4Route.h
|
||||
Ip4If.c
|
||||
Ip4Igmp.h
|
||||
Ip4Output.c
|
||||
Ip4Icmp.c
|
||||
Ip4Igmp.c
|
||||
Ip4Impl.c
|
||||
Ip4Common.h
|
||||
Ip4Impl.h
|
||||
Ip4Driver.h
|
||||
Ip4Common.c
|
||||
Ip4If.h
|
||||
Ip4Option.c
|
||||
Ip4Output.h
|
||||
ComponentName.c
|
||||
Ip4Input.h
|
||||
Ip4Route.c
|
||||
Ip4Icmp.h
|
||||
Ip4Input.c
|
||||
Ip4Config2Impl.c
|
||||
Ip4Config2Impl.h
|
||||
Ip4Config2.vfr
|
||||
Ip4DxeStrings.uni
|
||||
Ip4NvData.h
|
||||
Ip4Config2Nv.h
|
||||
Ip4Config2Nv.c
|
||||
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiLib
|
||||
BaseLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
DebugLib
|
||||
NetLib
|
||||
DpcLib
|
||||
HiiLib
|
||||
PrintLib
|
||||
DevicePathLib
|
||||
UefiHiiServicesLib
|
||||
|
||||
[Protocols]
|
||||
## BY_START
|
||||
## UNDEFINED # variable
|
||||
gEfiIp4ServiceBindingProtocolGuid
|
||||
gEfiIp4ProtocolGuid ## BY_START
|
||||
gEfiManagedNetworkServiceBindingProtocolGuid ## TO_START
|
||||
gEfiManagedNetworkProtocolGuid ## TO_START
|
||||
gEfiArpServiceBindingProtocolGuid ## TO_START
|
||||
gEfiIp4Config2ProtocolGuid ## BY_START
|
||||
gEfiArpProtocolGuid ## TO_START
|
||||
gEfiDhcp4ServiceBindingProtocolGuid ## TO_START
|
||||
gEfiDhcp4ProtocolGuid ## TO_START
|
||||
gEfiIpSec2ProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiHiiConfigAccessProtocolGuid ## BY_START
|
||||
gEfiDevicePathProtocolGuid ## TO_START
|
||||
|
||||
[Guids]
|
||||
## SOMETIMES_CONSUMES ## GUID # HiiIsConfigHdrMatch EFI_NIC_IP4_CONFIG_VARIABLE
|
||||
## SOMETIMES_PRODUCES ## GUID # HiiConstructConfigHdr EFI_NIC_IP4_CONFIG_VARIABLE
|
||||
## SOMETIMES_PRODUCES ## GUID # HiiGetBrowserData EFI_NIC_IP4_CONFIG_VARIABLE
|
||||
## SOMETIMES_CONSUMES ## HII
|
||||
gIp4Config2NvDataGuid
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
Ip4DxeExtra.uni
|
||||
|
19
NetworkPkg/Ip4Dxe/Ip4Dxe.uni
Normal file
19
NetworkPkg/Ip4Dxe/Ip4Dxe.uni
Normal file
@@ -0,0 +1,19 @@
|
||||
// /** @file
|
||||
// This module produces EFI IPv4 Protocol and EFI IPv4 Service Binding Protocol.
|
||||
//
|
||||
// This module produces EFI IPv4 Protocol upon EFI MNP Protocol and EFI ARP Protocol,
|
||||
// to provide basic network IPv4 packet I/O services, which includes support for a
|
||||
// subset of the Internet Control Message Protocol (ICMP) and may include support for
|
||||
// the Internet Group Management Protocol (IGMP).
|
||||
//
|
||||
// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "Produces EFI IPv4 Protocol and EFI IPv4 Service Binding Protocol"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "This module produces EFI IPv4 Protocol upon EFI MNP Protocol and EFI ARP Protocol to provide basic network IPv4 packet I/O services, which includes support for a subset of the Internet Control Message Protocol (ICMP), and may include support for the Internet Group Management Protocol (IGMP)."
|
||||
|
14
NetworkPkg/Ip4Dxe/Ip4DxeExtra.uni
Normal file
14
NetworkPkg/Ip4Dxe/Ip4DxeExtra.uni
Normal file
@@ -0,0 +1,14 @@
|
||||
// /** @file
|
||||
// Ip4Dxe 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
|
||||
"IP v4 DXE Driver"
|
||||
|
||||
|
30
NetworkPkg/Ip4Dxe/Ip4DxeStrings.uni
Normal file
30
NetworkPkg/Ip4Dxe/Ip4DxeStrings.uni
Normal file
@@ -0,0 +1,30 @@
|
||||
// /** @file
|
||||
// String definitions for Ip4Config2 formset
|
||||
|
||||
// Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
//**/
|
||||
|
||||
|
||||
/=#
|
||||
|
||||
#langdef en-US "English"
|
||||
|
||||
#string STR_IP4_CONFIG2_FORM_TITLE #language en-US "IPv4 Network Configuration"
|
||||
#string STR_IP4_CONFIG2_FORM_HELP #language en-US "Configure network parameters."
|
||||
#string STR_IP4_DEVICE_FORM_TITLE #language en-US ""
|
||||
#string STR_IP4_DEVICE_FORM_HELP #language en-US ""
|
||||
#string STR_IP4_CONFIGURE #language en-US "Configured"
|
||||
#string STR_IP4_CONFIGURE_HELP #language en-US "Indicate whether network address configured successfully or not."
|
||||
#string STR_IP4_ENABLE_DHCP #language en-US "Enable DHCP"
|
||||
#string STR_IP4_LOCAL_IP_ADDRESS #language en-US "Local IP Address"
|
||||
#string STR_IP4_IP_ADDRESS_HELP #language en-US "Enter IP address in dotted-decimal notation. Example: 192.168.10.12\r\n"
|
||||
#string STR_IP4_LOCAL_MASK #language en-US "Local NetMask"
|
||||
#string STR_IP4_MASK_HELP #language en-US "Enter NetMask in dotted-decimal notation. Example: 255.255.255.0\r\n"
|
||||
#string STR_IP4_LOCAL_GATEWAY #language en-US "Local Gateway"
|
||||
#string STR_IP4_GATEWAY_HELP #language en-US "Enter Gateway in dotted-decimal notation. Example: 192.168.10.1\r\n"
|
||||
#string STR_IP4_LOCAL_DNS #language en-US "Local DNS Servers"
|
||||
#string STR_IP4_DNS_HELP #language en-US "Enter DNS Servers in dotted-decimal notation. Example: 192.168.10.8 192.168.10.9\r\n"
|
||||
#string STR_SAVE_CHANGES #language en-US "Save Changes and Exit"
|
||||
#string STR_NULL #language en-US ""
|
363
NetworkPkg/Ip4Dxe/Ip4Icmp.c
Normal file
363
NetworkPkg/Ip4Dxe/Ip4Icmp.c
Normal file
@@ -0,0 +1,363 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
IP4_ICMP_CLASS
|
||||
mIcmpClass[] = {
|
||||
{ICMP_ECHO_REPLY, ICMP_QUERY_MESSAGE },
|
||||
{1, ICMP_INVALID_MESSAGE},
|
||||
{2, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_SOURCE_QUENCH, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_REDIRECT, ICMP_ERROR_MESSAGE },
|
||||
{6, ICMP_INVALID_MESSAGE},
|
||||
{7, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_ECHO_REQUEST, ICMP_QUERY_MESSAGE },
|
||||
{9, ICMP_INVALID_MESSAGE},
|
||||
{10, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_TIME_EXCEEDED, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_PARAMETER_PROBLEM, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_TIMESTAMP , ICMP_QUERY_MESSAGE },
|
||||
{14, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_INFO_REQUEST , ICMP_QUERY_MESSAGE },
|
||||
{ICMP_INFO_REPLY , ICMP_QUERY_MESSAGE },
|
||||
};
|
||||
|
||||
EFI_IP4_ICMP_TYPE
|
||||
mIp4SupportedIcmp[23] = {
|
||||
{ICMP_ECHO_REPLY, ICMP_DEFAULT_CODE },
|
||||
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_PROTO_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_PORT_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_FRAGMENT_FAILED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_SOURCEROUTE_FAILED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNKNOWN },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNKNOWN },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_SOURCE_ISOLATED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_PROHIBITED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_PROHIBITED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACHABLE_TOS },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNREACHABLE_TOS},
|
||||
|
||||
{ICMP_SOURCE_QUENCH, ICMP_DEFAULT_CODE },
|
||||
|
||||
{ICMP_REDIRECT, ICMP_NET_REDIRECT },
|
||||
{ICMP_REDIRECT, ICMP_HOST_REDIRECT },
|
||||
{ICMP_REDIRECT, ICMP_NET_TOS_REDIRECT },
|
||||
{ICMP_REDIRECT, ICMP_HOST_TOS_REDIRECT },
|
||||
|
||||
{ICMP_ECHO_REQUEST, ICMP_DEFAULT_CODE },
|
||||
|
||||
{ICMP_TIME_EXCEEDED, ICMP_TIMEOUT_IN_TRANSIT },
|
||||
{ICMP_TIME_EXCEEDED, ICMP_TIMEOUT_REASSEMBLE },
|
||||
|
||||
{ICMP_PARAMETER_PROBLEM, ICMP_DEFAULT_CODE },
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Process the ICMP redirect. Find the instance then update
|
||||
its route cache.
|
||||
|
||||
All kinds of redirect is treated as host redirect as
|
||||
specified by RFC1122 3.3.1.2:
|
||||
"Since the subnet mask appropriate to the destination
|
||||
address is generally not known, a Network Redirect
|
||||
message SHOULD be treated identically to a Host Redirect
|
||||
message;"
|
||||
|
||||
@param[in] IpSb The IP4 service binding instance that received
|
||||
the packet.
|
||||
@param[in] Head The IP head of the received ICMPpacket.
|
||||
@param[in] Packet The content of the ICMP redirect packet with IP
|
||||
head removed.
|
||||
@param[in] Icmp The buffer to store the ICMP error message if
|
||||
something is wrong.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invalid
|
||||
@retval EFI_SUCCESS Successfully updated the route caches
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4ProcessIcmpRedirect (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_ICMP_ERROR_HEAD *Icmp
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP4_PROTOCOL *Ip4Instance;
|
||||
IP4_ROUTE_CACHE_ENTRY *CacheEntry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
IP4_ADDR Gateway;
|
||||
IP4_ADDR Src;
|
||||
IP4_ADDR Dst;
|
||||
|
||||
//
|
||||
// Find the interface whose IP address is the source of the
|
||||
// orgianl IP packet.
|
||||
//
|
||||
IpIf = Ip4FindInterface (IpSb, NTOHL (Icmp->IpHead.Src));
|
||||
Gateway = NTOHL (Icmp->Fourth);
|
||||
|
||||
//
|
||||
// discard the packet if the new gateway address it specifies
|
||||
// is not on the same connected net through which the Redirect
|
||||
// arrived. (RFC1122 3.2.2.2).
|
||||
//
|
||||
if ((IpIf == NULL) || !IP4_NET_EQUAL (Gateway, IpIf->Ip, IpIf->SubnetMask)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Update each IP child's route cache on the interface.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
|
||||
Ip4Instance = NET_LIST_USER_STRUCT (Entry, IP4_PROTOCOL, AddrLink);
|
||||
|
||||
if (Ip4Instance->RouteTable == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Dst = NTOHL (Icmp->IpHead.Dst);
|
||||
Src = NTOHL (Icmp->IpHead.Src);
|
||||
CacheEntry = Ip4FindRouteCache (Ip4Instance->RouteTable, Dst, Src);
|
||||
|
||||
//
|
||||
// Only update the route cache's gateway if the source of the
|
||||
// Redirect is the current first-hop gateway
|
||||
//
|
||||
if ((CacheEntry != NULL) && (NTOHL (Head->Src) == CacheEntry->NextHop)) {
|
||||
CacheEntry->NextHop = Gateway;
|
||||
}
|
||||
}
|
||||
|
||||
NetbufFree (Packet);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Process the ICMP error packet. If it is an ICMP redirect packet,
|
||||
update call Ip4ProcessIcmpRedirect to update the IP instance's
|
||||
route cache, otherwise, deliver the packet to upper layer.
|
||||
|
||||
@param[in] IpSb The IP4 service that received the packet.
|
||||
@param[in] Head The IP4 head of the ICMP error packet
|
||||
@param[in] Packet The content of the ICMP error with IP4 head
|
||||
removed.
|
||||
|
||||
@retval EFI_SUCCESS The ICMP error is processed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid
|
||||
@retval Others Failed to process the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4ProcessIcmpError (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_ERROR_HEAD Icmp;
|
||||
|
||||
if (Packet->TotalSize < sizeof (Icmp)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
|
||||
//
|
||||
// If it is an ICMP redirect error, update the route cache
|
||||
// as RFC1122. Otherwise, demultiplex it to IP instances.
|
||||
//
|
||||
if (Icmp.Head.Type == ICMP_REDIRECT) {
|
||||
return Ip4ProcessIcmpRedirect (IpSb, Head, Packet, &Icmp);
|
||||
}
|
||||
|
||||
IP4_GET_CLIP_INFO (Packet)->Status = EFI_ICMP_ERROR;
|
||||
return Ip4Demultiplex (IpSb, Head, Packet, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Replay an ICMP echo request.
|
||||
|
||||
@param[in] IpSb The IP4 service that receivd the packet
|
||||
@param[in] Head The IP4 head of the ICMP error packet
|
||||
@param[in] Packet The content of the ICMP error with IP4 head
|
||||
removed.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
|
||||
@retval EFI_SUCCESS The ICMP Echo request is successfully answered.
|
||||
@retval Others Failed to answer the ICMP echo request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IcmpReplyEcho (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_QUERY_HEAD *Icmp;
|
||||
NET_BUF *Data;
|
||||
EFI_STATUS Status;
|
||||
IP4_HEAD ReplyHead;
|
||||
|
||||
//
|
||||
// make a copy the packet, it is really a bad idea to
|
||||
// send the MNP's buffer back to MNP.
|
||||
//
|
||||
Data = NetbufDuplicate (Packet, NULL, IP4_MAX_HEADLEN);
|
||||
|
||||
if (Data == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Change the ICMP type to echo reply, exchange the source
|
||||
// and destination, then send it. The source is updated to
|
||||
// use specific destination. See RFC1122. SRR/RR option
|
||||
// update is omitted.
|
||||
//
|
||||
Icmp = (IP4_ICMP_QUERY_HEAD *) NetbufGetByte (Data, 0, NULL);
|
||||
ASSERT (Icmp != NULL);
|
||||
Icmp->Head.Type = ICMP_ECHO_REPLY;
|
||||
Icmp->Head.Checksum = 0;
|
||||
Icmp->Head.Checksum = (UINT16) (~NetblockChecksum ((UINT8 *) Icmp, Data->TotalSize));
|
||||
|
||||
ReplyHead.Tos = 0;
|
||||
ReplyHead.Fragment = 0;
|
||||
ReplyHead.Ttl = 64;
|
||||
ReplyHead.Protocol = EFI_IP_PROTO_ICMP;
|
||||
ReplyHead.Src = 0;
|
||||
|
||||
//
|
||||
// Ip4Output will select a source for us
|
||||
//
|
||||
ReplyHead.Dst = Head->Src;
|
||||
|
||||
Status = Ip4Output (
|
||||
IpSb,
|
||||
NULL,
|
||||
Data,
|
||||
&ReplyHead,
|
||||
NULL,
|
||||
0,
|
||||
IP4_ALLZERO_ADDRESS,
|
||||
Ip4SysPacketSent,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
NetbufFree (Data);
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
NetbufFree (Packet);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Process the ICMP query message. If it is an ICMP echo
|
||||
request, answer it. Otherwise deliver it to upper layer.
|
||||
|
||||
@param[in] IpSb The IP4 service that receivd the packet
|
||||
@param[in] Head The IP4 head of the ICMP query packet
|
||||
@param[in] Packet The content of the ICMP query with IP4 head
|
||||
removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid
|
||||
@retval EFI_SUCCESS The ICMP query message is processed
|
||||
@retval Others Failed to process ICMP query.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4ProcessIcmpQuery (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_QUERY_HEAD Icmp;
|
||||
|
||||
if (Packet->TotalSize < sizeof (Icmp)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
|
||||
if (Icmp.Head.Type == ICMP_ECHO_REQUEST) {
|
||||
return Ip4IcmpReplyEcho (IpSb, Head, Packet);
|
||||
}
|
||||
|
||||
return Ip4Demultiplex (IpSb, Head, Packet, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Handle the ICMP packet. First validate the message format,
|
||||
then according to the message types, process it as query or
|
||||
error packet.
|
||||
|
||||
@param[in] IpSb The IP4 service that receivd the packet.
|
||||
@param[in] Head The IP4 head of the ICMP query packet.
|
||||
@param[in] Packet The content of the ICMP query with IP4 head
|
||||
removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformated.
|
||||
@retval EFI_SUCCESS The ICMP message is successfully processed.
|
||||
@retval Others Failed to handle ICMP packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IcmpHandle (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_HEAD Icmp;
|
||||
UINT16 Checksum;
|
||||
|
||||
if (Packet->TotalSize < sizeof (Icmp)) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
|
||||
if (Icmp.Type > ICMP_TYPE_MAX) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
Checksum = (UINT16) (~NetbufChecksum (Packet));
|
||||
if ((Icmp.Checksum != 0) && (Checksum != 0)) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_ERROR_MESSAGE) {
|
||||
return Ip4ProcessIcmpError (IpSb, Head, Packet);
|
||||
|
||||
} else if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_QUERY_MESSAGE) {
|
||||
return Ip4ProcessIcmpQuery (IpSb, Head, Packet);
|
||||
|
||||
}
|
||||
|
||||
DROP:
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
97
NetworkPkg/Ip4Dxe/Ip4Icmp.h
Normal file
97
NetworkPkg/Ip4Dxe/Ip4Icmp.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/** @file
|
||||
Header file for ICMP protocol.
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_ICMP_H__
|
||||
#define __EFI_IP4_ICMP_H__
|
||||
|
||||
//
|
||||
// ICMP type definations
|
||||
//
|
||||
#define ICMP_ECHO_REPLY 0
|
||||
#define ICMP_DEST_UNREACHABLE 3
|
||||
#define ICMP_SOURCE_QUENCH 4
|
||||
#define ICMP_REDIRECT 5
|
||||
#define ICMP_ECHO_REQUEST 8
|
||||
#define ICMP_TIME_EXCEEDED 11
|
||||
#define ICMP_PARAMETER_PROBLEM 12
|
||||
#define ICMP_TIMESTAMP 13
|
||||
#define ICMP_INFO_REQUEST 15
|
||||
#define ICMP_INFO_REPLY 16
|
||||
#define ICMP_TYPE_MAX ICMP_INFO_REPLY
|
||||
|
||||
#define ICMP_DEFAULT_CODE 0
|
||||
|
||||
//
|
||||
// ICMP code definations for ICMP_DEST_UNREACHABLE
|
||||
//
|
||||
#define ICMP_NET_UNREACHABLE 0
|
||||
#define ICMP_HOST_UNREACHABLE 1
|
||||
#define ICMP_PROTO_UNREACHABLE 2 // Host may generate
|
||||
#define ICMP_PORT_UNREACHABLE 3 // Host may generate
|
||||
#define ICMP_FRAGMENT_FAILED 4
|
||||
#define ICMP_SOURCEROUTE_FAILED 5 // Host may generate
|
||||
#define ICMP_NET_UNKNOWN 6
|
||||
#define ICMP_HOST_UNKNOWN 7
|
||||
#define ICMP_SOURCE_ISOLATED 8
|
||||
#define ICMP_NET_PROHIBITED 9
|
||||
#define ICMP_HOST_PROHIBITED 10
|
||||
#define ICMP_NET_UNREACHABLE_TOS 11
|
||||
#define ICMP_HOST_UNREACHABLE_TOS 12
|
||||
|
||||
//
|
||||
// ICMP code definations for ICMP_TIME_EXCEEDED
|
||||
//
|
||||
#define ICMP_TIMEOUT_IN_TRANSIT 0
|
||||
#define ICMP_TIMEOUT_REASSEMBLE 1 // Host may generate
|
||||
|
||||
//
|
||||
// ICMP code definations for ICMP_TIME_EXCEEDED
|
||||
//
|
||||
#define ICMP_NET_REDIRECT 0
|
||||
#define ICMP_HOST_REDIRECT 1
|
||||
#define ICMP_NET_TOS_REDIRECT 2
|
||||
#define ICMP_HOST_TOS_REDIRECT 3
|
||||
|
||||
//
|
||||
// ICMP message classes, each class of ICMP message shares
|
||||
// a common message format. INVALID_MESSAGE is only a flag.
|
||||
//
|
||||
#define ICMP_INVALID_MESSAGE 0
|
||||
#define ICMP_ERROR_MESSAGE 1
|
||||
#define ICMP_QUERY_MESSAGE 2
|
||||
|
||||
typedef struct {
|
||||
UINT8 IcmpType;
|
||||
UINT8 IcmpClass;
|
||||
} IP4_ICMP_CLASS;
|
||||
|
||||
extern IP4_ICMP_CLASS mIcmpClass[];
|
||||
extern EFI_IP4_ICMP_TYPE mIp4SupportedIcmp[];
|
||||
|
||||
/**
|
||||
Handle the ICMP packet. First validate the message format,
|
||||
then according to the message types, process it as query or
|
||||
error packet.
|
||||
|
||||
@param[in] IpSb The IP4 service that receivd the packet.
|
||||
@param[in] Head The IP4 head of the ICMP query packet.
|
||||
@param[in] Packet The content of the ICMP query with IP4 head
|
||||
removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformated.
|
||||
@retval EFI_SUCCESS The ICMP message is successfully processed.
|
||||
@retval Others Failed to handle ICMP packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IcmpHandle (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
#endif
|
1345
NetworkPkg/Ip4Dxe/Ip4If.c
Normal file
1345
NetworkPkg/Ip4Dxe/Ip4If.c
Normal file
File diff suppressed because it is too large
Load Diff
340
NetworkPkg/Ip4Dxe/Ip4If.h
Normal file
340
NetworkPkg/Ip4Dxe/Ip4If.h
Normal file
@@ -0,0 +1,340 @@
|
||||
/** @file
|
||||
Definition for IP4 pesudo interface structure.
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_IF_H__
|
||||
#define __EFI_IP4_IF_H__
|
||||
|
||||
#define IP4_FRAME_RX_SIGNATURE SIGNATURE_32 ('I', 'P', 'F', 'R')
|
||||
#define IP4_FRAME_TX_SIGNATURE SIGNATURE_32 ('I', 'P', 'F', 'T')
|
||||
#define IP4_FRAME_ARP_SIGNATURE SIGNATURE_32 ('I', 'P', 'F', 'A')
|
||||
#define IP4_INTERFACE_SIGNATURE SIGNATURE_32 ('I', 'P', 'I', 'F')
|
||||
|
||||
/**
|
||||
This prototype is used by both receive and transmission.
|
||||
When receiving Netbuf is allocated by IP4_INTERFACE, and
|
||||
released by IP4. Flag shows whether the frame is received
|
||||
as link broadcast/multicast...
|
||||
|
||||
When transmitting, the Netbuf is from IP4, and provided
|
||||
to the callback as a reference. Flag isn't used.
|
||||
|
||||
@param[in] IpInstance The instance that sent or received the packet.
|
||||
IpInstance can be NULL which means that it is the IP4 driver
|
||||
itself sending the packets. IP4 driver may send packets that
|
||||
don't belong to any instance, such as ICMP errors, ICMP echo
|
||||
responses, or IGMP packets. IpInstance is used as a tag in
|
||||
this module.
|
||||
@param[in] Packet The sent or received packet.
|
||||
@param[in] IoStatus Status of sending or receiving.
|
||||
@param[in] LinkFlag Indicate if the frame is received as link broadcast/multicast.
|
||||
When transmitting, it is not used.
|
||||
@param[in] Context Additional data for callback.
|
||||
|
||||
@retval None.
|
||||
**/
|
||||
typedef
|
||||
VOID
|
||||
(*IP4_FRAME_CALLBACK)(
|
||||
IN IP4_PROTOCOL *IpInstance OPTIONAL,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN UINT32 LinkFlag,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
///
|
||||
/// Each receive request is wrapped in an IP4_LINK_RX_TOKEN.
|
||||
/// Upon completion, the Callback will be called. Only one
|
||||
/// receive request is send to MNP. IpInstance is always NULL.
|
||||
/// Reference MNP's spec for information.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
IP4_INTERFACE *Interface;
|
||||
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
IP4_FRAME_CALLBACK CallBack;
|
||||
VOID *Context;
|
||||
|
||||
EFI_MANAGED_NETWORK_COMPLETION_TOKEN MnpToken;
|
||||
} IP4_LINK_RX_TOKEN;
|
||||
|
||||
///
|
||||
/// Each transmit request is wrapped in an IP4_LINK_TX_TOKEN.
|
||||
/// Upon completion, the Callback will be called.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
IP4_INTERFACE *Interface;
|
||||
IP4_SERVICE *IpSb;
|
||||
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
IP4_FRAME_CALLBACK CallBack;
|
||||
NET_BUF *Packet;
|
||||
VOID *Context;
|
||||
|
||||
EFI_MAC_ADDRESS DstMac;
|
||||
EFI_MAC_ADDRESS SrcMac;
|
||||
|
||||
EFI_MANAGED_NETWORK_COMPLETION_TOKEN MnpToken;
|
||||
EFI_MANAGED_NETWORK_TRANSMIT_DATA MnpTxData;
|
||||
} IP4_LINK_TX_TOKEN;
|
||||
|
||||
///
|
||||
/// Only one ARP request is requested for all the frames in
|
||||
/// a time. It is started for the first frames to the Ip. Any
|
||||
/// subsequent transmission frame will be linked to Frames, and
|
||||
/// be sent all at once the ARP requests succeed.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
LIST_ENTRY Frames;
|
||||
IP4_INTERFACE *Interface;
|
||||
|
||||
//
|
||||
// ARP requesting staffs
|
||||
//
|
||||
EFI_EVENT OnResolved;
|
||||
IP4_ADDR Ip;
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
} IP4_ARP_QUE;
|
||||
|
||||
/**
|
||||
Callback to select which frame to cancel. Caller can cancel a
|
||||
single frame, or all the frame from an IP instance.
|
||||
|
||||
@param Frame The sending frame to check for cancellation.
|
||||
@param Context Additional data for callback.
|
||||
|
||||
@retval TRUE The sending of the frame should be cancelled.
|
||||
@retval FALSE Do not cancel the frame sending.
|
||||
**/
|
||||
typedef
|
||||
BOOLEAN
|
||||
(*IP4_FRAME_TO_CANCEL)(
|
||||
IP4_LINK_TX_TOKEN *Frame,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
//
|
||||
// Each IP4 instance has its own station address. All the instances
|
||||
// with the same station address share a single interface structure.
|
||||
// Each interface has its own ARP child, and shares one MNP child.
|
||||
// Notice the special cases that DHCP can configure the interface
|
||||
// with 0.0.0.0/0.0.0.0.
|
||||
//
|
||||
struct _IP4_INTERFACE {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
|
||||
//
|
||||
// IP address and subnet mask of the interface. It also contains
|
||||
// the subnet/net broadcast address for quick access. The fields
|
||||
// are invalid if (Configured == FALSE)
|
||||
//
|
||||
IP4_ADDR Ip;
|
||||
IP4_ADDR SubnetMask;
|
||||
IP4_ADDR SubnetBrdcast;
|
||||
IP4_ADDR NetBrdcast;
|
||||
BOOLEAN Configured;
|
||||
|
||||
//
|
||||
// Handle used to create/destroy ARP child. All the IP children
|
||||
// share one MNP which is owned by IP service binding.
|
||||
//
|
||||
EFI_HANDLE Controller;
|
||||
EFI_HANDLE Image;
|
||||
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
EFI_ARP_PROTOCOL *Arp;
|
||||
EFI_HANDLE ArpHandle;
|
||||
|
||||
//
|
||||
// Queues to keep the frames sent and waiting ARP request.
|
||||
//
|
||||
LIST_ENTRY ArpQues;
|
||||
LIST_ENTRY SentFrames;
|
||||
IP4_LINK_RX_TOKEN *RecvRequest;
|
||||
|
||||
//
|
||||
// The interface's MAC and broadcast MAC address.
|
||||
//
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
EFI_MAC_ADDRESS BroadcastMac;
|
||||
UINT32 HwaddrLen;
|
||||
|
||||
//
|
||||
// All the IP instances that have the same IP/SubnetMask are linked
|
||||
// together through IpInstances. If any of the instance enables
|
||||
// promiscuous receive, PromiscRecv is true.
|
||||
//
|
||||
LIST_ENTRY IpInstances;
|
||||
BOOLEAN PromiscRecv;
|
||||
};
|
||||
|
||||
/**
|
||||
Create an IP4_INTERFACE. Delay the creation of ARP instance until
|
||||
the interface is configured.
|
||||
|
||||
@param[in] Mnp The shared MNP child of this IP4 service binding
|
||||
instance.
|
||||
@param[in] Controller The controller this IP4 service binding instance
|
||||
is installed. Most like the UNDI handle.
|
||||
@param[in] ImageHandle This driver's image handle.
|
||||
|
||||
@return Point to the created IP4_INTERFACE, otherwise NULL.
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4CreateInterface (
|
||||
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE ImageHandle
|
||||
);
|
||||
|
||||
/**
|
||||
Set the interface's address, create and configure
|
||||
the ARP child if necessary.
|
||||
|
||||
@param Interface The interface to set the address.
|
||||
@param IpAddr The interface's IP address.
|
||||
@param SubnetMask The interface's netmask.
|
||||
|
||||
@retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
|
||||
and a ARP is created for it.
|
||||
@retval Others Failed to set the interface's address.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4SetAddress (
|
||||
IN OUT IP4_INTERFACE *Interface,
|
||||
IN IP4_ADDR IpAddr,
|
||||
IN IP4_ADDR SubnetMask
|
||||
);
|
||||
|
||||
/**
|
||||
Free the interface used by IpInstance. All the IP instance with
|
||||
the same Ip/Netmask pair share the same interface. It is reference
|
||||
counted. All the frames haven't been sent will be cancelled.
|
||||
Because the IpInstance is optional, the caller must remove
|
||||
IpInstance from the interface's instance list itself.
|
||||
|
||||
@param[in] Interface The interface used by the IpInstance.
|
||||
@param[in] IpInstance The Ip instance that free the interface. NULL if
|
||||
the Ip driver is releasing the default interface.
|
||||
|
||||
@retval EFI_SUCCESS The interface use IpInstance is freed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4FreeInterface (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN IP4_PROTOCOL *IpInstance OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Send a frame from the interface. If the next hop is broadcast or
|
||||
multicast address, it is transmitted immediately. If the next hop
|
||||
is a unicast, it will consult ARP to resolve the NextHop's MAC.
|
||||
If some error happened, the CallBack won't be called. So, the caller
|
||||
must test the return value, and take action when there is an error.
|
||||
|
||||
@param[in] Interface The interface to send the frame from
|
||||
@param[in] IpInstance The IP child that request the transmission. NULL
|
||||
if it is the IP4 driver itself.
|
||||
@param[in] Packet The packet to transmit.
|
||||
@param[in] NextHop The immediate destination to transmit the packet
|
||||
to.
|
||||
@param[in] CallBack Function to call back when transmit finished.
|
||||
@param[in] Context Opaque parameter to the call back.
|
||||
@param[in] IpSb The pointer to the IP4 service binding instance.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
|
||||
@retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
|
||||
@retval EFI_SUCCESS The packet is successfully transmitted.
|
||||
@retval other Other error occurs.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4SendFrame (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN IP4_PROTOCOL *IpInstance OPTIONAL,
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_ADDR NextHop,
|
||||
IN IP4_FRAME_CALLBACK CallBack,
|
||||
IN VOID *Context,
|
||||
IN IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Remove all the frames on the interface that pass the FrameToCancel,
|
||||
either queued on ARP queues or that have already been delivered to
|
||||
MNP and not yet recycled.
|
||||
|
||||
@param[in] Interface Interface to remove the frames from.
|
||||
@param[in] IoStatus The transmit status returned to the frames'
|
||||
callback.
|
||||
@param[in] FrameToCancel Function to select the frame to cancel, NULL to
|
||||
select all.
|
||||
@param[in] Context Opaque parameters passed to FrameToCancel.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4CancelFrames (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
If there is a pending receive request, cancel it. Don't call
|
||||
the receive request's callback because this function can be only
|
||||
called if the instance or driver is tearing itself down. It
|
||||
doesn't make sense to call it back. But it is necessary to call
|
||||
the transmit token's callback to give it a chance to free the
|
||||
packet and update the upper layer's transmit request status, say
|
||||
that from the UDP.
|
||||
|
||||
@param[in] Interface The interface used by the IpInstance
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4CancelReceive (
|
||||
IN IP4_INTERFACE *Interface
|
||||
);
|
||||
|
||||
/**
|
||||
Request to receive the packet from the interface.
|
||||
|
||||
@param[in] Interface The interface to receive the frames from.
|
||||
@param[in] IpInstance The instance that requests the receive. NULL for
|
||||
the driver itself.
|
||||
@param[in] CallBack Function to call when receive finished.
|
||||
@param[in] Context Opaque parameter to the callback.
|
||||
|
||||
@retval EFI_ALREADY_STARTED There is already a pending receive request.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.
|
||||
@retval EFI_SUCCESS The recieve request has been started.
|
||||
@retval other Other error occurs.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4ReceiveFrame (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN IP4_PROTOCOL *IpInstance OPTIONAL,
|
||||
IN IP4_FRAME_CALLBACK CallBack,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
#endif
|
615
NetworkPkg/Ip4Dxe/Ip4Igmp.c
Normal file
615
NetworkPkg/Ip4Dxe/Ip4Igmp.c
Normal file
@@ -0,0 +1,615 @@
|
||||
/** @file
|
||||
This file implements the RFC2236: IGMP v2.
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
//
|
||||
// Route Alert option in IGMP report to direct routers to
|
||||
// examine the packet more closely.
|
||||
//
|
||||
UINT32 mRouteAlertOption = 0x00000494;
|
||||
|
||||
|
||||
/**
|
||||
Init the IGMP control data of the IP4 service instance, configure
|
||||
MNP to receive ALL SYSTEM multicast.
|
||||
|
||||
@param[in, out] IpSb The IP4 service whose IGMP is to be initialized.
|
||||
|
||||
@retval EFI_SUCCESS IGMP of the IpSb is successfully initialized.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to initialize IGMP.
|
||||
@retval Others Failed to initialize the IGMP of IpSb.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4InitIgmp (
|
||||
IN OUT IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
IGMP_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
|
||||
//
|
||||
// Configure MNP to receive ALL_SYSTEM multicast
|
||||
//
|
||||
Group = AllocatePool (sizeof (IGMP_GROUP));
|
||||
|
||||
if (Group == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Mnp = IpSb->Mnp;
|
||||
|
||||
Group->Address = IP4_ALLSYSTEM_ADDRESS;
|
||||
Group->RefCnt = 1;
|
||||
Group->DelayTime = 0;
|
||||
Group->ReportByUs = FALSE;
|
||||
|
||||
Status = Ip4GetMulticastMac (Mnp, IP4_ALLSYSTEM_ADDRESS, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Mnp->Groups (Mnp, TRUE, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
InsertHeadList (&IgmpCtrl->Groups, &Group->Link);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
FreePool (Group);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find the IGMP_GROUP structure which contains the status of multicast
|
||||
group Address in this IGMP control block
|
||||
|
||||
@param[in] IgmpCtrl The IGMP control block to search from.
|
||||
@param[in] Address The multicast address to search.
|
||||
|
||||
@return NULL if the multicast address isn't in the IGMP control block. Otherwise
|
||||
the point to the IGMP_GROUP which contains the status of multicast group
|
||||
for Address.
|
||||
|
||||
**/
|
||||
IGMP_GROUP *
|
||||
Ip4FindGroup (
|
||||
IN IGMP_SERVICE_DATA *IgmpCtrl,
|
||||
IN IP4_ADDR Address
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IGMP_GROUP *Group;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
|
||||
if (Group->Address == Address) {
|
||||
return Group;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Count the number of IP4 multicast groups that are mapped to the
|
||||
same MAC address. Several IP4 multicast address may be mapped to
|
||||
the same MAC address.
|
||||
|
||||
@param[in] IgmpCtrl The IGMP control block to search in.
|
||||
@param[in] Mac The MAC address to search.
|
||||
|
||||
@return The number of the IP4 multicast group that mapped to the same
|
||||
multicast group Mac.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4FindMac (
|
||||
IN IGMP_SERVICE_DATA *IgmpCtrl,
|
||||
IN EFI_MAC_ADDRESS *Mac
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IGMP_GROUP *Group;
|
||||
INTN Count;
|
||||
|
||||
Count = 0;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
|
||||
if (NET_MAC_EQUAL (&Group->Mac, Mac, sizeof (EFI_MAC_ADDRESS))) {
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
|
||||
return Count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send an IGMP protocol message to the Dst, such as IGMP v1 membership report.
|
||||
|
||||
@param[in] IpSb The IP4 service instance that requests the
|
||||
transmission.
|
||||
@param[in] Dst The destinaton to send to.
|
||||
@param[in] Type The IGMP message type, such as IGMP v1 membership
|
||||
report.
|
||||
@param[in] Group The group address in the IGMP message head.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to build the message.
|
||||
@retval EFI_SUCCESS The IGMP message is successfully send.
|
||||
@retval Others Failed to send the IGMP message.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4SendIgmpMessage (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN UINT8 Type,
|
||||
IN IP4_ADDR Group
|
||||
)
|
||||
{
|
||||
IP4_HEAD Head;
|
||||
NET_BUF *Packet;
|
||||
IGMP_HEAD *Igmp;
|
||||
|
||||
//
|
||||
// Allocate a net buffer to hold the message
|
||||
//
|
||||
Packet = NetbufAlloc (IP4_MAX_HEADLEN + sizeof (IGMP_HEAD));
|
||||
|
||||
if (Packet == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill in the IGMP and IP header, then transmit the message
|
||||
//
|
||||
NetbufReserve (Packet, IP4_MAX_HEADLEN);
|
||||
|
||||
Igmp = (IGMP_HEAD *) NetbufAllocSpace (Packet, sizeof (IGMP_HEAD), FALSE);
|
||||
if (Igmp == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Igmp->Type = Type;
|
||||
Igmp->MaxRespTime = 0;
|
||||
Igmp->Checksum = 0;
|
||||
Igmp->Group = HTONL (Group);
|
||||
Igmp->Checksum = (UINT16) (~NetblockChecksum ((UINT8 *) Igmp, sizeof (IGMP_HEAD)));
|
||||
|
||||
Head.Tos = 0;
|
||||
Head.Protocol = IP4_PROTO_IGMP;
|
||||
Head.Ttl = 1;
|
||||
Head.Fragment = 0;
|
||||
Head.Dst = Dst;
|
||||
Head.Src = IP4_ALLZERO_ADDRESS;
|
||||
|
||||
return Ip4Output (
|
||||
IpSb,
|
||||
NULL,
|
||||
Packet,
|
||||
&Head,
|
||||
(UINT8 *) &mRouteAlertOption,
|
||||
sizeof (UINT32),
|
||||
IP4_ALLZERO_ADDRESS,
|
||||
Ip4SysPacketSent,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send an IGMP membership report. Depends on whether the server is
|
||||
v1 or v2, it will send either a V1 or V2 membership report.
|
||||
|
||||
@param[in] IpSb The IP4 service instance that requests the
|
||||
transmission.
|
||||
@param[in] Group The group address to report.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to build the message.
|
||||
@retval EFI_SUCCESS The IGMP report message is successfully send.
|
||||
@retval Others Failed to send the report.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4SendIgmpReport (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Group
|
||||
)
|
||||
{
|
||||
if (IpSb->IgmpCtrl.Igmpv1QuerySeen != 0) {
|
||||
return Ip4SendIgmpMessage (IpSb, Group, IGMP_V1_MEMBERSHIP_REPORT, Group);
|
||||
} else {
|
||||
return Ip4SendIgmpMessage (IpSb, Group, IGMP_V2_MEMBERSHIP_REPORT, Group);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Join the multicast group on behalf of this IP4 child
|
||||
|
||||
@param[in] IpInstance The IP4 child that wants to join the group.
|
||||
@param[in] Address The group to join.
|
||||
|
||||
@retval EFI_SUCCESS Successfully join the multicast group.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
|
||||
@retval Others Failed to join the multicast group.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4JoinGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
)
|
||||
{
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
IP4_SERVICE *IpSb;
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
IGMP_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
IpSb = IpInstance->Service;
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
Mnp = IpSb->Mnp;
|
||||
|
||||
//
|
||||
// If the IP service already is a member in the group, just
|
||||
// increase the refernce count and return.
|
||||
//
|
||||
Group = Ip4FindGroup (IgmpCtrl, Address);
|
||||
|
||||
if (Group != NULL) {
|
||||
Group->RefCnt++;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Otherwise, create a new IGMP_GROUP, Get the multicast's MAC address,
|
||||
// send a report, then direct MNP to receive the multicast.
|
||||
//
|
||||
Group = AllocatePool (sizeof (IGMP_GROUP));
|
||||
|
||||
if (Group == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Group->Address = Address;
|
||||
Group->RefCnt = 1;
|
||||
Group->DelayTime = IGMP_UNSOLICIATED_REPORT;
|
||||
Group->ReportByUs = TRUE;
|
||||
|
||||
Status = Ip4GetMulticastMac (Mnp, Address, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip4SendIgmpReport (IpSb, Address);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Mnp->Groups (Mnp, TRUE, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
InsertHeadList (&IgmpCtrl->Groups, &Group->Link);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
FreePool (Group);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Leave the IP4 multicast group on behalf of IpInstance.
|
||||
|
||||
@param[in] IpInstance The IP4 child that wants to leave the group
|
||||
address.
|
||||
@param[in] Address The group address to leave.
|
||||
|
||||
@retval EFI_NOT_FOUND The IP4 service instance isn't in the group.
|
||||
@retval EFI_SUCCESS Successfully leave the multicast group.
|
||||
@retval Others Failed to leave the multicast group.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4LeaveGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
)
|
||||
{
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
IP4_SERVICE *IpSb;
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
IGMP_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
IpSb = IpInstance->Service;
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
Mnp = IpSb->Mnp;
|
||||
|
||||
Group = Ip4FindGroup (IgmpCtrl, Address);
|
||||
|
||||
if (Group == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// If more than one instance is in the group, decrease
|
||||
// the RefCnt then return.
|
||||
//
|
||||
if (--Group->RefCnt > 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// If multiple IP4 group addresses are mapped to the same
|
||||
// multicast MAC address, don't configure the MNP to leave
|
||||
// the MAC.
|
||||
//
|
||||
if (Ip4FindMac (IgmpCtrl, &Group->Mac) == 1) {
|
||||
Status = Mnp->Groups (Mnp, FALSE, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Send a leave report if the membership is reported by us
|
||||
// and we are talking IGMPv2.
|
||||
//
|
||||
if (Group->ReportByUs && IgmpCtrl->Igmpv1QuerySeen == 0) {
|
||||
Ip4SendIgmpMessage (IpSb, IP4_ALLROUTER_ADDRESS, IGMP_LEAVE_GROUP, Group->Address);
|
||||
}
|
||||
|
||||
RemoveEntryList (&Group->Link);
|
||||
FreePool (Group);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Handle the received IGMP message for the IP4 service instance.
|
||||
|
||||
@param[in] IpSb The IP4 service instance that received the message.
|
||||
@param[in] Head The IP4 header of the received message.
|
||||
@param[in] Packet The IGMP message, without IP4 header.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The IGMP message is malformated.
|
||||
@retval EFI_SUCCESS The IGMP message is successfully processed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IgmpHandle (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
IGMP_HEAD Igmp;
|
||||
IGMP_GROUP *Group;
|
||||
IP4_ADDR Address;
|
||||
LIST_ENTRY *Entry;
|
||||
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
|
||||
//
|
||||
// Must checksum over the whole packet, later IGMP version
|
||||
// may employ message longer than 8 bytes. IP's header has
|
||||
// already been trimmed off.
|
||||
//
|
||||
if ((Packet->TotalSize < sizeof (Igmp)) || (NetbufChecksum (Packet) != 0)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the packet in case it is fragmented
|
||||
//
|
||||
NetbufCopy (Packet, 0, sizeof (IGMP_HEAD), (UINT8 *)&Igmp);
|
||||
|
||||
switch (Igmp.Type) {
|
||||
case IGMP_MEMBERSHIP_QUERY:
|
||||
//
|
||||
// If MaxRespTime is zero, it is most likely that we are
|
||||
// talking to a V1 router
|
||||
//
|
||||
if (Igmp.MaxRespTime == 0) {
|
||||
IgmpCtrl->Igmpv1QuerySeen = IGMP_V1ROUTER_PRESENT;
|
||||
Igmp.MaxRespTime = 100;
|
||||
}
|
||||
|
||||
//
|
||||
// Igmp is ticking once per second but MaxRespTime is in
|
||||
// the unit of 100ms.
|
||||
//
|
||||
Igmp.MaxRespTime /= 10;
|
||||
Address = NTOHL (Igmp.Group);
|
||||
|
||||
if (Address == IP4_ALLSYSTEM_ADDRESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
|
||||
//
|
||||
// If address is all zero, all the memberships will be reported.
|
||||
// otherwise only one is reported.
|
||||
//
|
||||
if ((Address == IP4_ALLZERO_ADDRESS) || (Address == Group->Address)) {
|
||||
//
|
||||
// If the timer is pending, only update it if the time left
|
||||
// is longer than the MaxRespTime. TODO: randomize the DelayTime.
|
||||
//
|
||||
if ((Group->DelayTime == 0) || (Group->DelayTime > Igmp.MaxRespTime)) {
|
||||
Group->DelayTime = MAX (1, Igmp.MaxRespTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IGMP_V1_MEMBERSHIP_REPORT:
|
||||
case IGMP_V2_MEMBERSHIP_REPORT:
|
||||
Address = NTOHL (Igmp.Group);
|
||||
Group = Ip4FindGroup (IgmpCtrl, Address);
|
||||
|
||||
if ((Group != NULL) && (Group->DelayTime > 0)) {
|
||||
Group->DelayTime = 0;
|
||||
Group->ReportByUs = FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
NetbufFree (Packet);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The periodical timer function for IGMP. It does the following
|
||||
things:
|
||||
1. Decrease the Igmpv1QuerySeen to make it possible to refresh
|
||||
the IGMP server type.
|
||||
2. Decrease the report timer for each IGMP group in "delaying
|
||||
member" state.
|
||||
|
||||
@param[in] IpSb The IP4 service instance that is ticking.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4IgmpTicking (
|
||||
IN IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
LIST_ENTRY *Entry;
|
||||
IGMP_GROUP *Group;
|
||||
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
|
||||
if (IgmpCtrl->Igmpv1QuerySeen > 0) {
|
||||
IgmpCtrl->Igmpv1QuerySeen--;
|
||||
}
|
||||
|
||||
//
|
||||
// Decrease the report timer for each IGMP group in "delaying member"
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
ASSERT (Group->DelayTime >= 0);
|
||||
|
||||
if (Group->DelayTime > 0) {
|
||||
Group->DelayTime--;
|
||||
|
||||
if (Group->DelayTime == 0) {
|
||||
Ip4SendIgmpReport (IpSb, Group->Address);
|
||||
Group->ReportByUs = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add a group address to the array of group addresses.
|
||||
The caller should make sure that no duplicated address
|
||||
existed in the array. Although the function doesn't
|
||||
assume the byte order of the both Source and Addr, the
|
||||
network byte order is used by the caller.
|
||||
|
||||
@param[in] Source The array of group addresses to add to.
|
||||
@param[in] Count The number of group addresses in the Source.
|
||||
@param[in] Addr The IP4 multicast address to add.
|
||||
|
||||
@return NULL if failed to allocate memory for the new groups,
|
||||
otherwise the new combined group addresses.
|
||||
|
||||
**/
|
||||
IP4_ADDR *
|
||||
Ip4CombineGroups (
|
||||
IN IP4_ADDR *Source,
|
||||
IN UINT32 Count,
|
||||
IN IP4_ADDR Addr
|
||||
)
|
||||
{
|
||||
IP4_ADDR *Groups;
|
||||
|
||||
Groups = AllocatePool (sizeof (IP4_ADDR) * (Count + 1));
|
||||
|
||||
if (Groups == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CopyMem (Groups, Source, Count * sizeof (IP4_ADDR));
|
||||
Groups[Count] = Addr;
|
||||
|
||||
return Groups;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove a group address from the array of group addresses.
|
||||
Although the function doesn't assume the byte order of the
|
||||
both Groups and Addr, the network byte order is used by
|
||||
the caller.
|
||||
|
||||
@param Groups The array of group addresses to remove from.
|
||||
@param Count The number of group addresses in the Groups.
|
||||
@param Addr The IP4 multicast address to remove.
|
||||
|
||||
@return The nubmer of group addresses in the Groups after remove.
|
||||
It is Count if the Addr isn't in the Groups.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4RemoveGroupAddr (
|
||||
IN OUT IP4_ADDR *Groups,
|
||||
IN UINT32 Count,
|
||||
IN IP4_ADDR Addr
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
if (Groups[Index] == Addr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (Index < Count - 1) {
|
||||
Groups[Index] = Groups[Index + 1];
|
||||
Index++;
|
||||
}
|
||||
|
||||
return Index;
|
||||
}
|
201
NetworkPkg/Ip4Dxe/Ip4Igmp.h
Normal file
201
NetworkPkg/Ip4Dxe/Ip4Igmp.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_IGMP_H__
|
||||
#define __EFI_IP4_IGMP_H__
|
||||
|
||||
//
|
||||
// IGMP message type
|
||||
//
|
||||
#define IGMP_MEMBERSHIP_QUERY 0x11
|
||||
#define IGMP_V1_MEMBERSHIP_REPORT 0x12
|
||||
#define IGMP_V2_MEMBERSHIP_REPORT 0x16
|
||||
#define IGMP_LEAVE_GROUP 0x17
|
||||
|
||||
#define IGMP_V1ROUTER_PRESENT 400
|
||||
#define IGMP_UNSOLICIATED_REPORT 10
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UINT8 Type;
|
||||
UINT8 MaxRespTime;
|
||||
UINT16 Checksum;
|
||||
IP4_ADDR Group;
|
||||
} IGMP_HEAD;
|
||||
#pragma pack()
|
||||
|
||||
///
|
||||
/// The status of multicast group. It isn't necessary to maintain
|
||||
/// explicit state of host state diagram. A group with non-zero
|
||||
/// DelayTime is in "delaying member" state. otherwise, it is in
|
||||
/// "idle member" state.
|
||||
///
|
||||
typedef struct {
|
||||
LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
IP4_ADDR Address;
|
||||
INTN DelayTime;
|
||||
BOOLEAN ReportByUs;
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
} IGMP_GROUP;
|
||||
|
||||
///
|
||||
/// The IGMP status. Each IP4 service instance has a IGMP_SERVICE_DATA
|
||||
/// attached. The Igmpv1QuerySeen remember whether the server on this
|
||||
/// connected network is v1 or v2.
|
||||
///
|
||||
typedef struct {
|
||||
INTN Igmpv1QuerySeen;
|
||||
LIST_ENTRY Groups;
|
||||
} IGMP_SERVICE_DATA;
|
||||
|
||||
/**
|
||||
Init the IGMP control data of the IP4 service instance, configure
|
||||
MNP to receive ALL SYSTEM multicast.
|
||||
|
||||
@param[in, out] IpSb The IP4 service whose IGMP is to be initialized.
|
||||
|
||||
@retval EFI_SUCCESS IGMP of the IpSb is successfully initialized.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to initialize IGMP.
|
||||
@retval Others Failed to initialize the IGMP of IpSb.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4InitIgmp (
|
||||
IN OUT IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Join the multicast group on behalf of this IP4 child
|
||||
|
||||
@param[in] IpInstance The IP4 child that wants to join the group.
|
||||
@param[in] Address The group to join.
|
||||
|
||||
@retval EFI_SUCCESS Successfully join the multicast group.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
|
||||
@retval Others Failed to join the multicast group.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4JoinGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
);
|
||||
|
||||
/**
|
||||
Leave the IP4 multicast group on behalf of IpInstance.
|
||||
|
||||
@param[in] IpInstance The IP4 child that wants to leave the group
|
||||
address.
|
||||
@param[in] Address The group address to leave.
|
||||
|
||||
@retval EFI_NOT_FOUND The IP4 service instance isn't in the group.
|
||||
@retval EFI_SUCCESS Successfully leave the multicast group.
|
||||
@retval Others Failed to leave the multicast group.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4LeaveGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
);
|
||||
|
||||
/**
|
||||
Handle the received IGMP message for the IP4 service instance.
|
||||
|
||||
@param[in] IpSb The IP4 service instance that received the message.
|
||||
@param[in] Head The IP4 header of the received message.
|
||||
@param[in] Packet The IGMP message, without IP4 header.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The IGMP message is malformated.
|
||||
@retval EFI_SUCCESS The IGMP message is successfully processed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IgmpHandle (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
The periodical timer function for IGMP. It does the following
|
||||
things:
|
||||
1. Decrease the Igmpv1QuerySeen to make it possible to refresh
|
||||
the IGMP server type.
|
||||
2. Decrease the report timer for each IGMP group in "delaying
|
||||
member" state.
|
||||
|
||||
@param[in] IpSb The IP4 service instance that is ticking.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4IgmpTicking (
|
||||
IN IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Add a group address to the array of group addresses.
|
||||
The caller should make sure that no duplicated address
|
||||
existed in the array. Although the function doesn't
|
||||
assume the byte order of the both Source and Addr, the
|
||||
network byte order is used by the caller.
|
||||
|
||||
@param[in] Source The array of group addresses to add to.
|
||||
@param[in] Count The number of group addresses in the Source.
|
||||
@param[in] Addr The IP4 multicast address to add.
|
||||
|
||||
@return NULL if failed to allocate memory for the new groups,
|
||||
otherwise the new combined group addresses.
|
||||
|
||||
**/
|
||||
IP4_ADDR *
|
||||
Ip4CombineGroups (
|
||||
IN IP4_ADDR *Source,
|
||||
IN UINT32 Count,
|
||||
IN IP4_ADDR Addr
|
||||
);
|
||||
|
||||
/**
|
||||
Remove a group address from the array of group addresses.
|
||||
Although the function doesn't assume the byte order of the
|
||||
both Groups and Addr, the network byte order is used by
|
||||
the caller.
|
||||
|
||||
@param Groups The array of group addresses to remove from.
|
||||
@param Count The number of group addresses in the Groups.
|
||||
@param Addr The IP4 multicast address to remove.
|
||||
|
||||
@return The nubmer of group addresses in the Groups after remove.
|
||||
It is Count if the Addr isn't in the Groups.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4RemoveGroupAddr (
|
||||
IN OUT IP4_ADDR *Groups,
|
||||
IN UINT32 Count,
|
||||
IN IP4_ADDR Addr
|
||||
);
|
||||
|
||||
/**
|
||||
Find the IGMP_GROUP structure which contains the status of multicast
|
||||
group Address in this IGMP control block
|
||||
|
||||
@param[in] IgmpCtrl The IGMP control block to search from.
|
||||
@param[in] Address The multicast address to search.
|
||||
|
||||
@return NULL if the multicast address isn't in the IGMP control block. Otherwise
|
||||
the point to the IGMP_GROUP which contains the status of multicast group
|
||||
for Address.
|
||||
|
||||
**/
|
||||
IGMP_GROUP *
|
||||
Ip4FindGroup (
|
||||
IN IGMP_SERVICE_DATA *IgmpCtrl,
|
||||
IN IP4_ADDR Address
|
||||
);
|
||||
#endif
|
2330
NetworkPkg/Ip4Dxe/Ip4Impl.c
Normal file
2330
NetworkPkg/Ip4Dxe/Ip4Impl.c
Normal file
File diff suppressed because it is too large
Load Diff
417
NetworkPkg/Ip4Dxe/Ip4Impl.h
Normal file
417
NetworkPkg/Ip4Dxe/Ip4Impl.h
Normal file
@@ -0,0 +1,417 @@
|
||||
/** @file
|
||||
Ip4 internal functions and type defintions.
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
(C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_IMPL_H__
|
||||
#define __EFI_IP4_IMPL_H__
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Protocol/IpSec.h>
|
||||
#include <Protocol/Ip4.h>
|
||||
#include <Protocol/Ip4Config2.h>
|
||||
#include <Protocol/Arp.h>
|
||||
#include <Protocol/ManagedNetwork.h>
|
||||
#include <Protocol/Dhcp4.h>
|
||||
#include <Protocol/HiiConfigRouting.h>
|
||||
#include <Protocol/HiiConfigAccess.h>
|
||||
|
||||
#include <IndustryStandard/Dhcp.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/NetLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/DpcLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/HiiLib.h>
|
||||
#include <Library/UefiHiiServicesLib.h>
|
||||
|
||||
#include "Ip4Common.h"
|
||||
#include "Ip4Driver.h"
|
||||
#include "Ip4If.h"
|
||||
#include "Ip4Icmp.h"
|
||||
#include "Ip4Option.h"
|
||||
#include "Ip4Igmp.h"
|
||||
#include "Ip4Route.h"
|
||||
#include "Ip4Input.h"
|
||||
#include "Ip4Output.h"
|
||||
#include "Ip4Config2Impl.h"
|
||||
#include "Ip4Config2Nv.h"
|
||||
#include "Ip4NvData.h"
|
||||
|
||||
#define IP4_PROTOCOL_SIGNATURE SIGNATURE_32 ('I', 'P', '4', 'P')
|
||||
#define IP4_SERVICE_SIGNATURE SIGNATURE_32 ('I', 'P', '4', 'S')
|
||||
|
||||
//
|
||||
// The state of IP4 protocol. It starts from UNCONFIGED. if it is
|
||||
// successfully configured, it goes to CONFIGED. if configure NULL
|
||||
// is called, it becomes UNCONFIGED again.
|
||||
//
|
||||
#define IP4_STATE_UNCONFIGED 0
|
||||
#define IP4_STATE_CONFIGED 1
|
||||
|
||||
//
|
||||
// The state of IP4 service. It starts from UNSTARTED. It transits
|
||||
// to STARTED if autoconfigure is started. If default address is
|
||||
// configured, it becomes CONFIGED. and if partly destroyed, it goes
|
||||
// to DESTROY.
|
||||
//
|
||||
#define IP4_SERVICE_UNSTARTED 0
|
||||
#define IP4_SERVICE_STARTED 1
|
||||
#define IP4_SERVICE_CONFIGED 2
|
||||
#define IP4_SERVICE_DESTROY 3
|
||||
|
||||
|
||||
///
|
||||
/// IP4_TXTOKEN_WRAP wraps the upper layer's transmit token.
|
||||
/// The user's data is kept in the Packet. When fragment is
|
||||
/// needed, each fragment of the Packet has a reference to the
|
||||
/// Packet, no data is actually copied. The Packet will be
|
||||
/// released when all the fragments of it have been recycled by
|
||||
/// MNP. Upon then, the IP4_TXTOKEN_WRAP will be released, and
|
||||
/// user's event signalled.
|
||||
///
|
||||
typedef struct {
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
EFI_IP4_COMPLETION_TOKEN *Token;
|
||||
EFI_EVENT IpSecRecycleSignal;
|
||||
NET_BUF *Packet;
|
||||
BOOLEAN Sent;
|
||||
INTN Life;
|
||||
} IP4_TXTOKEN_WRAP;
|
||||
|
||||
///
|
||||
/// IP4_IPSEC_WRAP wraps the packet received from MNP layer. The packet
|
||||
/// will be released after it has been processed by the receiver. Upon then,
|
||||
/// the IP4_IPSEC_WRAP will be released, and the IpSecRecycleSignal will be signaled
|
||||
/// to notice IPsec to free the resources.
|
||||
///
|
||||
typedef struct {
|
||||
EFI_EVENT IpSecRecycleSignal;
|
||||
NET_BUF *Packet;
|
||||
} IP4_IPSEC_WRAP;
|
||||
|
||||
///
|
||||
/// IP4_RXDATA_WRAP wraps the data IP4 child delivers to the
|
||||
/// upper layers. The received packet is kept in the Packet.
|
||||
/// The Packet itself may be constructured from some fragments.
|
||||
/// All the fragments of the Packet is organized by a
|
||||
/// IP4_ASSEMBLE_ENTRY structure. If the Packet is recycled by
|
||||
/// the upper layer, the assemble entry and its associated
|
||||
/// fragments will be freed at last.
|
||||
///
|
||||
typedef struct {
|
||||
LIST_ENTRY Link;
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
NET_BUF *Packet;
|
||||
EFI_IP4_RECEIVE_DATA RxData;
|
||||
} IP4_RXDATA_WRAP;
|
||||
|
||||
|
||||
struct _IP4_PROTOCOL {
|
||||
UINT32 Signature;
|
||||
|
||||
EFI_IP4_PROTOCOL Ip4Proto;
|
||||
EFI_HANDLE Handle;
|
||||
INTN State;
|
||||
|
||||
BOOLEAN InDestroy;
|
||||
|
||||
IP4_SERVICE *Service;
|
||||
LIST_ENTRY Link; // Link to all the IP protocol from the service
|
||||
|
||||
//
|
||||
// User's transmit/receive tokens, and received/deliverd packets
|
||||
//
|
||||
NET_MAP RxTokens;
|
||||
NET_MAP TxTokens; // map between (User's Token, IP4_TXTOKE_WRAP)
|
||||
LIST_ENTRY Received; // Received but not delivered packet
|
||||
LIST_ENTRY Delivered; // Delivered and to be recycled packets
|
||||
EFI_LOCK RecycleLock;
|
||||
|
||||
//
|
||||
// Instance's address and route tables. There are two route tables.
|
||||
// RouteTable is used by the IP4 driver to route packet. EfiRouteTable
|
||||
// is used to communicate the current route info to the upper layer.
|
||||
//
|
||||
IP4_INTERFACE *Interface;
|
||||
LIST_ENTRY AddrLink; // Ip instances with the same IP address.
|
||||
IP4_ROUTE_TABLE *RouteTable;
|
||||
|
||||
EFI_IP4_ROUTE_TABLE *EfiRouteTable;
|
||||
UINT32 EfiRouteCount;
|
||||
|
||||
//
|
||||
// IGMP data for this instance
|
||||
//
|
||||
IP4_ADDR *Groups; // stored in network byte order
|
||||
UINT32 GroupCount;
|
||||
|
||||
EFI_IP4_CONFIG_DATA ConfigData;
|
||||
|
||||
};
|
||||
|
||||
struct _IP4_SERVICE {
|
||||
UINT32 Signature;
|
||||
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
|
||||
INTN State;
|
||||
|
||||
//
|
||||
// List of all the IP instances and interfaces, and default
|
||||
// interface and route table and caches.
|
||||
//
|
||||
UINTN NumChildren;
|
||||
LIST_ENTRY Children;
|
||||
|
||||
LIST_ENTRY Interfaces;
|
||||
|
||||
IP4_INTERFACE *DefaultInterface;
|
||||
IP4_ROUTE_TABLE *DefaultRouteTable;
|
||||
|
||||
//
|
||||
// Ip reassemble utilities, and IGMP data
|
||||
//
|
||||
IP4_ASSEMBLE_TABLE Assemble;
|
||||
IGMP_SERVICE_DATA IgmpCtrl;
|
||||
|
||||
//
|
||||
// Low level protocol used by this service instance
|
||||
//
|
||||
EFI_HANDLE Image;
|
||||
EFI_HANDLE Controller;
|
||||
|
||||
EFI_HANDLE MnpChildHandle;
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
|
||||
EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData;
|
||||
EFI_SIMPLE_NETWORK_MODE SnpMode;
|
||||
|
||||
EFI_EVENT Timer;
|
||||
EFI_EVENT ReconfigCheckTimer;
|
||||
EFI_EVENT ReconfigEvent;
|
||||
|
||||
BOOLEAN Reconfig;
|
||||
|
||||
//
|
||||
// Underlying media present status.
|
||||
//
|
||||
BOOLEAN MediaPresent;
|
||||
|
||||
//
|
||||
// IPv4 Configuration II Protocol instance
|
||||
//
|
||||
IP4_CONFIG2_INSTANCE Ip4Config2Instance;
|
||||
|
||||
CHAR16 *MacString;
|
||||
|
||||
UINT32 MaxPacketSize;
|
||||
UINT32 OldMaxPacketSize; ///< The MTU before IPsec enable.
|
||||
};
|
||||
|
||||
#define IP4_INSTANCE_FROM_PROTOCOL(Ip4) \
|
||||
CR ((Ip4), IP4_PROTOCOL, Ip4Proto, IP4_PROTOCOL_SIGNATURE)
|
||||
|
||||
#define IP4_SERVICE_FROM_PROTOCOL(Sb) \
|
||||
CR ((Sb), IP4_SERVICE, ServiceBinding, IP4_SERVICE_SIGNATURE)
|
||||
|
||||
#define IP4_SERVICE_FROM_CONFIG2_INSTANCE(This) \
|
||||
CR (This, IP4_SERVICE, Ip4Config2Instance, IP4_SERVICE_SIGNATURE)
|
||||
|
||||
|
||||
#define IP4_NO_MAPPING(IpInstance) (!(IpInstance)->Interface->Configured)
|
||||
|
||||
extern EFI_IP4_PROTOCOL mEfiIp4ProtocolTemplete;
|
||||
|
||||
/**
|
||||
Config the MNP parameter used by IP. The IP driver use one MNP
|
||||
child to transmit/receive frames. By default, it configures MNP
|
||||
to receive unicast/multicast/broadcast. And it will enable/disable
|
||||
the promiscous receive according to whether there is IP child
|
||||
enable that or not. If Force is FALSE, it will iterate through
|
||||
all the IP children to check whether the promiscuous receive
|
||||
setting has been changed. If it hasn't been changed, it won't
|
||||
reconfigure the MNP. If Force is TRUE, the MNP is configured no
|
||||
matter whether that is changed or not.
|
||||
|
||||
@param[in] IpSb The IP4 service instance that is to be changed.
|
||||
@param[in] Force Force the configuration or not.
|
||||
|
||||
@retval EFI_SUCCESS The MNP is successfully configured/reconfigured.
|
||||
@retval Others Configuration failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4ServiceConfigMnp (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN BOOLEAN Force
|
||||
);
|
||||
|
||||
/**
|
||||
Intiialize the IP4_PROTOCOL structure to the unconfigured states.
|
||||
|
||||
@param IpSb The IP4 service instance.
|
||||
@param IpInstance The IP4 child instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4InitProtocol (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN OUT IP4_PROTOCOL *IpInstance
|
||||
);
|
||||
|
||||
/**
|
||||
Clean up the IP4 child, release all the resources used by it.
|
||||
|
||||
@param[in] IpInstance The IP4 child to clean up.
|
||||
|
||||
@retval EFI_SUCCESS The IP4 child is cleaned up.
|
||||
@retval EFI_DEVICE_ERROR Some resources failed to be released.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4CleanProtocol (
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
);
|
||||
|
||||
/**
|
||||
Cancel the user's receive/transmit request.
|
||||
|
||||
@param[in] IpInstance The IP4 child.
|
||||
@param[in] Token The token to cancel. If NULL, all token will be
|
||||
cancelled.
|
||||
|
||||
@retval EFI_SUCCESS The token is cancelled.
|
||||
@retval EFI_NOT_FOUND The token isn't found on either the
|
||||
transmit/receive queue.
|
||||
@retval EFI_DEVICE_ERROR Not all token is cancelled when Token is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Cancel (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN EFI_IP4_COMPLETION_TOKEN *Token OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Change the IP4 child's multicast setting. The caller
|
||||
should make sure that the parameters is valid.
|
||||
|
||||
@param[in] IpInstance The IP4 child to change the setting.
|
||||
@param[in] JoinFlag TRUE to join the group, otherwise leave it
|
||||
@param[in] GroupAddress The target group address
|
||||
|
||||
@retval EFI_ALREADY_STARTED Want to join the group, but already a member of it
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
|
||||
@retval EFI_DEVICE_ERROR Failed to set the group configuraton
|
||||
@retval EFI_SUCCESS Successfully updated the group setting.
|
||||
@retval EFI_NOT_FOUND Try to leave the group which it isn't a member.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Groups (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN BOOLEAN JoinFlag,
|
||||
IN EFI_IPv4_ADDRESS *GroupAddress OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
This heart beat timer of IP4 service instance times out all of its IP4 children's
|
||||
received-but-not-delivered and transmitted-but-not-recycle packets, and provides
|
||||
time input for its IGMP protocol.
|
||||
|
||||
@param[in] Event The IP4 service instance's heart beat timer.
|
||||
@param[in] Context The IP4 service instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip4TimerTicking (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
This dedicated timer is used to poll underlying network media status. In case
|
||||
of cable swap or wireless network switch, a new round auto configuration will
|
||||
be initiated. The timer will signal the IP4 to run DHCP configuration again.
|
||||
IP4 driver will free old IP address related resource, such as route table and
|
||||
Interface, then initiate a DHCP process to acquire new IP, eventually create
|
||||
route table for new IP address.
|
||||
|
||||
@param[in] Event The IP4 service instance's heart beat timer.
|
||||
@param[in] Context The IP4 service instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip4TimerReconfigChecking (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Decrease the life of the transmitted packets. If it is
|
||||
decreased to zero, cancel the packet. This function is
|
||||
called by Ip4PacketTimerTicking which time out both the
|
||||
received-but-not-delivered and transmitted-but-not-recycle
|
||||
packets.
|
||||
|
||||
@param[in] Map The IP4 child's transmit map.
|
||||
@param[in] Item Current transmitted packet.
|
||||
@param[in] Context Not used.
|
||||
|
||||
@retval EFI_SUCCESS Always returns EFI_SUCCESS.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4SentPacketTicking (
|
||||
IN NET_MAP *Map,
|
||||
IN NET_MAP_ITEM *Item,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
The callback function for the net buffer which wraps the user's
|
||||
transmit token. Although it seems this function is pretty simple,
|
||||
there are some subtle things.
|
||||
When user requests the IP to transmit a packet by passing it a
|
||||
token, the token is wrapped in an IP4_TXTOKEN_WRAP and the data
|
||||
is wrapped in an net buffer. the net buffer's Free function is
|
||||
set to Ip4FreeTxToken. The Token and token wrap are added to the
|
||||
IP child's TxToken map. Then the buffer is passed to Ip4Output for
|
||||
transmission. If something error happened before that, the buffer
|
||||
is freed, which in turn will free the token wrap. The wrap may
|
||||
have been added to the TxToken map or not, and the user's event
|
||||
shouldn't be fired because we are still in the EfiIp4Transmit. If
|
||||
the buffer has been sent by Ip4Output, it should be removed from
|
||||
the TxToken map and user's event signaled. The token wrap and buffer
|
||||
are bound together. Check the comments in Ip4Output for information
|
||||
about IP fragmentation.
|
||||
|
||||
@param[in] Context The token's wrap.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip4FreeTxToken (
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
extern EFI_IPSEC2_PROTOCOL *mIpSec;
|
||||
extern BOOLEAN mIpSec2Installed;
|
||||
|
||||
#endif
|
1597
NetworkPkg/Ip4Dxe/Ip4Input.c
Normal file
1597
NetworkPkg/Ip4Dxe/Ip4Input.c
Normal file
File diff suppressed because it is too large
Load Diff
246
NetworkPkg/Ip4Dxe/Ip4Input.h
Normal file
246
NetworkPkg/Ip4Dxe/Ip4Input.h
Normal file
@@ -0,0 +1,246 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_INPUT_H__
|
||||
#define __EFI_IP4_INPUT_H__
|
||||
|
||||
#define IP4_MIN_HEADLEN 20
|
||||
#define IP4_MAX_HEADLEN 60
|
||||
///
|
||||
/// 8(ESP header) + 16(max IV) + 16(max padding) + 2(ESP tail) + 12(max ICV) = 54
|
||||
///
|
||||
#define IP4_MAX_IPSEC_HEADLEN 54
|
||||
|
||||
#define IP4_ASSEMLE_HASH_SIZE 31
|
||||
#define IP4_FRAGMENT_LIFE 120
|
||||
#define IP4_MAX_PACKET_SIZE 65535
|
||||
|
||||
///
|
||||
/// Per packet information for input process. LinkFlag specifies whether
|
||||
/// the packet is received as Link layer unicast, multicast or broadcast.
|
||||
/// The CastType is the IP layer cast type, such as IP multicast or unicast.
|
||||
/// Start, End and Length are staffs used to assemble the packets. Start
|
||||
/// is the sequence number of the first byte of data in the packet. Length
|
||||
/// is the number of bytes of data. End = Start + Length, that is, the
|
||||
/// sequence number of last byte + 1. Each assembled packet has a count down
|
||||
/// life. If it isn't consumed before Life reaches zero, the packet is released.
|
||||
///
|
||||
typedef struct {
|
||||
UINTN LinkFlag;
|
||||
INTN CastType;
|
||||
INTN Start;
|
||||
INTN End;
|
||||
INTN Length;
|
||||
UINT32 Life;
|
||||
EFI_STATUS Status;
|
||||
} IP4_CLIP_INFO;
|
||||
|
||||
///
|
||||
/// Structure used to assemble IP packets.
|
||||
///
|
||||
typedef struct {
|
||||
LIST_ENTRY Link;
|
||||
|
||||
//
|
||||
// Identity of one IP4 packet. Each fragment of a packet has
|
||||
// the same (Dst, Src, Id, Protocol).
|
||||
//
|
||||
IP4_ADDR Dst;
|
||||
IP4_ADDR Src;
|
||||
UINT16 Id;
|
||||
UINT8 Protocol;
|
||||
|
||||
INTN TotalLen;
|
||||
INTN CurLen;
|
||||
LIST_ENTRY Fragments; // List of all the fragments of this packet
|
||||
|
||||
IP4_HEAD *Head; // IP head of the first fragment
|
||||
IP4_CLIP_INFO *Info; // Per packet info of the first fragment
|
||||
INTN Life; // Count down life for the packet.
|
||||
} IP4_ASSEMBLE_ENTRY;
|
||||
|
||||
///
|
||||
/// Each Ip service instance has an assemble table to reassemble
|
||||
/// the packets before delivery to its children. It is organized
|
||||
/// as hash table.
|
||||
///
|
||||
typedef struct {
|
||||
LIST_ENTRY Bucket[IP4_ASSEMLE_HASH_SIZE];
|
||||
} IP4_ASSEMBLE_TABLE;
|
||||
|
||||
#define IP4_GET_CLIP_INFO(Packet) ((IP4_CLIP_INFO *) ((Packet)->ProtoData))
|
||||
|
||||
#define IP4_ASSEMBLE_HASH(Dst, Src, Id, Proto) \
|
||||
(((Dst) + (Src) + ((Id) << 16) + (Proto)) % IP4_ASSEMLE_HASH_SIZE)
|
||||
|
||||
#define IP4_RXDATA_WRAP_SIZE(NumFrag) \
|
||||
(sizeof (IP4_RXDATA_WRAP) + sizeof (EFI_IP4_FRAGMENT_DATA) * ((NumFrag) - 1))
|
||||
|
||||
/**
|
||||
Initialize an already allocated assemble table. This is generally
|
||||
the assemble table embedded in the IP4 service instance.
|
||||
|
||||
@param[in, out] Table The assemble table to initialize.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4InitAssembleTable (
|
||||
IN OUT IP4_ASSEMBLE_TABLE *Table
|
||||
);
|
||||
|
||||
/**
|
||||
Clean up the assemble table: remove all the fragments
|
||||
and assemble entries.
|
||||
|
||||
@param[in] Table The assemble table to clean up
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4CleanAssembleTable (
|
||||
IN IP4_ASSEMBLE_TABLE *Table
|
||||
);
|
||||
|
||||
/**
|
||||
The IP4 input routine. It is called by the IP4_INTERFACE when a
|
||||
IP4 fragment is received from MNP.
|
||||
|
||||
@param[in] Ip4Instance The IP4 child that request the receive, most like
|
||||
it is NULL.
|
||||
@param[in] Packet The IP4 packet received.
|
||||
@param[in] IoStatus The return status of receive request.
|
||||
@param[in] Flag The link layer flag for the packet received, such
|
||||
as multicast.
|
||||
@param[in] Context The IP4 service instance that own the MNP.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4AccpetFrame (
|
||||
IN IP4_PROTOCOL *Ip4Instance,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN UINT32 Flag,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Demultiple the packet. the packet delivery is processed in two
|
||||
passes. The first pass will enque a shared copy of the packet
|
||||
to each IP4 child that accepts the packet. The second pass will
|
||||
deliver a non-shared copy of the packet to each IP4 child that
|
||||
has pending receive requests. Data is copied if more than one
|
||||
child wants to consume the packet because each IP child needs
|
||||
its own copy of the packet to make changes.
|
||||
|
||||
@param[in] IpSb The IP4 service instance that received the packet.
|
||||
@param[in] Head The header of the received packet.
|
||||
@param[in] Packet The data of the received packet.
|
||||
@param[in] Option Point to the IP4 packet header options.
|
||||
@param[in] OptionLen Length of the IP4 packet header options.
|
||||
|
||||
@retval EFI_NOT_FOUND No IP child accepts the packet.
|
||||
@retval EFI_SUCCESS The packet is enqueued or delivered to some IP
|
||||
children.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Demultiplex (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptionLen
|
||||
);
|
||||
|
||||
/**
|
||||
Enqueue a received packet to all the IP children that share
|
||||
the same interface.
|
||||
|
||||
@param[in] IpSb The IP4 service instance that receive the packet.
|
||||
@param[in] Head The header of the received packet.
|
||||
@param[in] Packet The data of the received packet.
|
||||
@param[in] Option Point to the IP4 packet header options.
|
||||
@param[in] OptionLen Length of the IP4 packet header options.
|
||||
@param[in] IpIf The interface to enqueue the packet to.
|
||||
|
||||
@return The number of the IP4 children that accepts the packet
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4InterfaceEnquePacket (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptionLen,
|
||||
IN IP4_INTERFACE *IpIf
|
||||
);
|
||||
|
||||
/**
|
||||
Deliver the received packets to upper layer if there are both received
|
||||
requests and enqueued packets. If the enqueued packet is shared, it will
|
||||
duplicate it to a non-shared packet, release the shared packet, then
|
||||
deliver the non-shared packet up.
|
||||
|
||||
@param[in] IpInstance The IP child to deliver the packet up.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources to deliver the
|
||||
packets.
|
||||
@retval EFI_SUCCESS All the enqueued packets that can be delivered
|
||||
are delivered up.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4InstanceDeliverPacket (
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
);
|
||||
|
||||
/**
|
||||
Timeout the fragment and enqueued packets.
|
||||
|
||||
@param[in] IpSb The IP4 service instance to timeout
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4PacketTimerTicking (
|
||||
IN IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
The work function to locate IPsec protocol to process the inbound or
|
||||
outbound IP packets. The process routine handls the packet with following
|
||||
actions: bypass the packet, discard the packet, or protect the packet.
|
||||
|
||||
@param[in] IpSb The IP4 service instance.
|
||||
@param[in, out] Head The The caller supplied IP4 header.
|
||||
@param[in, out] Netbuf The IP4 packet to be processed by IPsec.
|
||||
@param[in, out] Options The caller supplied options.
|
||||
@param[in, out] OptionsLen The length of the option.
|
||||
@param[in] Direction The directionality in an SPD entry,
|
||||
EfiIPsecInBound or EfiIPsecOutBound.
|
||||
@param[in] Context The token's wrap.
|
||||
|
||||
@retval EFI_SUCCESS The IPsec protocol is not available or disabled.
|
||||
@retval EFI_SUCCESS The packet was bypassed and all buffers remain the same.
|
||||
@retval EFI_SUCCESS The packet was protected.
|
||||
@retval EFI_ACCESS_DENIED The packet was discarded.
|
||||
@retval EFI_OUT_OF_RESOURCES There is no suffcient resource to complete the operation.
|
||||
@retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than the
|
||||
number of input data blocks when build a fragment table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IpSecProcessPacket (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN OUT IP4_HEAD **Head,
|
||||
IN OUT NET_BUF **Netbuf,
|
||||
IN OUT UINT8 **Options,
|
||||
IN OUT UINT32 *OptionsLen,
|
||||
IN EFI_IPSEC_TRAFFIC_DIR Direction,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
#endif
|
45
NetworkPkg/Ip4Dxe/Ip4NvData.h
Normal file
45
NetworkPkg/Ip4Dxe/Ip4NvData.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/** @file
|
||||
Routines used to operate the Ip4Dxe.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _IP4_NV_DATA_H_
|
||||
#define _IP4_NV_DATA_H_
|
||||
|
||||
#include <Guid/Ip4Config2Hii.h>
|
||||
|
||||
#define FORMID_MAIN_FORM 1
|
||||
#define FORMID_DEVICE_FORM 2
|
||||
|
||||
#define KEY_ENABLE 0x100
|
||||
#define KEY_DHCP_ENABLE 0x101
|
||||
#define KEY_LOCAL_IP 0x102
|
||||
#define KEY_SUBNET_MASK 0x103
|
||||
#define KEY_GATE_WAY 0x104
|
||||
#define KEY_DNS 0x105
|
||||
#define KEY_SAVE_CHANGES 0x106
|
||||
|
||||
#define IP_MIN_SIZE 7
|
||||
#define IP_MAX_SIZE 15
|
||||
#define IP4_STR_MAX_SIZE 16
|
||||
#define ADDRESS_STR_MAX_SIZE 255
|
||||
#define MAX_IP4_CONFIG_DNS 16
|
||||
|
||||
///
|
||||
/// IP4_CONFIG2_IFR_NVDATA contains the IP4 configure
|
||||
/// parameters for that NIC.
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Configure; ///< NIC configure status
|
||||
UINT8 DhcpEnable; ///< Static or DHCP
|
||||
CHAR16 StationAddress[IP4_STR_MAX_SIZE]; ///< IP addresses
|
||||
CHAR16 SubnetMask[IP4_STR_MAX_SIZE]; ///< Subnet address
|
||||
CHAR16 GatewayAddress[IP4_STR_MAX_SIZE]; ///< Gateway address
|
||||
CHAR16 DnsAddress[ADDRESS_STR_MAX_SIZE]; ///< DNS server address
|
||||
} IP4_CONFIG2_IFR_NVDATA;
|
||||
|
||||
#endif
|
||||
|
204
NetworkPkg/Ip4Dxe/Ip4Option.c
Normal file
204
NetworkPkg/Ip4Dxe/Ip4Option.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/** @file
|
||||
IP4 option support functions.
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Validate the IP4 option format for both the packets we received
|
||||
and will transmit.
|
||||
|
||||
@param[in] Option The first byte of the option
|
||||
@param[in] OptionLen The length of the whole option
|
||||
@param[in] Rcvd The option is from the packet we received if TRUE,
|
||||
otherwise the option we wants to transmit.
|
||||
|
||||
@retval TRUE The option is properly formatted
|
||||
@retval FALSE The option is mal-formated
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip4OptionIsValid (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptionLen,
|
||||
IN BOOLEAN Rcvd
|
||||
)
|
||||
{
|
||||
UINT32 Cur;
|
||||
UINT32 Len;
|
||||
UINT32 Point;
|
||||
|
||||
Cur = 0;
|
||||
|
||||
while (Cur < OptionLen) {
|
||||
switch (Option[Cur]) {
|
||||
case IP4_OPTION_NOP:
|
||||
Cur++;
|
||||
break;
|
||||
|
||||
case IP4_OPTION_EOP:
|
||||
Cur = OptionLen;
|
||||
break;
|
||||
|
||||
case IP4_OPTION_LSRR:
|
||||
case IP4_OPTION_SSRR:
|
||||
case IP4_OPTION_RR:
|
||||
Len = Option[Cur + 1];
|
||||
Point = Option[Cur + 2];
|
||||
|
||||
//
|
||||
// SRR/RR options are formatted as |Type|Len|Point|Ip1|Ip2|...
|
||||
//
|
||||
if ((OptionLen - Cur < Len) || (Len < 3) || ((Len - 3) % 4 != 0)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((Point > Len + 1) || (Point % 4 != 0)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// The Point must point pass the last entry if the packet is received
|
||||
// by us. It must point to 4 if the packet is to be sent by us for
|
||||
// source route option.
|
||||
//
|
||||
if ((Option[Cur] != IP4_OPTION_RR) &&
|
||||
((Rcvd && (Point != Len + 1)) || (!Rcvd && (Point != 4)))) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Cur += Len;
|
||||
break;
|
||||
|
||||
default:
|
||||
Len = Option[Cur + 1];
|
||||
|
||||
if ((OptionLen - Cur < Len) || (Len < 2)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Cur = Cur + Len;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Copy the option from the original option to buffer. It
|
||||
handles the details such as:
|
||||
1. whether copy the single IP4 option to the first/non-first
|
||||
fragments.
|
||||
2. Pad the options copied over to aligned to 4 bytes.
|
||||
|
||||
@param[in] Option The original option to copy from
|
||||
@param[in] OptionLen The length of the original option
|
||||
@param[in] FirstFragment Whether it is the first fragment
|
||||
@param[in, out] Buf The buffer to copy options to. NULL
|
||||
@param[in, out] BufLen The length of the buffer
|
||||
|
||||
@retval EFI_SUCCESS The options are copied over
|
||||
@retval EFI_BUFFER_TOO_SMALL Buf is NULL or BufLen provided is too small.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4CopyOption (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptionLen,
|
||||
IN BOOLEAN FirstFragment,
|
||||
IN OUT UINT8 *Buf, OPTIONAL
|
||||
IN OUT UINT32 *BufLen
|
||||
)
|
||||
{
|
||||
UINT8 OptBuf[40];
|
||||
UINT32 Cur;
|
||||
UINT32 Next;
|
||||
UINT8 Type;
|
||||
UINT32 Len;
|
||||
|
||||
ASSERT ((BufLen != NULL) && (OptionLen <= 40));
|
||||
|
||||
Cur = 0;
|
||||
Next = 0;
|
||||
|
||||
while (Cur < OptionLen) {
|
||||
Type = Option[Cur];
|
||||
Len = Option[Cur + 1];
|
||||
|
||||
if (Type == IP4_OPTION_NOP) {
|
||||
//
|
||||
// Keep the padding, in case that the sender wants to align
|
||||
// the option, say, to 4 bytes
|
||||
//
|
||||
OptBuf[Next] = IP4_OPTION_NOP;
|
||||
Next++;
|
||||
Cur++;
|
||||
|
||||
} else if (Type == IP4_OPTION_EOP) {
|
||||
//
|
||||
// Don't append the EOP to avoid including only a EOP option
|
||||
//
|
||||
break;
|
||||
|
||||
} else {
|
||||
//
|
||||
// don't copy options that is only valid for the first fragment
|
||||
//
|
||||
if (FirstFragment || (Type & IP4_OPTION_COPY_MASK) != 0) {
|
||||
CopyMem (OptBuf + Next, Option + Cur, Len);
|
||||
Next += Len;
|
||||
}
|
||||
|
||||
Cur += Len;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Don't append an EOP only option.
|
||||
//
|
||||
if (Next == 0) {
|
||||
*BufLen = 0;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Append an EOP if the end of option doesn't coincide with the
|
||||
// end of the IP header, that is, isn't aligned to 4 bytes..
|
||||
//
|
||||
if ((Next % 4) != 0) {
|
||||
OptBuf[Next] = IP4_OPTION_EOP;
|
||||
Next++;
|
||||
}
|
||||
|
||||
//
|
||||
// Head length is in the unit of 4 bytes. Now, Len is the
|
||||
// acutal option length to appear in the IP header.
|
||||
//
|
||||
Len = ((Next + 3) &~0x03);
|
||||
|
||||
//
|
||||
// If the buffer is too small, set the BufLen then return
|
||||
//
|
||||
if ((Buf == NULL) || (*BufLen < Len)) {
|
||||
*BufLen = Len;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the option to the Buf, zero the buffer first to pad
|
||||
// the options with NOP to align to 4 bytes.
|
||||
//
|
||||
ZeroMem (Buf, Len);
|
||||
CopyMem (Buf, OptBuf, Next);
|
||||
*BufLen = Len;
|
||||
return EFI_SUCCESS;
|
||||
}
|
66
NetworkPkg/Ip4Dxe/Ip4Option.h
Normal file
66
NetworkPkg/Ip4Dxe/Ip4Option.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/** @file
|
||||
IP4 option support routines.
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_OPTION_H__
|
||||
#define __EFI_IP4_OPTION_H__
|
||||
|
||||
#define IP4_OPTION_EOP 0
|
||||
#define IP4_OPTION_NOP 1
|
||||
#define IP4_OPTION_LSRR 131 // Loss source and record routing, 10000011
|
||||
#define IP4_OPTION_SSRR 137 // Strict source and record routing, 10001001
|
||||
#define IP4_OPTION_RR 7 // Record routing, 00000111
|
||||
|
||||
#define IP4_OPTION_COPY_MASK 0x80
|
||||
|
||||
/**
|
||||
Validate the IP4 option format for both the packets we received
|
||||
and will transmit. It will compute the ICMP error message fields
|
||||
if the option is mal-formated. But this information isn't used.
|
||||
|
||||
@param[in] Option The first byte of the option
|
||||
@param[in] OptionLen The length of the whole option
|
||||
@param[in] Rcvd The option is from the packet we received if TRUE,
|
||||
otherwise the option we wants to transmit.
|
||||
|
||||
@retval TRUE The option is properly formatted
|
||||
@retval FALSE The option is mal-formated
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip4OptionIsValid (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptionLen,
|
||||
IN BOOLEAN Rcvd
|
||||
);
|
||||
|
||||
/**
|
||||
Copy the option from the original option to buffer. It
|
||||
handles the details such as:
|
||||
1. whether copy the single IP4 option to the first/non-first
|
||||
fragments.
|
||||
2. Pad the options copied over to aligned to 4 bytes.
|
||||
|
||||
@param[in] Option The original option to copy from
|
||||
@param[in] OptionLen The length of the original option
|
||||
@param[in] FirstFragment Whether it is the first fragment
|
||||
@param[in, out] Buf The buffer to copy options to. NULL
|
||||
@param[in, out] BufLen The length of the buffer
|
||||
|
||||
@retval EFI_SUCCESS The options are copied over
|
||||
@retval EFI_BUFFER_TOO_SMALL Buf is NULL or BufLen provided is too small.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4CopyOption (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptionLen,
|
||||
IN BOOLEAN FirstFragment,
|
||||
IN OUT UINT8 *Buf, OPTIONAL
|
||||
IN OUT UINT32 *BufLen
|
||||
);
|
||||
#endif
|
482
NetworkPkg/Ip4Dxe/Ip4Output.c
Normal file
482
NetworkPkg/Ip4Dxe/Ip4Output.c
Normal file
@@ -0,0 +1,482 @@
|
||||
/** @file
|
||||
Transmit the IP4 packet.
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
UINT16 mIp4Id;
|
||||
|
||||
|
||||
/**
|
||||
Prepend an IP4 head to the Packet. It will copy the options and
|
||||
build the IP4 header fields. Used for IP4 fragmentation.
|
||||
|
||||
@param Packet The packet to prepend IP4 header to
|
||||
@param Head The caller supplied header. The caller should set
|
||||
the following header fields: Tos, TotalLen, Id,
|
||||
Fragment, Ttl, Protocol, Src and Dst. All the fields
|
||||
are in host byte order. This function will fill in
|
||||
the Ver, HeadLen, and checksum.
|
||||
@param Option The orginal IP4 option to copy from
|
||||
@param OptLen The length of the IP4 option
|
||||
|
||||
@retval EFI_BAD_BUFFER_SIZE There is no enought room in the head space of
|
||||
Packet.
|
||||
@retval EFI_SUCCESS The IP4 header is successfully added to the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4PrependHead (
|
||||
IN OUT NET_BUF *Packet,
|
||||
IN IP4_HEAD *Head,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen
|
||||
)
|
||||
{
|
||||
UINT32 HeadLen;
|
||||
UINT32 Len;
|
||||
IP4_HEAD *PacketHead;
|
||||
BOOLEAN FirstFragment;
|
||||
|
||||
//
|
||||
// Prepend the options: first get the option length, then copy it over.
|
||||
//
|
||||
HeadLen = 0;
|
||||
FirstFragment = IP4_FIRST_FRAGMENT (Head->Fragment);
|
||||
|
||||
Ip4CopyOption (Option, OptLen, FirstFragment, NULL, &Len);
|
||||
|
||||
HeadLen = IP4_MIN_HEADLEN + Len;
|
||||
ASSERT (((Len % 4) == 0) && (HeadLen <= IP4_MAX_HEADLEN));
|
||||
|
||||
PacketHead = (IP4_HEAD *) NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD);
|
||||
|
||||
if (PacketHead == NULL) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
Ip4CopyOption (Option, OptLen, FirstFragment, (UINT8 *) (PacketHead + 1), &Len);
|
||||
|
||||
//
|
||||
// Set the head up, convert the host byte order to network byte order
|
||||
//
|
||||
PacketHead->Ver = 4;
|
||||
PacketHead->HeadLen = (UINT8) (HeadLen >> 2);
|
||||
PacketHead->Tos = Head->Tos;
|
||||
PacketHead->TotalLen = HTONS ((UINT16) Packet->TotalSize);
|
||||
PacketHead->Id = HTONS (Head->Id);
|
||||
PacketHead->Fragment = HTONS (Head->Fragment);
|
||||
PacketHead->Checksum = 0;
|
||||
PacketHead->Ttl = Head->Ttl;
|
||||
PacketHead->Protocol = Head->Protocol;
|
||||
PacketHead->Src = HTONL (Head->Src);
|
||||
PacketHead->Dst = HTONL (Head->Dst);
|
||||
PacketHead->Checksum = (UINT16) (~NetblockChecksum ((UINT8 *) PacketHead, HeadLen));
|
||||
|
||||
Packet->Ip.Ip4 = PacketHead;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Select an interface to send the packet generated in the IP4 driver
|
||||
itself, that is, not by the requests of IP4 child's consumer. Such
|
||||
packets include the ICMP echo replies, and other ICMP error packets.
|
||||
|
||||
@param[in] IpSb The IP4 service that wants to send the packets.
|
||||
@param[in] Dst The destination of the packet
|
||||
@param[in] Src The source of the packet
|
||||
|
||||
@return NULL if no proper interface is found, otherwise the interface that
|
||||
can be used to send the system packet from.
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4SelectInterface (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src
|
||||
)
|
||||
{
|
||||
IP4_INTERFACE *IpIf;
|
||||
IP4_INTERFACE *Selected;
|
||||
LIST_ENTRY *Entry;
|
||||
|
||||
//
|
||||
// Select the interface the Dst is on if one of the connected
|
||||
// network. Some IP instance may be configured with 0.0.0.0/0,
|
||||
// don't select that interface now.
|
||||
//
|
||||
IpIf = Ip4FindNet (IpSb, Dst);
|
||||
|
||||
if ((IpIf != NULL) && (IpIf->Ip != IP4_ALLZERO_ADDRESS)) {
|
||||
return IpIf;
|
||||
}
|
||||
|
||||
//
|
||||
// If source is one of the interface address, select it.
|
||||
//
|
||||
IpIf = Ip4FindInterface (IpSb, Src);
|
||||
|
||||
if ((IpIf != NULL) && (IpIf->Ip != IP4_ALLZERO_ADDRESS)) {
|
||||
return IpIf;
|
||||
}
|
||||
|
||||
//
|
||||
// Select a configured interface as the fall back. Always prefer
|
||||
// an interface with non-zero address.
|
||||
//
|
||||
Selected = NULL;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && ((Selected == NULL) || (Selected->Ip == 0))) {
|
||||
Selected = IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return Selected;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The default callback function for system generated packet.
|
||||
It will free the packet.
|
||||
|
||||
@param Ip4Instance The IP4 child that issued the transmission. It most
|
||||
like is NULL.
|
||||
@param Packet The packet that transmitted.
|
||||
@param IoStatus The result of the transmission, succeeded or failed.
|
||||
@param LinkFlag Not used when transmission. check IP4_FRAME_CALLBACK
|
||||
for reference.
|
||||
@param Context The context provided by us
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4SysPacketSent (
|
||||
IP4_PROTOCOL *Ip4Instance,
|
||||
NET_BUF *Packet,
|
||||
EFI_STATUS IoStatus,
|
||||
UINT32 LinkFlag,
|
||||
VOID *Context
|
||||
)
|
||||
{
|
||||
NetbufFree (Packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Transmit an IP4 packet. The packet comes either from the IP4
|
||||
child's consumer (IpInstance != NULL) or the IP4 driver itself
|
||||
(IpInstance == NULL). It will route the packet, fragment it,
|
||||
then transmit all the fragments through some interface.
|
||||
|
||||
@param[in] IpSb The IP4 service instance to transmit the packet
|
||||
@param[in] IpInstance The IP4 child that issues the transmission. It is
|
||||
NULL if the packet is from the system.
|
||||
@param[in] Packet The user data to send, excluding the IP header.
|
||||
@param[in] Head The caller supplied header. The caller should set
|
||||
the following header fields: Tos, TotalLen, Id, tl,
|
||||
Fragment, Protocol, Src and Dst. All the fields are
|
||||
in host byte order. This function will fill in the
|
||||
Ver, HeadLen, Fragment, and checksum. The Fragment
|
||||
only need to include the DF flag. Ip4Output will
|
||||
compute the MF and offset for you.
|
||||
@param[in] Option The original option to append to the IP headers
|
||||
@param[in] OptLen The length of the option
|
||||
@param[in] GateWay The next hop address to transmit packet to.
|
||||
255.255.255.255 means broadcast.
|
||||
@param[in] Callback The callback function to issue when transmission
|
||||
completed.
|
||||
@param[in] Context The opaque context for the callback
|
||||
|
||||
@retval EFI_NO_MAPPING There is no interface to the destination.
|
||||
@retval EFI_NOT_FOUND There is no route to the destination
|
||||
@retval EFI_SUCCESS The packet is successfully transmitted.
|
||||
@retval EFI_BAD_BUFFER_SIZE The length of the IPv4 header + option length +
|
||||
total data length is greater than MTU (or greater
|
||||
than the maximum packet size if Token.Packet.TxData.
|
||||
OverrideData.DoNotFragment is TRUE.)
|
||||
@retval Others Failed to transmit the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Output (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_PROTOCOL *IpInstance OPTIONAL,
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_HEAD *Head,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen,
|
||||
IN IP4_ADDR GateWay,
|
||||
IN IP4_FRAME_CALLBACK Callback,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
IP4_INTERFACE *IpIf;
|
||||
IP4_ROUTE_CACHE_ENTRY *CacheEntry;
|
||||
IP4_ADDR Dest;
|
||||
EFI_STATUS Status;
|
||||
NET_BUF *Fragment;
|
||||
UINT32 Index;
|
||||
UINT32 HeadLen;
|
||||
UINT32 PacketLen;
|
||||
UINT32 Offset;
|
||||
UINT32 Mtu;
|
||||
UINT32 Num;
|
||||
BOOLEAN RawData;
|
||||
|
||||
//
|
||||
// Select an interface/source for system packet, application
|
||||
// should select them itself.
|
||||
//
|
||||
if (IpInstance == NULL) {
|
||||
IpIf = Ip4SelectInterface (IpSb, Head->Dst, Head->Src);
|
||||
} else {
|
||||
IpIf = IpInstance->Interface;
|
||||
}
|
||||
|
||||
if (IpIf == NULL) {
|
||||
return EFI_NO_MAPPING;
|
||||
}
|
||||
|
||||
if ((Head->Src == IP4_ALLZERO_ADDRESS) && (IpInstance == NULL)) {
|
||||
Head->Src = IpIf->Ip;
|
||||
}
|
||||
|
||||
//
|
||||
// Before IPsec process, prepared the IP head.
|
||||
// If Ip4Output is transmitting RawData, don't update IPv4 header.
|
||||
//
|
||||
HeadLen = sizeof (IP4_HEAD) + ((OptLen + 3) & (~0x03));
|
||||
|
||||
if ((IpInstance != NULL) && IpInstance->ConfigData.RawData) {
|
||||
RawData = TRUE;
|
||||
} else {
|
||||
Head->HeadLen = (UINT8) (HeadLen >> 2);
|
||||
Head->Id = mIp4Id++;
|
||||
Head->Ver = 4;
|
||||
RawData = FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Call IPsec process.
|
||||
//
|
||||
Status = Ip4IpSecProcessPacket (
|
||||
IpSb,
|
||||
&Head,
|
||||
&Packet,
|
||||
&Option,
|
||||
&OptLen,
|
||||
EfiIPsecOutBound,
|
||||
Context
|
||||
);
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Dest = Head->Dst;
|
||||
if (IP4_IS_BROADCAST (Ip4GetNetCast (Dest, IpIf)) || (Dest == IP4_ALLONE_ADDRESS)) {
|
||||
//
|
||||
// Set the gateway to local broadcast if the Dest is
|
||||
// the broadcast address for the connected network or
|
||||
// it is local broadcast.
|
||||
//
|
||||
GateWay = IP4_ALLONE_ADDRESS;
|
||||
|
||||
} else if (IP4_IS_MULTICAST (Dest)) {
|
||||
//
|
||||
// Set the gateway to the destination if it is an multicast
|
||||
// address. The IP4_INTERFACE won't consult ARP to send local
|
||||
// broadcast and multicast.
|
||||
//
|
||||
GateWay = Head->Dst;
|
||||
|
||||
} else if (GateWay == IP4_ALLZERO_ADDRESS) {
|
||||
//
|
||||
// Route the packet unless overrided, that is, GateWay isn't zero.
|
||||
//
|
||||
if (IpInstance == NULL) {
|
||||
CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, TRUE);
|
||||
} else {
|
||||
CacheEntry = Ip4Route (IpInstance->RouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, FALSE);
|
||||
//
|
||||
// If failed to route the packet by using the instance's route table,
|
||||
// try to use the default route table.
|
||||
//
|
||||
if (CacheEntry == NULL) {
|
||||
CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (CacheEntry == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
GateWay = CacheEntry->NextHop;
|
||||
Ip4FreeRouteCacheEntry (CacheEntry);
|
||||
}
|
||||
|
||||
//
|
||||
// OK, selected the source and route, fragment the packet then send
|
||||
// them. Tag each fragment other than the first one as spawn from it.
|
||||
//
|
||||
Mtu = IpSb->MaxPacketSize + sizeof (IP4_HEAD);
|
||||
|
||||
if (Packet->TotalSize + HeadLen > Mtu) {
|
||||
//
|
||||
// Fragmentation is diabled for RawData mode.
|
||||
//
|
||||
if (RawData) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
//
|
||||
// Packet is fragmented from the tail to the head, that is, the
|
||||
// first frame sent is the last fragment of the packet. The first
|
||||
// fragment is NOT sent in this loop. First compute how many
|
||||
// fragments there are.
|
||||
//
|
||||
Mtu = (Mtu - HeadLen) & (~0x07);
|
||||
Num = (Packet->TotalSize + Mtu - 1) / Mtu;
|
||||
|
||||
//
|
||||
// Initialize the packet length and Offset. Other than the last
|
||||
// fragment, the packet length equals to MTU. The offset is always
|
||||
// aligned to MTU.
|
||||
//
|
||||
PacketLen = Packet->TotalSize - (Num - 1) * Mtu;
|
||||
Offset = Mtu * (Num - 1);
|
||||
|
||||
for (Index = 0; Index < Num - 1; Index++, Offset -= Mtu) {
|
||||
Fragment = NetbufGetFragment (Packet, Offset, PacketLen, IP4_MAX_HEADLEN);
|
||||
|
||||
if (Fragment == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Update the header's fragment. The caller fills the IP4 header
|
||||
// fields that are required by Ip4PrependHead except the fragment.
|
||||
//
|
||||
Head->Fragment = IP4_HEAD_FRAGMENT_FIELD (FALSE, (Index != 0), Offset);
|
||||
Ip4PrependHead (Fragment, Head, Option, OptLen);
|
||||
|
||||
//
|
||||
// Transmit the fragments, pass the Packet address as the context.
|
||||
// So, we can find all the fragments spawned from the Packet by
|
||||
// compare the NetBuf and Context to the Packet.
|
||||
//
|
||||
Status = Ip4SendFrame (
|
||||
IpIf,
|
||||
IpInstance,
|
||||
Fragment,
|
||||
GateWay,
|
||||
Ip4SysPacketSent,
|
||||
Packet,
|
||||
IpSb
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
PacketLen = Mtu;
|
||||
}
|
||||
|
||||
//
|
||||
// Trim the already sent data, then adjust the head's fragment field.
|
||||
//
|
||||
NetbufTrim (Packet, Packet->TotalSize - Mtu, FALSE);
|
||||
Head->Fragment = IP4_HEAD_FRAGMENT_FIELD (FALSE, TRUE, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Send the first fragment, it is either the orginal packet, or the
|
||||
// first fragment of a fragmented packet. It seems that there is a subtle
|
||||
// bug here: what if the caller free the packet in Callback and IpIf (or
|
||||
// MNP child used by that interface) still holds the fragments and try
|
||||
// to access the data? The caller can free the packet if it recycles the
|
||||
// consumer's (such as UDP) data in the Callback. But this can't happen.
|
||||
// The detailed sequence is:
|
||||
// 1. for the packets generated by IP4 driver itself:
|
||||
// The Callback is Ip4SysPacketSent, which is the same as the
|
||||
// fragments' callback. Ip4SysPacketSent simply calls NetbufFree
|
||||
// to release its reference to the packet. So, no problem for
|
||||
// system packets.
|
||||
//
|
||||
// 2. for the upper layer's packets (use UDP as an example):
|
||||
// UDP requests the IP layer to transmit some data which is
|
||||
// wrapped in an asynchronous token, the token is wrapped
|
||||
// in IP4_TXTOKEN_WRAP by IP4. IP4 also wrap the user's data
|
||||
// in a net buffer, which is Packet we get here. IP4_TXTOKEN_WRAP
|
||||
// is bound with the Packet. It will only be freed when all
|
||||
// the references to Packet have been released. Upon then, the
|
||||
// Packet's OnFree callback will release the IP4_TXTOKEN_WRAP,
|
||||
// and singal the user's recycle event. So, also no problem for
|
||||
// upper layer's packets.
|
||||
//
|
||||
Ip4PrependHead (Packet, Head, Option, OptLen);
|
||||
Status = Ip4SendFrame (IpIf, IpInstance, Packet, GateWay, Callback, Context, IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
Ip4CancelPacket (IpIf, Packet, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The filter function to find a packet and all its fragments.
|
||||
The packet's fragments have their Context set to the packet.
|
||||
|
||||
@param[in] Frame The frames hold by the low level interface
|
||||
@param[in] Context Context to the function, which is the packet.
|
||||
|
||||
@retval TRUE This is the packet to cancel or its fragments.
|
||||
@retval FALSE This is unrelated packet.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip4CancelPacketFragments (
|
||||
IN IP4_LINK_TX_TOKEN *Frame,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
if ((Frame->Packet == (NET_BUF *) Context) || (Frame->Context == Context)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Cancel the Packet and all its fragments.
|
||||
|
||||
@param IpIf The interface from which the Packet is sent
|
||||
@param Packet The Packet to cancel
|
||||
@param IoStatus The status returns to the sender.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4CancelPacket (
|
||||
IN IP4_INTERFACE *IpIf,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus
|
||||
)
|
||||
{
|
||||
Ip4CancelFrames (IpIf, IoStatus, Ip4CancelPacketFragments, Packet);
|
||||
}
|
120
NetworkPkg/Ip4Dxe/Ip4Output.h
Normal file
120
NetworkPkg/Ip4Dxe/Ip4Output.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_OUTPUT_H__
|
||||
#define __EFI_IP4_OUTPUT_H__
|
||||
|
||||
/**
|
||||
The default callback function for system generated packet.
|
||||
It will free the packet.
|
||||
|
||||
@param Ip4Instance The IP4 child that issued the transmission. It most
|
||||
like is NULL.
|
||||
@param Packet The packet that transmitted.
|
||||
@param IoStatus The result of the transmission, succeeded or failed.
|
||||
@param LinkFlag Not used when transmission. check IP4_FRAME_CALLBACK
|
||||
for reference.
|
||||
@param Context The context provided by us
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4SysPacketSent (
|
||||
IP4_PROTOCOL *Ip4Instance,
|
||||
NET_BUF *Packet,
|
||||
EFI_STATUS IoStatus,
|
||||
UINT32 LinkFlag,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Transmit an IP4 packet. The packet comes either from the IP4
|
||||
child's consumer (IpInstance != NULL) or the IP4 driver itself
|
||||
(IpInstance == NULL). It will route the packet, fragment it,
|
||||
then transmit all the fragments through some interface.
|
||||
|
||||
@param[in] IpSb The IP4 service instance to transmit the packet
|
||||
@param[in] IpInstance The IP4 child that issues the transmission. It is
|
||||
NULL if the packet is from the system.
|
||||
@param[in] Packet The user data to send, excluding the IP header.
|
||||
@param[in] Head The caller supplied header. The caller should set
|
||||
the following header fields: Tos, TotalLen, Id, tl,
|
||||
Fragment, Protocol, Src and Dst. All the fields are
|
||||
in host byte order. This function will fill in the
|
||||
Ver, HeadLen, Fragment, and checksum. The Fragment
|
||||
only need to include the DF flag. Ip4Output will
|
||||
compute the MF and offset for you.
|
||||
@param[in] Option The original option to append to the IP headers
|
||||
@param[in] OptLen The length of the option
|
||||
@param[in] GateWay The next hop address to transmit packet to.
|
||||
255.255.255.255 means broadcast.
|
||||
@param[in] Callback The callback function to issue when transmission
|
||||
completed.
|
||||
@param[in] Context The opaque context for the callback
|
||||
|
||||
@retval EFI_NO_MAPPING There is no interface to the destination.
|
||||
@retval EFI_NOT_FOUND There is no route to the destination
|
||||
@retval EFI_SUCCESS The packet is successfully transmitted.
|
||||
@retval Others Failed to transmit the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Output (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_PROTOCOL *IpInstance OPTIONAL,
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_HEAD *Head,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen,
|
||||
IN IP4_ADDR GateWay,
|
||||
IN IP4_FRAME_CALLBACK Callback,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Cancel the Packet and all its fragments.
|
||||
|
||||
@param IpIf The interface from which the Packet is sent
|
||||
@param Packet The Packet to cancel
|
||||
@param IoStatus The status returns to the sender.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4CancelPacket (
|
||||
IN IP4_INTERFACE *IpIf,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus
|
||||
);
|
||||
|
||||
/**
|
||||
Prepend an IP4 head to the Packet. It will copy the options and
|
||||
build the IP4 header fields. Used for IP4 fragmentation.
|
||||
|
||||
@param Packet The packet to prepend IP4 header to
|
||||
@param Head The caller supplied header. The caller should set
|
||||
the following header fields: Tos, TotalLen, Id,
|
||||
Fragment, Ttl, Protocol, Src and Dst. All the fields
|
||||
are in host byte order. This function will fill in
|
||||
the Ver, HeadLen, and checksum.
|
||||
@param Option The orginal IP4 option to copy from
|
||||
@param OptLen The length of the IP4 option
|
||||
|
||||
@retval EFI_BAD_BUFFER_SIZE There is no enought room in the head space of
|
||||
Packet.
|
||||
@retval EFI_SUCCESS The IP4 header is successfully added to the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4PrependHead (
|
||||
IN OUT NET_BUF *Packet,
|
||||
IN IP4_HEAD *Head,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen
|
||||
);
|
||||
|
||||
extern UINT16 mIp4Id;
|
||||
|
||||
#endif
|
673
NetworkPkg/Ip4Dxe/Ip4Route.c
Normal file
673
NetworkPkg/Ip4Dxe/Ip4Route.c
Normal file
@@ -0,0 +1,673 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Allocate a route entry then initialize it with the Dest/Netmaks
|
||||
and Gateway.
|
||||
|
||||
@param[in] Dest The destination network
|
||||
@param[in] Netmask The destination network mask
|
||||
@param[in] GateWay The nexthop address
|
||||
|
||||
@return NULL if failed to allocate memeory, otherwise the newly created
|
||||
route entry.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_ENTRY *
|
||||
Ip4CreateRouteEntry (
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR GateWay
|
||||
)
|
||||
{
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
|
||||
RtEntry = AllocatePool (sizeof (IP4_ROUTE_ENTRY));
|
||||
|
||||
if (RtEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
InitializeListHead (&RtEntry->Link);
|
||||
|
||||
RtEntry->RefCnt = 1;
|
||||
RtEntry->Dest = Dest;
|
||||
RtEntry->Netmask = Netmask;
|
||||
RtEntry->NextHop = GateWay;
|
||||
RtEntry->Flag = 0;
|
||||
|
||||
return RtEntry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free the route table entry. It is reference counted.
|
||||
|
||||
@param RtEntry The route entry to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4FreeRouteEntry (
|
||||
IN IP4_ROUTE_ENTRY *RtEntry
|
||||
)
|
||||
{
|
||||
ASSERT (RtEntry->RefCnt > 0);
|
||||
|
||||
if (--RtEntry->RefCnt == 0) {
|
||||
FreePool (RtEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Allocate and initialize an IP4 route cache entry.
|
||||
|
||||
@param[in] Dst The destination address
|
||||
@param[in] Src The source address
|
||||
@param[in] GateWay The next hop address
|
||||
@param[in] Tag The tag from the caller. This marks all the cache
|
||||
entries spawned from one route table entry.
|
||||
|
||||
@return NULL if failed to allocate memory for the cache, other point
|
||||
to the created route cache entry.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4CreateRouteCacheEntry (
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src,
|
||||
IN IP4_ADDR GateWay,
|
||||
IN UINTN Tag
|
||||
)
|
||||
{
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
|
||||
RtCacheEntry = AllocatePool (sizeof (IP4_ROUTE_CACHE_ENTRY));
|
||||
|
||||
if (RtCacheEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
InitializeListHead (&RtCacheEntry->Link);
|
||||
|
||||
RtCacheEntry->RefCnt = 1;
|
||||
RtCacheEntry->Dest = Dst;
|
||||
RtCacheEntry->Src = Src;
|
||||
RtCacheEntry->NextHop = GateWay;
|
||||
RtCacheEntry->Tag = Tag;
|
||||
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free the route cache entry. It is reference counted.
|
||||
|
||||
@param RtCacheEntry The route cache entry to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4FreeRouteCacheEntry (
|
||||
IN IP4_ROUTE_CACHE_ENTRY *RtCacheEntry
|
||||
)
|
||||
{
|
||||
ASSERT (RtCacheEntry->RefCnt > 0);
|
||||
|
||||
if (--RtCacheEntry->RefCnt == 0) {
|
||||
FreePool (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialize an empty route cache table.
|
||||
|
||||
@param[in, out] RtCache The rotue cache table to initialize.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4InitRouteCache (
|
||||
IN OUT IP4_ROUTE_CACHE *RtCache
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < IP4_ROUTE_CACHE_HASH_VALUE; Index++) {
|
||||
InitializeListHead (&(RtCache->CacheBucket[Index]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Clean up a route cache, that is free all the route cache
|
||||
entries enqueued in the cache.
|
||||
|
||||
@param[in] RtCache The route cache table to clean up
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4CleanRouteCache (
|
||||
IN IP4_ROUTE_CACHE *RtCache
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < IP4_ROUTE_CACHE_HASH_VALUE; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &(RtCache->CacheBucket[Index])) {
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
RemoveEntryList (Entry);
|
||||
Ip4FreeRouteCacheEntry (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Create an empty route table, includes its internal route cache
|
||||
|
||||
@return NULL if failed to allocate memory for the route table, otherwise
|
||||
the point to newly created route table.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_TABLE *
|
||||
Ip4CreateRouteTable (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
IP4_ROUTE_TABLE *RtTable;
|
||||
UINT32 Index;
|
||||
|
||||
RtTable = AllocatePool (sizeof (IP4_ROUTE_TABLE));
|
||||
|
||||
if (RtTable == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RtTable->RefCnt = 1;
|
||||
RtTable->TotalNum = 0;
|
||||
|
||||
for (Index = 0; Index <= IP4_MASK_MAX; Index++) {
|
||||
InitializeListHead (&(RtTable->RouteArea[Index]));
|
||||
}
|
||||
|
||||
RtTable->Next = NULL;
|
||||
|
||||
Ip4InitRouteCache (&RtTable->Cache);
|
||||
return RtTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free the route table and its associated route cache. Route
|
||||
table is reference counted.
|
||||
|
||||
@param[in] RtTable The route table to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4FreeRouteTable (
|
||||
IN IP4_ROUTE_TABLE *RtTable
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
UINT32 Index;
|
||||
|
||||
ASSERT (RtTable->RefCnt > 0);
|
||||
|
||||
if (--RtTable->RefCnt > 0) {
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Free all the route table entry and its route cache.
|
||||
//
|
||||
for (Index = 0; Index <= IP4_MASK_MAX; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &(RtTable->RouteArea[Index])) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
RemoveEntryList (Entry);
|
||||
Ip4FreeRouteEntry (RtEntry);
|
||||
}
|
||||
}
|
||||
|
||||
Ip4CleanRouteCache (&RtTable->Cache);
|
||||
|
||||
FreePool (RtTable);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Remove all the cache entries bearing the Tag. When a route cache
|
||||
entry is created, it is tagged with the address of route entry
|
||||
from which it is spawned. When a route entry is deleted, the cache
|
||||
entries spawned from it are also deleted.
|
||||
|
||||
@param RtCache Route cache to remove the entries from
|
||||
@param Tag The Tag of the entries to remove
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4PurgeRouteCache (
|
||||
IN OUT IP4_ROUTE_CACHE *RtCache,
|
||||
IN UINTN Tag
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < IP4_ROUTE_CACHE_HASH_VALUE; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &RtCache->CacheBucket[Index]) {
|
||||
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
if (RtCacheEntry->Tag == Tag) {
|
||||
RemoveEntryList (Entry);
|
||||
Ip4FreeRouteCacheEntry (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add a route entry to the route table. All the IP4_ADDRs are in
|
||||
host byte order.
|
||||
|
||||
@param[in, out] RtTable Route table to add route to
|
||||
@param[in] Dest The destination of the network
|
||||
@param[in] Netmask The netmask of the destination
|
||||
@param[in] Gateway The next hop address
|
||||
|
||||
@retval EFI_ACCESS_DENIED The same route already exists
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the entry
|
||||
@retval EFI_SUCCESS The route is added successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4AddRoute (
|
||||
IN OUT IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Head;
|
||||
LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
|
||||
//
|
||||
// All the route entries with the same netmask length are
|
||||
// linke to the same route area
|
||||
//
|
||||
Head = &(RtTable->RouteArea[NetGetMaskLength (Netmask)]);
|
||||
|
||||
//
|
||||
// First check whether the route exists
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, Head) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
if (IP4_NET_EQUAL (RtEntry->Dest, Dest, Netmask) && (RtEntry->NextHop == Gateway)) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create a route entry and insert it to the route area.
|
||||
//
|
||||
RtEntry = Ip4CreateRouteEntry (Dest, Netmask, Gateway);
|
||||
|
||||
if (RtEntry == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (Gateway == IP4_ALLZERO_ADDRESS) {
|
||||
RtEntry->Flag = IP4_DIRECT_ROUTE;
|
||||
}
|
||||
|
||||
InsertHeadList (Head, &RtEntry->Link);
|
||||
RtTable->TotalNum++;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove a route entry and all the route caches spawn from it.
|
||||
|
||||
@param RtTable The route table to remove the route from
|
||||
@param Dest The destination network
|
||||
@param Netmask The netmask of the Dest
|
||||
@param Gateway The next hop address
|
||||
|
||||
@retval EFI_SUCCESS The route entry is successfully removed
|
||||
@retval EFI_NOT_FOUND There is no route entry in the table with that
|
||||
properity.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4DelRoute (
|
||||
IN OUT IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Head;
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
|
||||
Head = &(RtTable->RouteArea[NetGetMaskLength (Netmask)]);
|
||||
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
if (IP4_NET_EQUAL (RtEntry->Dest, Dest, Netmask) && (RtEntry->NextHop == Gateway)) {
|
||||
Ip4PurgeRouteCache (&RtTable->Cache, (UINTN) RtEntry);
|
||||
RemoveEntryList (Entry);
|
||||
Ip4FreeRouteEntry (RtEntry);
|
||||
|
||||
RtTable->TotalNum--;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find a route cache with the dst and src. This is used by ICMP
|
||||
redirect messasge process. All kinds of redirect is treated as
|
||||
host redirect according to RFC1122. So, only route cache entries
|
||||
are modified according to the ICMP redirect message.
|
||||
|
||||
@param[in] RtTable The route table to search the cache for
|
||||
@param[in] Dest The destination address
|
||||
@param[in] Src The source address
|
||||
|
||||
@return NULL if no route entry to the (Dest, Src). Otherwise the point
|
||||
to the correct route cache entry.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4FindRouteCache (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
UINT32 Index;
|
||||
|
||||
Index = IP4_ROUTE_CACHE_HASH (Dest, Src);
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &RtTable->Cache.CacheBucket[Index]) {
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
if ((RtCacheEntry->Dest == Dest) && (RtCacheEntry->Src == Src)) {
|
||||
NET_GET_REF (RtCacheEntry);
|
||||
return RtCacheEntry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Search the route table for a most specific match to the Dst. It searches
|
||||
from the longest route area (mask length == 32) to the shortest route area
|
||||
(default routes). In each route area, it will first search the instance's
|
||||
route table, then the default route table. This is required by the following
|
||||
requirements:
|
||||
1. IP search the route table for a most specific match
|
||||
2. The local route entries have precedence over the default route entry.
|
||||
|
||||
@param[in] RtTable The route table to search from
|
||||
@param[in] Dst The destionation address to search
|
||||
|
||||
@return NULL if no route matches the Dst, otherwise the point to the
|
||||
most specific route to the Dst.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_ENTRY *
|
||||
Ip4FindRouteEntry (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dst
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
IP4_ROUTE_TABLE *Table;
|
||||
INTN Index;
|
||||
|
||||
RtEntry = NULL;
|
||||
|
||||
for (Index = IP4_MASK_MAX; Index >= 0; Index--) {
|
||||
for (Table = RtTable; Table != NULL; Table = Table->Next) {
|
||||
NET_LIST_FOR_EACH (Entry, &Table->RouteArea[Index]) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
if (IP4_NET_EQUAL (RtEntry->Dest, Dst, RtEntry->Netmask)) {
|
||||
NET_GET_REF (RtEntry);
|
||||
return RtEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Search the route table to route the packet. Return/create a route
|
||||
cache if there is a route to the destination.
|
||||
|
||||
@param[in] RtTable The route table to search from
|
||||
@param[in] Dest The destination address to search for
|
||||
@param[in] Src The source address to search for
|
||||
@param[in] SubnetMask The subnet mask of the Src address, this field is
|
||||
used to check if the station is using /32 subnet.
|
||||
@param[in] AlwaysTryDestAddr Always try to use the dest address as next hop even
|
||||
though we can't find a matching route entry. This
|
||||
field is only valid when using /32 subnet.
|
||||
|
||||
@return NULL if failed to route packet, otherwise a route cache
|
||||
entry that can be used to route packet.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4Route (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src,
|
||||
IN IP4_ADDR SubnetMask,
|
||||
IN BOOLEAN AlwaysTryDestAddr
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Head;
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
IP4_ROUTE_CACHE_ENTRY *Cache;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
IP4_ADDR NextHop;
|
||||
UINT32 Count;
|
||||
|
||||
ASSERT (RtTable != NULL);
|
||||
|
||||
Head = &RtTable->Cache.CacheBucket[IP4_ROUTE_CACHE_HASH (Dest, Src)];
|
||||
RtCacheEntry = Ip4FindRouteCache (RtTable, Dest, Src);
|
||||
|
||||
//
|
||||
// If found, promote the cache entry to the head of the hash bucket. LRU
|
||||
//
|
||||
if (RtCacheEntry != NULL) {
|
||||
RemoveEntryList (&RtCacheEntry->Link);
|
||||
InsertHeadList (Head, &RtCacheEntry->Link);
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
||||
//
|
||||
// Search the route table for the most specific route
|
||||
//
|
||||
RtEntry = Ip4FindRouteEntry (RtTable, Dest);
|
||||
|
||||
if (RtEntry == NULL) {
|
||||
if (SubnetMask != IP4_ALLONE_ADDRESS) {
|
||||
return NULL;
|
||||
} else if (!AlwaysTryDestAddr) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Found a route to the Dest, if it is a direct route, the packet
|
||||
// will be sent directly to the destination, such as for connected
|
||||
// network. Otherwise, it is an indirect route, the packet will be
|
||||
// sent to the next hop router.
|
||||
//
|
||||
// When using /32 subnet mask, the packet will always be sent to the direct
|
||||
// destination first, if we can't find a matching route cache.
|
||||
//
|
||||
if (SubnetMask == IP4_ALLONE_ADDRESS || ((RtEntry->Flag & IP4_DIRECT_ROUTE) != 0)) {
|
||||
NextHop = Dest;
|
||||
} else {
|
||||
NextHop = RtEntry->NextHop;
|
||||
}
|
||||
|
||||
if (RtEntry != NULL) {
|
||||
Ip4FreeRouteEntry (RtEntry);
|
||||
}
|
||||
|
||||
//
|
||||
// Create a route cache entry, and tag it as spawned from this route entry
|
||||
// For /32 subnet mask, the default route in RtEntry will be used if failed
|
||||
// to send the packet to driect destination address.
|
||||
//
|
||||
RtCacheEntry = Ip4CreateRouteCacheEntry (Dest, Src, NextHop, (UINTN) RtEntry);
|
||||
|
||||
if (RtCacheEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
InsertHeadList (Head, &RtCacheEntry->Link);
|
||||
NET_GET_REF (RtCacheEntry);
|
||||
|
||||
//
|
||||
// Each bucket of route cache can contain at most 64 entries.
|
||||
// Remove the entries at the tail of the bucket. These entries
|
||||
// are likely to be used least.
|
||||
//
|
||||
Count = 0;
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
|
||||
if (++Count < IP4_ROUTE_CACHE_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Cache = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
RemoveEntryList (Entry);
|
||||
Ip4FreeRouteCacheEntry (Cache);
|
||||
}
|
||||
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of
|
||||
GetModeData. The EFI_IP4_ROUTE_TABLE is clumsy to use in the
|
||||
internal operation of the IP4 driver.
|
||||
|
||||
@param[in] IpInstance The IP4 child that requests the route table.
|
||||
|
||||
@retval EFI_SUCCESS The route table is successfully build
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the rotue table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4BuildEfiRouteTable (
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_TABLE *RtTable;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
EFI_IP4_ROUTE_TABLE *Table;
|
||||
UINT32 Count;
|
||||
INT32 Index;
|
||||
|
||||
RtTable = IpInstance->RouteTable;
|
||||
|
||||
if (IpInstance->EfiRouteTable != NULL) {
|
||||
FreePool (IpInstance->EfiRouteTable);
|
||||
|
||||
IpInstance->EfiRouteTable = NULL;
|
||||
IpInstance->EfiRouteCount = 0;
|
||||
}
|
||||
|
||||
Count = RtTable->TotalNum;
|
||||
|
||||
if (RtTable->Next != NULL) {
|
||||
Count += RtTable->Next->TotalNum;
|
||||
}
|
||||
|
||||
if (Count == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Table = AllocatePool (sizeof (EFI_IP4_ROUTE_TABLE) * Count);
|
||||
|
||||
if (Table == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the route entry to EFI route table. Keep the order of
|
||||
// route entry copied from most specific to default route. That
|
||||
// is, interlevel the route entry from the instance's route area
|
||||
// and those from the default route table's route area.
|
||||
//
|
||||
Count = 0;
|
||||
|
||||
for (Index = IP4_MASK_MAX; Index >= 0; Index--) {
|
||||
for (RtTable = IpInstance->RouteTable; RtTable != NULL; RtTable = RtTable->Next) {
|
||||
NET_LIST_FOR_EACH (Entry, &(RtTable->RouteArea[Index])) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
EFI_IP4 (Table[Count].SubnetAddress) = HTONL (RtEntry->Dest & RtEntry->Netmask);
|
||||
EFI_IP4 (Table[Count].SubnetMask) = HTONL (RtEntry->Netmask);
|
||||
EFI_IP4 (Table[Count].GatewayAddress) = HTONL (RtEntry->NextHop);
|
||||
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IpInstance->EfiRouteTable = Table;
|
||||
IpInstance->EfiRouteCount = Count;
|
||||
return EFI_SUCCESS;
|
||||
}
|
225
NetworkPkg/Ip4Dxe/Ip4Route.h
Normal file
225
NetworkPkg/Ip4Dxe/Ip4Route.h
Normal file
@@ -0,0 +1,225 @@
|
||||
/** @file
|
||||
EFI IP4 route table and route cache table defintions.
|
||||
|
||||
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_ROUTE_H__
|
||||
#define __EFI_IP4_ROUTE_H__
|
||||
|
||||
#include "Ip4Common.h"
|
||||
|
||||
#define IP4_DIRECT_ROUTE 0x00000001
|
||||
|
||||
#define IP4_ROUTE_CACHE_HASH_VALUE 31
|
||||
#define IP4_ROUTE_CACHE_MAX 64 // Max NO. of cache entry per hash bucket
|
||||
|
||||
#define IP4_ROUTE_CACHE_HASH(Dst, Src) (((Dst) ^ (Src)) % IP4_ROUTE_CACHE_HASH_VALUE)
|
||||
|
||||
///
|
||||
/// The route entry in the route table. Dest/Netmask is the destion
|
||||
/// network. The nexthop is the gateway to send the packet to in
|
||||
/// order to reach the Dest/Netmask. If the Flag has IP4_DIRECT_ROUTE
|
||||
/// on, the gateway is the destination of the IP packet itself. Route
|
||||
/// enties of the connected network have the flag on.
|
||||
///
|
||||
typedef struct {
|
||||
LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
IP4_ADDR Dest;
|
||||
IP4_ADDR Netmask;
|
||||
IP4_ADDR NextHop;
|
||||
UINT32 Flag;
|
||||
} IP4_ROUTE_ENTRY;
|
||||
|
||||
///
|
||||
/// The route cache entry. The route cache entry is optional.
|
||||
/// But it is necessary to support the ICMP redirect message.
|
||||
/// Check Ip4ProcessIcmpRedirect for information.
|
||||
///
|
||||
/// The cache entry field Tag is used to tag all the route
|
||||
/// cache entry spawned from a route table entry. This makes
|
||||
/// it simple to delete all the route cache entries from a
|
||||
/// to-be-deleted route entry.
|
||||
///
|
||||
typedef struct {
|
||||
LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
IP4_ADDR Dest;
|
||||
IP4_ADDR Src;
|
||||
IP4_ADDR NextHop;
|
||||
UINTN Tag;
|
||||
} IP4_ROUTE_CACHE_ENTRY;
|
||||
|
||||
///
|
||||
/// The route cache table is organized as a hash table. Each
|
||||
/// IP4 route table has a embedded route cache. For now the
|
||||
/// route cache and route table are binded togehter. But keep
|
||||
/// the route cache a seperated structure in case we want to
|
||||
/// detach them later.
|
||||
///
|
||||
typedef struct {
|
||||
LIST_ENTRY CacheBucket[IP4_ROUTE_CACHE_HASH_VALUE];
|
||||
} IP4_ROUTE_CACHE;
|
||||
|
||||
///
|
||||
/// Each IP4 instance has its own route table. Each ServiceBinding
|
||||
/// instance has a default route table and default address.
|
||||
///
|
||||
/// All the route table entries with the same mask are linked
|
||||
/// together in one route area. For example, RouteArea[0] contains
|
||||
/// the default routes. A route table also contains a route cache.
|
||||
///
|
||||
typedef struct _IP4_ROUTE_TABLE IP4_ROUTE_TABLE;
|
||||
|
||||
struct _IP4_ROUTE_TABLE {
|
||||
INTN RefCnt;
|
||||
UINT32 TotalNum;
|
||||
LIST_ENTRY RouteArea[IP4_MASK_NUM];
|
||||
IP4_ROUTE_TABLE *Next;
|
||||
IP4_ROUTE_CACHE Cache;
|
||||
};
|
||||
|
||||
/**
|
||||
Create an empty route table, includes its internal route cache
|
||||
|
||||
@return NULL if failed to allocate memory for the route table, otherwise
|
||||
the point to newly created route table.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_TABLE *
|
||||
Ip4CreateRouteTable (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Free the route table and its associated route cache. Route
|
||||
table is reference counted.
|
||||
|
||||
@param[in] RtTable The route table to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4FreeRouteTable (
|
||||
IN IP4_ROUTE_TABLE *RtTable
|
||||
);
|
||||
|
||||
/**
|
||||
Add a route entry to the route table. All the IP4_ADDRs are in
|
||||
host byte order.
|
||||
|
||||
@param[in, out] RtTable Route table to add route to
|
||||
@param[in] Dest The destination of the network
|
||||
@param[in] Netmask The netmask of the destination
|
||||
@param[in] Gateway The next hop address
|
||||
|
||||
@retval EFI_ACCESS_DENIED The same route already exists
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the entry
|
||||
@retval EFI_SUCCESS The route is added successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4AddRoute (
|
||||
IN OUT IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
);
|
||||
|
||||
/**
|
||||
Remove a route entry and all the route caches spawn from it.
|
||||
|
||||
@param RtTable The route table to remove the route from
|
||||
@param Dest The destination network
|
||||
@param Netmask The netmask of the Dest
|
||||
@param Gateway The next hop address
|
||||
|
||||
@retval EFI_SUCCESS The route entry is successfully removed
|
||||
@retval EFI_NOT_FOUND There is no route entry in the table with that
|
||||
properity.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4DelRoute (
|
||||
IN OUT IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
);
|
||||
|
||||
/**
|
||||
Find a route cache with the dst and src. This is used by ICMP
|
||||
redirect messasge process. All kinds of redirect is treated as
|
||||
host redirect according to RFC1122. So, only route cache entries
|
||||
are modified according to the ICMP redirect message.
|
||||
|
||||
@param[in] RtTable The route table to search the cache for
|
||||
@param[in] Dest The destination address
|
||||
@param[in] Src The source address
|
||||
|
||||
@return NULL if no route entry to the (Dest, Src). Otherwise the point
|
||||
to the correct route cache entry.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4FindRouteCache (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src
|
||||
);
|
||||
|
||||
/**
|
||||
Free the route cache entry. It is reference counted.
|
||||
|
||||
@param RtCacheEntry The route cache entry to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4FreeRouteCacheEntry (
|
||||
IN IP4_ROUTE_CACHE_ENTRY *RtCacheEntry
|
||||
);
|
||||
|
||||
/**
|
||||
Search the route table to route the packet. Return/create a route
|
||||
cache if there is a route to the destination.
|
||||
|
||||
@param[in] RtTable The route table to search from
|
||||
@param[in] Dest The destination address to search for
|
||||
@param[in] Src The source address to search for
|
||||
@param[in] SubnetMask The subnet mask of the Src address, this field is
|
||||
used to check if the station is using /32 subnet.
|
||||
@param[in] AlwaysTryDestAddr Always try to use the dest address as next hop even
|
||||
though we can't find a matching route entry. This
|
||||
field is only valid when using /32 subnet.
|
||||
|
||||
@return NULL if failed to route packet, otherwise a route cache
|
||||
entry that can be used to route packet.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4Route (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src,
|
||||
IN IP4_ADDR SubnetMask,
|
||||
IN BOOLEAN AlwaysTryDestAddr
|
||||
);
|
||||
|
||||
/**
|
||||
Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of
|
||||
GetModeData. The EFI_IP4_ROUTE_TABLE is clumsy to use in the
|
||||
internal operation of the IP4 driver.
|
||||
|
||||
@param[in] IpInstance The IP4 child that requests the route table.
|
||||
|
||||
@retval EFI_SUCCESS The route table is successfully build
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the rotue table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4BuildEfiRouteTable (
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
);
|
||||
#endif
|
Reference in New Issue
Block a user