Add NetworkPkg (P.UDK2010.UP3.Network.P1)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10986 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
313
NetworkPkg/Ip6Dxe/ComponentName.c
Normal file
313
NetworkPkg/Ip6Dxe/ComponentName.c
Normal file
@@ -0,0 +1,313 @@
|
||||
/** @file
|
||||
Implementation of EFI_COMPONENT_NAME_PROTOCOL and
|
||||
EFI_COMPONENT_NAME2_PROTOCOL protocol.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip6Impl.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
|
||||
Ip6ComponentNameGetDriverName (
|
||||
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 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 not a valid EFI_HANDLE.
|
||||
|
||||
@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
|
||||
Ip6ComponentNameGetControllerName (
|
||||
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 gIp6ComponentName = {
|
||||
Ip6ComponentNameGetDriverName,
|
||||
Ip6ComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name 2 Protocol.
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIp6ComponentName2 = {
|
||||
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Ip6ComponentNameGetDriverName,
|
||||
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Ip6ComponentNameGetControllerName,
|
||||
"en"
|
||||
};
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIp6DriverNameTable[] = {
|
||||
{
|
||||
"eng;en",
|
||||
L"IP6 Network Service Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
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
|
||||
Ip6ComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
{
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mIp6DriverNameTable,
|
||||
DriverName,
|
||||
(BOOLEAN) (This == &gIp6ComponentName)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
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 not a valid EFI_HANDLE.
|
||||
|
||||
@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
|
||||
Ip6ComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
796
NetworkPkg/Ip6Dxe/Ip6Common.c
Normal file
796
NetworkPkg/Ip6Dxe/Ip6Common.c
Normal file
@@ -0,0 +1,796 @@
|
||||
/** @file
|
||||
The implementation of common functions shared by IP6 driver.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip6Impl.h"
|
||||
|
||||
/**
|
||||
Build a array of EFI_IP6_ADDRESS_INFO to be returned to the caller. The number
|
||||
of EFI_IP6_ADDRESS_INFO is also returned. If AddressList is NULL,
|
||||
only the address count is returned.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
@param[out] AddressCount The number of returned addresses.
|
||||
@param[out] AddressList The pointer to the array of EFI_IP6_ADDRESS_INFO.
|
||||
This is an optional parameter.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The address array successfully built.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the address info.
|
||||
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6BuildEfiAddressList (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
OUT UINT32 *AddressCount,
|
||||
OUT EFI_IP6_ADDRESS_INFO **AddressList OPTIONAL
|
||||
)
|
||||
{
|
||||
UINT32 Count;
|
||||
LIST_ENTRY *Entry;
|
||||
EFI_IP6_ADDRESS_INFO *EfiAddrInfo;
|
||||
IP6_ADDRESS_INFO *AddrInfo;
|
||||
|
||||
if (AddressCount == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (IpSb->LinkLocalOk) {
|
||||
Count = 1 + IpSb->DefaultInterface->AddressCount;
|
||||
} else {
|
||||
Count = 0;
|
||||
}
|
||||
|
||||
*AddressCount = Count;
|
||||
|
||||
if ((AddressList == NULL) || (Count == 0)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (*AddressList == NULL) {
|
||||
*AddressList = AllocatePool (sizeof (EFI_IP6_ADDRESS_INFO) * Count);
|
||||
if (*AddressList == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
EfiAddrInfo = *AddressList;
|
||||
|
||||
IP6_COPY_ADDRESS (&EfiAddrInfo->Address, &IpSb->LinkLocalAddr);
|
||||
EfiAddrInfo->PrefixLength = IP6_LINK_LOCAL_PREFIX_LENGTH;
|
||||
|
||||
EfiAddrInfo++;
|
||||
Count = 1;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->DefaultInterface->AddressList) {
|
||||
AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
|
||||
|
||||
IP6_COPY_ADDRESS (&EfiAddrInfo->Address, &AddrInfo->Address);
|
||||
EfiAddrInfo->PrefixLength = AddrInfo->PrefixLength;
|
||||
|
||||
EfiAddrInfo++;
|
||||
Count++;
|
||||
}
|
||||
|
||||
ASSERT (Count == *AddressCount);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Generate the multicast addresses identify the group of all IPv6 nodes or IPv6
|
||||
routers defined in RFC4291.
|
||||
|
||||
All Nodes Addresses: FF01::1, FF02::1.
|
||||
All Router Addresses: FF01::2, FF02::2, FF05::2.
|
||||
|
||||
@param[in] Router If TRUE, generate all routers addresses,
|
||||
else generate all node addresses.
|
||||
@param[in] Scope interface-local(1), link-local(2), or site-local(5)
|
||||
@param[out] Ip6Addr The generated multicast address.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
|
||||
@retval EFI_SUCCESS The address is generated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SetToAllNodeMulticast (
|
||||
IN BOOLEAN Router,
|
||||
IN UINT8 Scope,
|
||||
OUT EFI_IPv6_ADDRESS *Ip6Addr
|
||||
)
|
||||
{
|
||||
if (Ip6Addr == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!Router && Scope == IP6_SITE_LOCAL_SCOPE) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ZeroMem (Ip6Addr, sizeof (EFI_IPv6_ADDRESS));
|
||||
Ip6Addr->Addr[0] = 0xFF;
|
||||
Ip6Addr->Addr[1] = Scope;
|
||||
|
||||
if (!Router) {
|
||||
Ip6Addr->Addr[15] = 0x1;
|
||||
} else {
|
||||
Ip6Addr->Addr[15] = 0x2;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function converts MAC address to 64 bits interface ID according to RFC4291
|
||||
and returns the interface ID. Currently only 48-bit MAC address is supported by
|
||||
this function.
|
||||
|
||||
@param[in, out] IpSb The IP6 service binding instance.
|
||||
|
||||
@retval NULL The operation fails.
|
||||
@return Pointer to the generated interface ID.
|
||||
|
||||
**/
|
||||
UINT8 *
|
||||
Ip6CreateInterfaceID (
|
||||
IN OUT IP6_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
UINT8 InterfaceId[8];
|
||||
UINT8 Byte;
|
||||
EFI_MAC_ADDRESS *MacAddr;
|
||||
UINT32 AddrLen;
|
||||
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
|
||||
AddrLen = IpSb->SnpMode.HwAddressSize;
|
||||
|
||||
//
|
||||
// Currently only IEEE 802 48-bit MACs are supported to create link local address.
|
||||
//
|
||||
if (AddrLen != IP6_MAC_LEN || IpSb->InterfaceIdLen != IP6_IF_ID_LEN) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MacAddr = &IpSb->SnpMode.CurrentAddress;
|
||||
|
||||
//
|
||||
// Convert MAC address to 64 bits interface ID according to Appendix A of RFC4291:
|
||||
// 1. Insert 0xFFFE to the middle
|
||||
// 2. Invert the universal/local bit - bit 6 in network order
|
||||
//
|
||||
CopyMem (InterfaceId, MacAddr, 3);
|
||||
InterfaceId[3] = 0xFF;
|
||||
InterfaceId[4] = 0xFE;
|
||||
CopyMem (&InterfaceId[5], &MacAddr->Addr[3], 3);
|
||||
|
||||
Byte = (UINT8) (InterfaceId[0] & IP6_U_BIT);
|
||||
if (Byte == IP6_U_BIT) {
|
||||
InterfaceId[0] &= ~IP6_U_BIT;
|
||||
} else {
|
||||
InterfaceId[0] |= IP6_U_BIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Return the interface ID.
|
||||
//
|
||||
return AllocateCopyPool (IpSb->InterfaceIdLen, InterfaceId);
|
||||
}
|
||||
|
||||
/**
|
||||
This function creates link-local address from interface identifier. The
|
||||
interface identifier is normally created from MAC address. It might be manually
|
||||
configured by administrator if the link-local address created from MAC address
|
||||
is a duplicate address.
|
||||
|
||||
@param[in, out] IpSb The IP6 service binding instance.
|
||||
|
||||
@retval NULL If the operation fails.
|
||||
@return The generated Link Local address, in network order.
|
||||
|
||||
**/
|
||||
EFI_IPv6_ADDRESS *
|
||||
Ip6CreateLinkLocalAddr (
|
||||
IN OUT IP6_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
EFI_IPv6_ADDRESS *Ip6Addr;
|
||||
EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
|
||||
UINTN DataSize;
|
||||
EFI_IP6_CONFIG_INTERFACE_ID InterfaceId;
|
||||
EFI_STATUS Status;
|
||||
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
|
||||
if (IpSb->InterfaceId != NULL) {
|
||||
FreePool (IpSb->InterfaceId);
|
||||
}
|
||||
|
||||
//
|
||||
// Get the interface id if it is manully configured.
|
||||
//
|
||||
Ip6Config = &IpSb->Ip6ConfigInstance.Ip6Config;
|
||||
DataSize = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);
|
||||
ZeroMem (&InterfaceId, DataSize);
|
||||
|
||||
Status = Ip6Config->GetData (
|
||||
Ip6Config,
|
||||
Ip6ConfigDataTypeAltInterfaceId,
|
||||
&DataSize,
|
||||
&InterfaceId
|
||||
);
|
||||
if (Status == EFI_NOT_FOUND) {
|
||||
//
|
||||
// Since the interface id is not configured, generate the interface id from
|
||||
// MAC address.
|
||||
//
|
||||
IpSb->InterfaceId = Ip6CreateInterfaceID (IpSb);
|
||||
if (IpSb->InterfaceId == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CopyMem (&InterfaceId, IpSb->InterfaceId, IpSb->InterfaceIdLen);
|
||||
//
|
||||
// Record the interface id.
|
||||
//
|
||||
Status = Ip6Config->SetData (
|
||||
Ip6Config,
|
||||
Ip6ConfigDataTypeAltInterfaceId,
|
||||
DataSize,
|
||||
&InterfaceId
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (IpSb->InterfaceId);
|
||||
IpSb->InterfaceId = NULL;
|
||||
return NULL;
|
||||
}
|
||||
} else if (!EFI_ERROR (Status)) {
|
||||
IpSb->InterfaceId = AllocateCopyPool (DataSize, &InterfaceId);
|
||||
if (IpSb->InterfaceId == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Append FE80::/64 to the left of IPv6 address then return.
|
||||
//
|
||||
Ip6Addr = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
|
||||
if (Ip6Addr == NULL) {
|
||||
FreePool (IpSb->InterfaceId);
|
||||
IpSb->InterfaceId = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CopyMem (&Ip6Addr->Addr[8], IpSb->InterfaceId, IpSb->InterfaceIdLen);
|
||||
Ip6Addr->Addr[1] = 0x80;
|
||||
Ip6Addr->Addr[0] = 0xFE;
|
||||
|
||||
return Ip6Addr;
|
||||
}
|
||||
|
||||
/**
|
||||
Compute the solicited-node multicast address for an unicast or anycast address,
|
||||
by taking the low-order 24 bits of this address, and appending those bits to
|
||||
the prefix FF02:0:0:0:0:1:FF00::/104.
|
||||
|
||||
@param[in] Ip6Addr The unicast or anycast address, in network order.
|
||||
@param[out] MulticastAddr The generated solicited-node multicast address,
|
||||
in network order.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CreateSNMulticastAddr (
|
||||
IN EFI_IPv6_ADDRESS *Ip6Addr,
|
||||
OUT EFI_IPv6_ADDRESS *MulticastAddr
|
||||
)
|
||||
{
|
||||
ASSERT (Ip6Addr != NULL && MulticastAddr != NULL);
|
||||
|
||||
ZeroMem (MulticastAddr, sizeof (EFI_IPv6_ADDRESS));
|
||||
|
||||
MulticastAddr->Addr[0] = 0xFF;
|
||||
MulticastAddr->Addr[1] = 0x02;
|
||||
MulticastAddr->Addr[11] = 0x1;
|
||||
MulticastAddr->Addr[12] = 0xFF;
|
||||
|
||||
CopyMem (&MulticastAddr->Addr[13], &Ip6Addr->Addr[13], 3);
|
||||
}
|
||||
|
||||
/**
|
||||
Insert a node IP6_ADDRESS_INFO to an IP6 interface.
|
||||
|
||||
@param[in, out] IpIf Points to an IP6 interface.
|
||||
@param[in] AddrInfo Points to IP6_ADDRESS_INFO
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6AddAddr (
|
||||
IN OUT IP6_INTERFACE *IpIf,
|
||||
IN IP6_ADDRESS_INFO *AddrInfo
|
||||
)
|
||||
{
|
||||
InsertHeadList (&IpIf->AddressList, &AddrInfo->Link);
|
||||
IpIf->AddressCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
Destroy the IP instance if its StationAddress is removed. It is the help function
|
||||
for Ip6RemoveAddr().
|
||||
|
||||
@param[in, out] IpSb Points to an IP6 service binding instance.
|
||||
@param[in] Address The to be removed address
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6DestroyInstanceByAddress (
|
||||
IN OUT IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Address
|
||||
)
|
||||
{
|
||||
BOOLEAN OneDestroyed;
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
LIST_ENTRY *Entry;
|
||||
IP6_PROTOCOL *Instance;
|
||||
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
|
||||
ServiceBinding = &IpSb->ServiceBinding;
|
||||
|
||||
//
|
||||
// Upper layer IP protocol consumers may have tight relationship between several
|
||||
// IP protocol instances, in other words, calling ServiceBinding->DestroyChild to
|
||||
// destroy one IP child may cause other related IP children destroyed too. This
|
||||
// will probably leave hole in the children list when we iterate it. So everytime
|
||||
// we just destroy one child then back to the start point to iterate the list.
|
||||
//
|
||||
do {
|
||||
OneDestroyed = FALSE;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Children) {
|
||||
Instance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);
|
||||
|
||||
if ((Instance->State == IP6_STATE_CONFIGED) && EFI_IP6_EQUAL (&Instance->ConfigData.StationAddress, Address)) {
|
||||
ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
|
||||
OneDestroyed = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (OneDestroyed);
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the IPv6 address from the address list node points to IP6_ADDRESS_INFO.
|
||||
|
||||
This function removes the matching IPv6 addresses from the address list and
|
||||
adjusts the address count of the address list. If IpSb is not NULL, this function
|
||||
calls Ip6LeaveGroup to see whether it should call Mnp->Groups() to remove the
|
||||
its solicited-node multicast MAC address from the filter list and sends out
|
||||
a Multicast Listener Done. If Prefix is NULL, all address in the address list
|
||||
will be removed. If Prefix is not NULL, the address that matching the Prefix
|
||||
with PrefixLength in the address list will be removed.
|
||||
|
||||
@param[in] IpSb NULL or points to IP6 service binding instance.
|
||||
@param[in, out] AddressList Address list array.
|
||||
@param[in, out] AddressCount The count of addresses in address list array.
|
||||
@param[in] Prefix NULL or an IPv6 address prefix.
|
||||
@param[in] PrefixLength The length of Prefix.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_NOT_FOUND The address matching the Prefix with PrefixLength
|
||||
cannot be found in the address list.
|
||||
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6RemoveAddr (
|
||||
IN IP6_SERVICE *IpSb OPTIONAL,
|
||||
IN OUT LIST_ENTRY *AddressList,
|
||||
IN OUT UINT32 *AddressCount,
|
||||
IN EFI_IPv6_ADDRESS *Prefix OPTIONAL,
|
||||
IN UINT8 PrefixLength
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
IP6_ADDRESS_INFO *AddrInfo;
|
||||
EFI_IPv6_ADDRESS SnMCastAddr;
|
||||
|
||||
if (IsListEmpty (AddressList) || *AddressCount < 1 || PrefixLength > IP6_PREFIX_NUM) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = EFI_NOT_FOUND;
|
||||
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, AddressList) {
|
||||
AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
|
||||
|
||||
if (Prefix == NULL ||
|
||||
(PrefixLength == 128 && EFI_IP6_EQUAL (Prefix, &AddrInfo->Address)) ||
|
||||
(PrefixLength == AddrInfo->PrefixLength && NetIp6IsNetEqual (Prefix, &AddrInfo->Address, PrefixLength))
|
||||
) {
|
||||
if (IpSb != NULL) {
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
Ip6CreateSNMulticastAddr (&AddrInfo->Address, &SnMCastAddr);
|
||||
Ip6LeaveGroup (IpSb, &SnMCastAddr);
|
||||
|
||||
//
|
||||
// Destroy any instance who is using the dying address as the source address.
|
||||
//
|
||||
Ip6DestroyInstanceByAddress (IpSb, &AddrInfo->Address);
|
||||
}
|
||||
|
||||
RemoveEntryList (Entry);
|
||||
FreePool (AddrInfo);
|
||||
(*AddressCount)--;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether the incoming Ipv6 address is a solicited-node multicast address.
|
||||
|
||||
@param[in] Ip6 Ip6 address, in network order.
|
||||
|
||||
@retval TRUE Yes, solicited-node multicast address
|
||||
@retval FALSE No
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsSNMulticastAddr (
|
||||
IN EFI_IPv6_ADDRESS *Ip6
|
||||
)
|
||||
{
|
||||
EFI_IPv6_ADDRESS Sn;
|
||||
BOOLEAN Flag;
|
||||
|
||||
Ip6CreateSNMulticastAddr (Ip6, &Sn);
|
||||
Flag = FALSE;
|
||||
|
||||
if (CompareMem (Sn.Addr, Ip6->Addr, 13) == 0) {
|
||||
Flag = TRUE;
|
||||
}
|
||||
|
||||
return Flag;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether the incoming IPv6 address is one of the maintained addresses in
|
||||
the IP6 service binding instance.
|
||||
|
||||
@param[in] IpSb Points to a IP6 service binding instance.
|
||||
@param[in] Address The IP6 address to be checked.
|
||||
@param[out] Interface If not NULL, output the IP6 interface which
|
||||
maintains the Address.
|
||||
@param[out] AddressInfo If not NULL, output the IP6 address information
|
||||
of the Address.
|
||||
|
||||
@retval TRUE Yes, it is one of the maintained address.
|
||||
@retval FALSE No, it is not one of the maintained address.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsOneOfSetAddress (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Address,
|
||||
OUT IP6_INTERFACE **Interface OPTIONAL,
|
||||
OUT IP6_ADDRESS_INFO **AddressInfo OPTIONAL
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Entry2;
|
||||
IP6_INTERFACE *IpIf;
|
||||
IP6_ADDRESS_INFO *TmpAddressInfo;
|
||||
|
||||
//
|
||||
// Check link-local address first
|
||||
//
|
||||
if (IpSb->LinkLocalOk && EFI_IP6_EQUAL (&IpSb->LinkLocalAddr, Address)) {
|
||||
if (Interface != NULL) {
|
||||
*Interface = IpSb->DefaultInterface;
|
||||
}
|
||||
|
||||
if (AddressInfo != NULL) {
|
||||
*AddressInfo = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
|
||||
|
||||
NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {
|
||||
TmpAddressInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
|
||||
|
||||
if (EFI_IP6_EQUAL (&TmpAddressInfo->Address, Address)) {
|
||||
if (Interface != NULL) {
|
||||
*Interface = IpIf;
|
||||
}
|
||||
|
||||
if (AddressInfo != NULL) {
|
||||
*AddressInfo = TmpAddressInfo;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether the incoming MAC address is valid.
|
||||
|
||||
@param[in] IpSb Points to a IP6 service binding instance.
|
||||
@param[in] LinkAddress The MAC address.
|
||||
|
||||
@retval TRUE Yes, it is valid.
|
||||
@retval FALSE No, it is not valid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsValidLinkAddress (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_MAC_ADDRESS *LinkAddress
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
//
|
||||
// TODO: might be updated later to be more acceptable.
|
||||
//
|
||||
for (Index = IpSb->SnpMode.HwAddressSize; Index < sizeof (EFI_MAC_ADDRESS); Index++) {
|
||||
if (LinkAddress->Addr[Index] != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Copy the PrefixLength bits from Src to Dest.
|
||||
|
||||
@param[out] Dest A pointer to the buffer to copy to.
|
||||
@param[in] Src A pointer to the buffer to copy from.
|
||||
@param[in] PrefixLength The number of bits to copy.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CopyAddressByPrefix (
|
||||
OUT EFI_IPv6_ADDRESS *Dest,
|
||||
IN EFI_IPv6_ADDRESS *Src,
|
||||
IN UINT8 PrefixLength
|
||||
)
|
||||
{
|
||||
UINT8 Byte;
|
||||
UINT8 Bit;
|
||||
UINT8 Mask;
|
||||
|
||||
ASSERT (Dest != NULL && Src != NULL);
|
||||
ASSERT (PrefixLength < IP6_PREFIX_NUM);
|
||||
|
||||
Byte = (UINT8) (PrefixLength / 8);
|
||||
Bit = (UINT8) (PrefixLength % 8);
|
||||
|
||||
ZeroMem (Dest, sizeof (EFI_IPv6_ADDRESS));
|
||||
|
||||
CopyMem (Dest, Src, Byte);
|
||||
|
||||
if (Bit > 0) {
|
||||
Mask = (UINT8) (0xFF << (8 - Bit));
|
||||
ASSERT (Byte < 16);
|
||||
Dest->Addr[Byte] = (UINT8) (Src->Addr[Byte] & Mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get the MAC address for a multicast IP address. Call
|
||||
Mnp's McastIpToMac to find the MAC address instead of
|
||||
hard-coding 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 The multicast IP successfully
|
||||
translated to a multicast MAC address.
|
||||
@retval Other The address is not converted because an error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6GetMulticastMac (
|
||||
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
|
||||
IN EFI_IPv6_ADDRESS *Multicast,
|
||||
OUT EFI_MAC_ADDRESS *Mac
|
||||
)
|
||||
{
|
||||
EFI_IP_ADDRESS EfiIp;
|
||||
|
||||
IP6_COPY_ADDRESS (&EfiIp.v6, Multicast);
|
||||
|
||||
return Mnp->McastIpToMac (Mnp, TRUE, &EfiIp, Mac);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the Ip6 variable data.
|
||||
|
||||
@param[in] IpSb Points to an IP6 service binding instance.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.
|
||||
@retval other Set variable failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SetVariableData (
|
||||
IN IP6_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
UINT32 NumConfiguredInstance;
|
||||
LIST_ENTRY *Entry;
|
||||
UINTN VariableDataSize;
|
||||
EFI_IP6_VARIABLE_DATA *Ip6VariableData;
|
||||
EFI_IP6_ADDRESS_PAIR *Ip6AddressPair;
|
||||
IP6_PROTOCOL *IpInstance;
|
||||
CHAR16 *NewMacString;
|
||||
EFI_STATUS Status;
|
||||
|
||||
NumConfiguredInstance = 0;
|
||||
|
||||
//
|
||||
// Go through the children list to count the configured children.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Children) {
|
||||
IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);
|
||||
|
||||
if (IpInstance->State == IP6_STATE_CONFIGED) {
|
||||
NumConfiguredInstance++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the size of the Ip6VariableData. As there may be no IP child,
|
||||
// we should add extra buffer for the address paris only if the number of configured
|
||||
// children is more than 1.
|
||||
//
|
||||
VariableDataSize = sizeof (EFI_IP6_VARIABLE_DATA);
|
||||
|
||||
if (NumConfiguredInstance > 1) {
|
||||
VariableDataSize += sizeof (EFI_IP6_ADDRESS_PAIR) * (NumConfiguredInstance - 1);
|
||||
}
|
||||
|
||||
Ip6VariableData = AllocatePool (VariableDataSize);
|
||||
if (Ip6VariableData == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Ip6VariableData->DriverHandle = IpSb->Image;
|
||||
Ip6VariableData->AddressCount = NumConfiguredInstance;
|
||||
|
||||
Ip6AddressPair = &Ip6VariableData->AddressPairs[0];
|
||||
|
||||
//
|
||||
// Go through the children list to fill the configured children's address pairs.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Children) {
|
||||
IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);
|
||||
|
||||
if (IpInstance->State == IP6_STATE_CONFIGED) {
|
||||
Ip6AddressPair->InstanceHandle = IpInstance->Handle;
|
||||
Ip6AddressPair->PrefixLength = IpInstance->PrefixLength;
|
||||
IP6_COPY_ADDRESS (&Ip6AddressPair->Ip6Address, &IpInstance->ConfigData.StationAddress);
|
||||
|
||||
Ip6AddressPair++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get the mac string.
|
||||
//
|
||||
Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &NewMacString);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (IpSb->MacString != NULL) {
|
||||
//
|
||||
// The variable is set already, we're going to update it.
|
||||
//
|
||||
if (StrCmp (IpSb->MacString, NewMacString) != 0) {
|
||||
//
|
||||
// The mac address is changed, delete the previous variable first.
|
||||
//
|
||||
gRT->SetVariable (
|
||||
IpSb->MacString,
|
||||
&gEfiIp6ServiceBindingProtocolGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
FreePool (IpSb->MacString);
|
||||
}
|
||||
|
||||
IpSb->MacString = NewMacString;
|
||||
|
||||
Status = gRT->SetVariable (
|
||||
IpSb->MacString,
|
||||
&gEfiIp6ServiceBindingProtocolGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
VariableDataSize,
|
||||
(VOID *) Ip6VariableData
|
||||
);
|
||||
|
||||
Exit:
|
||||
FreePool (Ip6VariableData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Clear the variable and free the resource.
|
||||
|
||||
@param[in] IpSb Ip6 service binding instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6ClearVariableData (
|
||||
IN IP6_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
ASSERT (IpSb->MacString != NULL);
|
||||
|
||||
gRT->SetVariable (
|
||||
IpSb->MacString,
|
||||
&gEfiIp6ServiceBindingProtocolGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
FreePool (IpSb->MacString);
|
||||
IpSb->MacString = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
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, out] Head The IP head to convert.
|
||||
|
||||
@return Point to the converted IP head.
|
||||
|
||||
**/
|
||||
EFI_IP6_HEADER *
|
||||
Ip6NtohHead (
|
||||
IN OUT EFI_IP6_HEADER *Head
|
||||
)
|
||||
{
|
||||
Head->FlowLabelL = NTOHS (Head->FlowLabelL);
|
||||
Head->PayloadLength = NTOHS (Head->PayloadLength);
|
||||
|
||||
return Head;
|
||||
}
|
||||
|
338
NetworkPkg/Ip6Dxe/Ip6Common.h
Normal file
338
NetworkPkg/Ip6Dxe/Ip6Common.h
Normal file
@@ -0,0 +1,338 @@
|
||||
/** @file
|
||||
Common definition and functions for IP6 driver.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP6_COMMON_H__
|
||||
#define __EFI_IP6_COMMON_H__
|
||||
|
||||
#define IP6_LINK_EQUAL(Mac1, Mac2) (CompareMem ((Mac1), (Mac2), sizeof (EFI_MAC_ADDRESS)) == 0)
|
||||
|
||||
//
|
||||
// Convert the Microsecond to second. IP transmit/receive time is
|
||||
// in the unit of microsecond. IP ticks once per second.
|
||||
//
|
||||
#define IP6_US_TO_SEC(Us) (((Us) + 999999) / 1000000)
|
||||
|
||||
#define IP6_ETHER_PROTO 0x86DD
|
||||
|
||||
#define IP6_MAC_LEN 6
|
||||
#define IP6_IF_ID_LEN 8
|
||||
|
||||
#define IP6_INTERFACE_LOCAL_SCOPE 1
|
||||
#define IP6_LINK_LOCAL_SCOPE 2
|
||||
#define IP6_SITE_LOCAL_SCOPE 5
|
||||
|
||||
#define IP6_INFINIT_LIFETIME 0xFFFFFFFF
|
||||
|
||||
#define IP6_HOP_LIMIT 255
|
||||
//
|
||||
// Make it to 64 since all 54 bits are zero.
|
||||
//
|
||||
#define IP6_LINK_LOCAL_PREFIX_LENGTH 64
|
||||
|
||||
#define IP6_TIMER_INTERVAL_IN_MS 100
|
||||
#define IP6_ONE_SECOND_IN_MS 1000
|
||||
|
||||
//
|
||||
// The packet is received as link level broadcast/multicast/promiscuous.
|
||||
//
|
||||
#define IP6_LINK_BROADCAST 0x00000001
|
||||
#define IP6_LINK_MULTICAST 0x00000002
|
||||
#define IP6_LINK_PROMISC 0x00000004
|
||||
|
||||
#define IP6_U_BIT 0x02
|
||||
|
||||
typedef enum {
|
||||
Ip6Promiscuous = 1,
|
||||
Ip6Unicast,
|
||||
Ip6Multicast,
|
||||
Ip6AnyCast
|
||||
} IP6_ADDRESS_TYPE;
|
||||
|
||||
typedef struct _IP6_INTERFACE IP6_INTERFACE;
|
||||
typedef struct _IP6_PROTOCOL IP6_PROTOCOL;
|
||||
typedef struct _IP6_SERVICE IP6_SERVICE;
|
||||
typedef struct _IP6_ADDRESS_INFO IP6_ADDRESS_INFO;
|
||||
|
||||
/**
|
||||
Build a array of EFI_IP6_ADDRESS_INFO to be returned to the caller. The number
|
||||
of EFI_IP6_ADDRESS_INFO is also returned. If AddressList is NULL,
|
||||
only the address count is returned.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
@param[out] AddressCount The number of returned addresses.
|
||||
@param[out] AddressList The pointer to the array of EFI_IP6_ADDRESS_INFO.
|
||||
This is an optional parameter.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The address array is successfully build
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the address info.
|
||||
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6BuildEfiAddressList (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
OUT UINT32 *AddressCount,
|
||||
OUT EFI_IP6_ADDRESS_INFO **AddressList OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Generate the multicast addresses identify the group of all IPv6 nodes or IPv6
|
||||
routers defined in RFC4291.
|
||||
|
||||
All Nodes Addresses: FF01::1, FF02::1.
|
||||
All Router Addresses: FF01::2, FF02::2, FF05::2.
|
||||
|
||||
@param[in] Router If TRUE, generate all routers addresses,
|
||||
else generate all node addresses.
|
||||
@param[in] Scope interface-local(1), link-local(2), or site-local(5)
|
||||
@param[out] Ip6Addr The generated multicast address.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
|
||||
@retval EFI_SUCCESS The address is generated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SetToAllNodeMulticast (
|
||||
IN BOOLEAN Router,
|
||||
IN UINT8 Scope,
|
||||
OUT EFI_IPv6_ADDRESS *Ip6Addr
|
||||
);
|
||||
|
||||
/**
|
||||
This function converts MAC address to 64 bits interface ID according to RFC4291
|
||||
and returns the interface ID. Currently only 48-bit MAC address is supported by
|
||||
this function.
|
||||
|
||||
@param[in, out] IpSb The IP6 service binding instance.
|
||||
|
||||
@retval NULL The operation fails.
|
||||
@return Pointer to the generated interface ID.
|
||||
|
||||
**/
|
||||
UINT8 *
|
||||
Ip6CreateInterfaceID (
|
||||
IN OUT IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
This function creates link-local address from interface identifier. The
|
||||
interface identifier is normally created from MAC address. It might be manually
|
||||
configured by administrator if the link-local address created from MAC address
|
||||
is a duplicate address.
|
||||
|
||||
@param[in, out] IpSb The IP6 service binding instance.
|
||||
|
||||
@retval NULL If the operation fails.
|
||||
@return The generated Link Local address, in network order.
|
||||
|
||||
**/
|
||||
EFI_IPv6_ADDRESS *
|
||||
Ip6CreateLinkLocalAddr (
|
||||
IN OUT IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Compute the solicited-node multicast address for an unicast or anycast address,
|
||||
by taking the low-order 24 bits of this address, and appending those bits to
|
||||
the prefix FF02:0:0:0:0:1:FF00::/104.
|
||||
|
||||
@param Ip6Addr The unicast or anycast address, in network order.
|
||||
@param MulticastAddr The generated solicited-node multicast address,
|
||||
in network order.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CreateSNMulticastAddr (
|
||||
IN EFI_IPv6_ADDRESS *Ip6Addr,
|
||||
OUT EFI_IPv6_ADDRESS *MulticastAddr
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether the incoming Ipv6 address is a solicited-node multicast address.
|
||||
|
||||
@param[in] Ip6 Ip6 address, in network order.
|
||||
|
||||
@retval TRUE Yes, solicited-node multicast address
|
||||
@retval FALSE No
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsSNMulticastAddr (
|
||||
IN EFI_IPv6_ADDRESS *Ip6
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether the incoming IPv6 address is one of the maintained address in
|
||||
the IP6 service binding instance.
|
||||
|
||||
@param[in] IpSb Points to a IP6 service binding instance
|
||||
@param[in] Address The IP6 address to be checked.
|
||||
@param[out] Interface If not NULL, output the IP6 interface which
|
||||
maintains the Address.
|
||||
@param[out] AddressInfo If not NULL, output the IP6 address information
|
||||
of the Address.
|
||||
|
||||
@retval TRUE Yes, it is one of the maintained addresses.
|
||||
@retval FALSE No, it is not one of the maintained addresses.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsOneOfSetAddress (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Address,
|
||||
OUT IP6_INTERFACE **Interface OPTIONAL,
|
||||
OUT IP6_ADDRESS_INFO **AddressInfo OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether the incoming MAC address is valid.
|
||||
|
||||
@param[in] IpSb Points to a IP6 service binding instance.
|
||||
@param[in] LinkAddress The MAC address.
|
||||
|
||||
@retval TRUE Yes, it is valid.
|
||||
@retval FALSE No, it is not valid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsValidLinkAddress (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_MAC_ADDRESS *LinkAddress
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Copy the PrefixLength bits from Src to Dest.
|
||||
|
||||
@param[out] Dest A pointer to the buffer to copy to.
|
||||
@param[in] Src A pointer to the buffer to copy from.
|
||||
@param[in] PrefixLength The number of bits to copy.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CopyAddressByPrefix (
|
||||
OUT EFI_IPv6_ADDRESS *Dest,
|
||||
IN EFI_IPv6_ADDRESS *Src,
|
||||
IN UINT8 PrefixLength
|
||||
);
|
||||
|
||||
/**
|
||||
Insert a node IP6_ADDRESS_INFO to an IP6 interface.
|
||||
|
||||
@param[in, out] IpIf Points to an IP6 interface.
|
||||
@param[in] AddrInfo Points to an IP6_ADDRESS_INFO.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6AddAddr (
|
||||
IN OUT IP6_INTERFACE *IpIf,
|
||||
IN IP6_ADDRESS_INFO *AddrInfo
|
||||
);
|
||||
|
||||
/**
|
||||
Remove the IPv6 address from the address list node points to IP6_ADDRESS_INFO.
|
||||
|
||||
This function removes the matching IPv6 addresses from the address list and
|
||||
adjusts the address count of the address list. If IpSb is not NULL, this function
|
||||
calls Ip6LeaveGroup to see whether it should call Mnp->Groups() to remove the
|
||||
its solicited-node multicast MAC address from the filter list and sends out
|
||||
a Multicast Listener Done. If Prefix is NULL, all address in the address list
|
||||
will be removed. If Prefix is not NULL, the address that matching the Prefix
|
||||
with PrefixLength in the address list will be removed.
|
||||
|
||||
@param[in] IpSb NULL or points to IP6 service binding instance.
|
||||
@param[in, out] AddressList address list array
|
||||
@param[in, out] AddressCount the count of addresses in address list array
|
||||
@param[in] Prefix NULL or an IPv6 address prefix
|
||||
@param[in] PrefixLength the length of Prefix
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_NOT_FOUND The address matching the Prefix with PrefixLength
|
||||
cannot be found in address list.
|
||||
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6RemoveAddr (
|
||||
IN IP6_SERVICE *IpSb OPTIONAL,
|
||||
IN OUT LIST_ENTRY *AddressList,
|
||||
IN OUT UINT32 *AddressCount,
|
||||
IN EFI_IPv6_ADDRESS *Prefix OPTIONAL,
|
||||
IN UINT8 PrefixLength
|
||||
);
|
||||
|
||||
/**
|
||||
Set the Ip6 variable data.
|
||||
|
||||
@param[in] IpSb Points to an IP6 service binding instance
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.
|
||||
@retval other Set variable failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SetVariableData (
|
||||
IN IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Clear the variable and free the resource.
|
||||
|
||||
@param[in] IpSb Ip6 service binding instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6ClearVariableData (
|
||||
IN IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Get the MAC address for a multicast IP address. Call
|
||||
Mnp's McastIpToMac to find the MAC address instead of
|
||||
hard-coding 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 The multicast IP is successfully
|
||||
translated to a multicast MAC address.
|
||||
@retval Other The address is not converted because an error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6GetMulticastMac (
|
||||
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
|
||||
IN EFI_IPv6_ADDRESS *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, out] Head The IP head to convert.
|
||||
|
||||
@return Point to the converted IP head.
|
||||
|
||||
**/
|
||||
EFI_IP6_HEADER *
|
||||
Ip6NtohHead (
|
||||
IN OUT EFI_IP6_HEADER *Head
|
||||
);
|
||||
|
||||
#endif
|
170
NetworkPkg/Ip6Dxe/Ip6Config.vfr
Normal file
170
NetworkPkg/Ip6Dxe/Ip6Config.vfr
Normal file
@@ -0,0 +1,170 @@
|
||||
/** @file
|
||||
VFR file used by the IP6 configuration component.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip6NvData.h"
|
||||
|
||||
#define EFI_NETWORK_DEVICE_CLASS 0x04
|
||||
|
||||
formset
|
||||
guid = IP6_CONFIG_NVDATA_GUID,
|
||||
title = STRING_TOKEN(STR_IP6_CONFIG_FORM_TITLE),
|
||||
help = STRING_TOKEN(STR_IP6_CONFIG_FORM_HELP),
|
||||
class = EFI_NETWORK_DEVICE_CLASS,
|
||||
subclass = 0x03,
|
||||
|
||||
varstore IP6_CONFIG_IFR_NVDATA,
|
||||
name = IP6_CONFIG_IFR_NVDATA,
|
||||
guid = IP6_CONFIG_NVDATA_GUID;
|
||||
|
||||
form formid = FORMID_MAIN_FORM,
|
||||
title = STRING_TOKEN(STR_IP6_DEVICE_FORM_TITLE);
|
||||
|
||||
text
|
||||
help = STRING_TOKEN(STR_IP6_INTERFACE_NAME_HELP),
|
||||
text = STRING_TOKEN(STR_IP6_INTERFACE_NAME),
|
||||
text = STRING_TOKEN(STR_IP6_INTERFACE_NAME_CONTENT);
|
||||
|
||||
text
|
||||
help = STRING_TOKEN(STR_IP6_INTERFACE_TYPE_HELP),
|
||||
text = STRING_TOKEN(STR_IP6_INTERFACE_TYPE),
|
||||
text = STRING_TOKEN(STR_IP6_INTERFACE_TYPE_CONTENT);
|
||||
|
||||
text
|
||||
help = STRING_TOKEN(STR_IP6_MAC_ADDRESS_HELP),
|
||||
text = STRING_TOKEN(STR_IP6_MAC_ADDRESS),
|
||||
text = STRING_TOKEN(STR_IP6_MAC_ADDRESS_CONTENT);
|
||||
|
||||
text
|
||||
help = STRING_TOKEN(STR_IP6_HOST_ADDRESS_HELP),
|
||||
text = STRING_TOKEN(STR_IP6_HOST_ADDRESS),
|
||||
text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
label HOST_ADDRESS_LABEL;
|
||||
label LABEL_END;
|
||||
|
||||
text
|
||||
help = STRING_TOKEN(STR_IP6_ROUTE_TABLE_HELP),
|
||||
text = STRING_TOKEN(STR_IP6_ROUTE_TABLE),
|
||||
text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
label ROUTE_TABLE_LABEL;
|
||||
label LABEL_END;
|
||||
|
||||
text
|
||||
help = STRING_TOKEN(STR_IP6_GATEWAY_ADDRESS_HELP),
|
||||
text = STRING_TOKEN(STR_IP6_GATEWAY_ADDRESS),
|
||||
text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
label GATEWAY_ADDRESS_LABEL;
|
||||
label LABEL_END;
|
||||
|
||||
text
|
||||
help = STRING_TOKEN(STR_IP6_DNS_ADDRESS_HELP),
|
||||
text = STRING_TOKEN(STR_IP6_DNS_ADDRESS),
|
||||
text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
label DNS_ADDRESS_LABEL;
|
||||
label LABEL_END;
|
||||
|
||||
string varid = IP6_CONFIG_IFR_NVDATA.InterfaceId,
|
||||
prompt = STRING_TOKEN(STR_IP6_INTERFACE_ID),
|
||||
help = STRING_TOKEN(STR_IP6_INTERFACE_ID_HELP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_INTERFACE_ID,
|
||||
minsize = INTERFACE_ID_STR_MIN_SIZE,
|
||||
maxsize = INTERFACE_ID_STR_MAX_SIZE,
|
||||
endstring;
|
||||
|
||||
numeric varid = IP6_CONFIG_IFR_NVDATA.DadTransmitCount,
|
||||
prompt = STRING_TOKEN(STR_IP6_DAD_TRANSMIT_COUNT),
|
||||
help = STRING_TOKEN(STR_IP6_DAD_TRANSMIT_COUNT_HELP),
|
||||
flags = 0,
|
||||
minimum = 0,
|
||||
maximum = DAD_MAX_TRANSMIT_COUNT,
|
||||
step = 0,
|
||||
endnumeric;
|
||||
|
||||
oneof varid = IP6_CONFIG_IFR_NVDATA.Policy,
|
||||
prompt = STRING_TOKEN(STR_POLICY_TYPE_PROMPT),
|
||||
help = STRING_TOKEN(STR_POLICY_TYPE_HELP),
|
||||
option text = STRING_TOKEN(STR_POLICY_TYPE_AUTO), value = IP6_POLICY_AUTO, flags = DEFAULT;
|
||||
option text = STRING_TOKEN(STR_POLICY_TYPE_MANUAL), value = IP6_POLICY_MANUAL, flags = 0;
|
||||
endoneof;
|
||||
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
suppressif ideqval IP6_CONFIG_IFR_NVDATA.Policy == IP6_POLICY_AUTO;
|
||||
goto FORMID_MANUAL_CONFIG_FORM,
|
||||
prompt = STRING_TOKEN(STR_IP6_AD_CONFIG_FORM),
|
||||
help = STRING_TOKEN(STR_IP6_AD_CONFIG_FORM_HELP),
|
||||
flags = 0;
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
endif;
|
||||
|
||||
text
|
||||
help = STRING_TOKEN (STR_SAVE_CHANGES_HELP),
|
||||
text = STRING_TOKEN (STR_SAVE_CHANGES),
|
||||
text = STRING_TOKEN (STR_NULL),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_SAVE_CHANGES;
|
||||
|
||||
endform;
|
||||
|
||||
form formid = FORMID_MANUAL_CONFIG_FORM,
|
||||
title = STRING_TOKEN(STR_IP6_AD_CONFIG_FORM);
|
||||
|
||||
string varid = IP6_CONFIG_IFR_NVDATA.ManualAddress,
|
||||
prompt = STRING_TOKEN(STR_IP6_MANUAL_ADDRESS),
|
||||
help = STRING_TOKEN(STR_IP6_MANUAL_ADDRESS_HELP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_MANUAL_ADDRESS,
|
||||
minsize = ADDRESS_STR_MIN_SIZE,
|
||||
maxsize = ADDRESS_STR_MAX_SIZE,
|
||||
endstring;
|
||||
|
||||
string varid = IP6_CONFIG_IFR_NVDATA.GatewayAddress,
|
||||
prompt = STRING_TOKEN(STR_IP6_NEW_GATEWAY_ADDRESS),
|
||||
help = STRING_TOKEN(STR_IP6_NEW_GATEWAY_ADDR_HELP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_GATEWAY_ADDRESS,
|
||||
minsize = ADDRESS_STR_MIN_SIZE,
|
||||
maxsize = ADDRESS_STR_MAX_SIZE,
|
||||
endstring;
|
||||
|
||||
string varid = IP6_CONFIG_IFR_NVDATA.DnsAddress,
|
||||
prompt = STRING_TOKEN(STR_IP6_NEW_DNS_ADDRESS),
|
||||
help = STRING_TOKEN(STR_IP6_NEW_DNS_ADDRESS_HELP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_DNS_ADDRESS,
|
||||
minsize = ADDRESS_STR_MIN_SIZE,
|
||||
maxsize = ADDRESS_STR_MAX_SIZE,
|
||||
endstring;
|
||||
|
||||
goto FORMID_MAIN_FORM,
|
||||
prompt = STRING_TOKEN (STR_SAVE_AND_EXIT),
|
||||
help = STRING_TOKEN (STR_SAVE_AND_EXIT),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_SAVE_CONFIG_CHANGES;
|
||||
|
||||
goto FORMID_MAIN_FORM,
|
||||
prompt = STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
|
||||
help = STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_IGNORE_CONFIG_CHANGES;
|
||||
|
||||
endform;
|
||||
|
||||
endformset;
|
||||
|
2369
NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
Normal file
2369
NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
Normal file
File diff suppressed because it is too large
Load Diff
295
NetworkPkg/Ip6Dxe/Ip6ConfigImpl.h
Normal file
295
NetworkPkg/Ip6Dxe/Ip6ConfigImpl.h
Normal file
@@ -0,0 +1,295 @@
|
||||
/** @file
|
||||
Definitions for EFI IPv6 Configuartion Protocol implementation.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __IP6_CONFIG_IMPL_H__
|
||||
#define __IP6_CONFIG_IMPL_H__
|
||||
|
||||
#define IP6_CONFIG_INSTANCE_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'C')
|
||||
#define IP6_FORM_CALLBACK_INFO_SIGNATURE SIGNATURE_32 ('I', 'F', 'C', 'I')
|
||||
#define IP6_CONFIG_VARIABLE_ATTRIBUTE (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)
|
||||
|
||||
#define IP6_CONFIG_DEFAULT_DAD_XMITS 1
|
||||
#define IP6_CONFIG_DHCP6_OPTION_ORO 6
|
||||
#define IP6_CONFIG_DHCP6_OPTION_DNS_SERVERS 23
|
||||
|
||||
#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))
|
||||
|
||||
typedef struct _IP6_CONFIG_INSTANCE IP6_CONFIG_INSTANCE;
|
||||
|
||||
#define IP6_CONFIG_INSTANCE_FROM_PROTOCOL(Proto) \
|
||||
CR ((Proto), \
|
||||
IP6_CONFIG_INSTANCE, \
|
||||
Ip6Config, \
|
||||
IP6_CONFIG_INSTANCE_SIGNATURE \
|
||||
)
|
||||
|
||||
|
||||
#define IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK(Callback) \
|
||||
CR ((Callback), \
|
||||
IP6_CONFIG_INSTANCE, \
|
||||
CallbackInfo, \
|
||||
IP6_CONFIG_INSTANCE_SIGNATURE \
|
||||
)
|
||||
|
||||
#define IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE(Instance) \
|
||||
CR ((Instance), \
|
||||
IP6_SERVICE, \
|
||||
Ip6ConfigInstance, \
|
||||
IP6_SERVICE_SIGNATURE \
|
||||
)
|
||||
|
||||
#define IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(ConfigAccess) \
|
||||
CR ((ConfigAccess), \
|
||||
IP6_FORM_CALLBACK_INFO, \
|
||||
HiiConfigAccess, \
|
||||
IP6_FORM_CALLBACK_INFO_SIGNATURE \
|
||||
)
|
||||
|
||||
/**
|
||||
The prototype of work function for EfiIp6ConfigSetData().
|
||||
|
||||
@param[in] Instance The pointer to the IP6 config 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 IPv6
|
||||
network stack was set successfully.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(*IP6_CONFIG_SET_DATA) (
|
||||
IN IP6_CONFIG_INSTANCE *Instance,
|
||||
IN UINTN DataSize,
|
||||
IN VOID *Data
|
||||
);
|
||||
|
||||
/**
|
||||
The prototype of work function for EfiIp6ConfigGetData().
|
||||
|
||||
@param[in] Instance The pointer to the IP6 config 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
|
||||
(*IP6_CONFIG_GET_DATA) (
|
||||
IN IP6_CONFIG_INSTANCE *Instance,
|
||||
IN OUT UINTN *DataSize,
|
||||
IN VOID *Data OPTIONAL
|
||||
);
|
||||
|
||||
typedef union {
|
||||
VOID *Ptr;
|
||||
EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
|
||||
EFI_IP6_CONFIG_INTERFACE_ID *AltIfId;
|
||||
EFI_IP6_CONFIG_POLICY *Policy;
|
||||
EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS *DadXmits;
|
||||
EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress;
|
||||
EFI_IPv6_ADDRESS *Gateway;
|
||||
EFI_IPv6_ADDRESS *DnsServers;
|
||||
} IP6_CONFIG_DATA;
|
||||
|
||||
typedef struct {
|
||||
IP6_CONFIG_SET_DATA SetData;
|
||||
IP6_CONFIG_GET_DATA GetData;
|
||||
EFI_STATUS Status;
|
||||
UINT8 Attribute;
|
||||
NET_MAP EventMap;
|
||||
IP6_CONFIG_DATA Data;
|
||||
UINTN DataSize;
|
||||
} IP6_CONFIG_DATA_ITEM;
|
||||
|
||||
typedef struct {
|
||||
UINT16 Offset;
|
||||
UINTN DataSize;
|
||||
EFI_IP6_CONFIG_DATA_TYPE DataType;
|
||||
} IP6_CONFIG_DATA_RECORD;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
//
|
||||
// heap data that contains the data for each data record.
|
||||
//
|
||||
// BOOLEAN IsAltIfIdSet;
|
||||
// EFI_IP6_CONFIG_POLICY Policy;
|
||||
// EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
|
||||
// UINT32 ManualaddressCount;
|
||||
// UINT32 GatewayCount;
|
||||
// UINT32 DnsServersCount;
|
||||
// EFI_IP6_CONFIG_INTERFACE_ID AltIfId;
|
||||
// EFI_IP6_CONFIG_MANUAL_ADDRESS ManualAddress[];
|
||||
// EFI_IPv6_ADDRESS Gateway[];
|
||||
// EFI_IPv6_ADDRESS DnsServers[];
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 IaId;
|
||||
UINT16 Checksum;
|
||||
UINT16 DataRecordCount;
|
||||
IP6_CONFIG_DATA_RECORD DataRecord[1];
|
||||
} IP6_CONFIG_VARIABLE;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
typedef struct {
|
||||
LIST_ENTRY Link;
|
||||
EFI_IP6_ADDRESS_INFO AddrInfo;
|
||||
} IP6_ADDRESS_INFO_ENTRY;
|
||||
|
||||
typedef struct {
|
||||
EFI_IP6_CONFIG_POLICY Policy; ///< manual or automatic
|
||||
EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadTransmitCount; ///< dad transmits count
|
||||
EFI_IP6_CONFIG_INTERFACE_ID InterfaceId; ///< alternative interface id
|
||||
LIST_ENTRY ManualAddress; ///< IP addresses
|
||||
UINT32 ManualAddressCount; ///< IP addresses count
|
||||
LIST_ENTRY GatewayAddress; ///< Gateway address
|
||||
UINT32 GatewayAddressCount; ///< Gateway address count
|
||||
LIST_ENTRY DnsAddress; ///< DNS server address
|
||||
UINT32 DnsAddressCount; ///< DNS server address count
|
||||
} IP6_CONFIG_NVDATA;
|
||||
|
||||
typedef struct _IP6_FORM_CALLBACK_INFO {
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE ChildHandle;
|
||||
EFI_HII_CONFIG_ACCESS_PROTOCOL HiiConfigAccess;
|
||||
EFI_DEVICE_PATH_PROTOCOL *HiiVendorDevicePath;
|
||||
EFI_HII_HANDLE RegisteredHandle;
|
||||
} IP6_FORM_CALLBACK_INFO;
|
||||
|
||||
struct _IP6_CONFIG_INSTANCE {
|
||||
UINT32 Signature;
|
||||
BOOLEAN Configured;
|
||||
LIST_ENTRY Link;
|
||||
UINT16 IfIndex;
|
||||
|
||||
EFI_IP6_CONFIG_INTERFACE_INFO InterfaceInfo;
|
||||
EFI_IP6_CONFIG_INTERFACE_ID AltIfId;
|
||||
EFI_IP6_CONFIG_POLICY Policy;
|
||||
EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
|
||||
|
||||
IP6_CONFIG_DATA_ITEM DataItem[Ip6ConfigDataTypeMaximum];
|
||||
NET_MAP DadFailedMap;
|
||||
NET_MAP DadPassedMap;
|
||||
|
||||
EFI_IP6_CONFIG_PROTOCOL Ip6Config;
|
||||
|
||||
EFI_EVENT Dhcp6SbNotifyEvent;
|
||||
VOID *Registration;
|
||||
EFI_HANDLE Dhcp6Handle;
|
||||
EFI_DHCP6_PROTOCOL *Dhcp6;
|
||||
BOOLEAN OtherInfoOnly;
|
||||
UINT32 IaId;
|
||||
EFI_EVENT Dhcp6Event;
|
||||
UINT32 FailedIaAddressCount;
|
||||
EFI_IPv6_ADDRESS *DeclineAddress;
|
||||
UINT32 DeclineAddressCount;
|
||||
|
||||
IP6_FORM_CALLBACK_INFO CallbackInfo;
|
||||
IP6_CONFIG_NVDATA Ip6NvData;
|
||||
};
|
||||
|
||||
/**
|
||||
The event process routine when the DHCPv6 server is answered with a reply packet
|
||||
for an information request.
|
||||
|
||||
@param[in] This Points to the EFI_DHCP6_PROTOCOL.
|
||||
@param[in] Context The pointer to the IP6 configuration instance data.
|
||||
@param[in] Packet The DHCPv6 reply packet.
|
||||
|
||||
@retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
|
||||
@retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
|
||||
the DNS server address is not valid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip6ConfigOnDhcp6Reply (
|
||||
IN EFI_DHCP6_PROTOCOL *This,
|
||||
IN VOID *Context,
|
||||
IN EFI_DHCP6_PACKET *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
The work function to trigger the DHCPv6 process to perform a stateful autoconfiguration.
|
||||
|
||||
@param[in] Instance Pointer to the IP6 config instance data.
|
||||
@param[in] OtherInfoOnly If FALSE, get stateful address and other information
|
||||
via DHCPv6. Otherwise, only get the other information.
|
||||
|
||||
@retval EFI_SUCCESS The operation finished successfully.
|
||||
@retval EFI_UNSUPPORTED The DHCP6 driver is not available.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ConfigStartStatefulAutoConfig (
|
||||
IN IP6_CONFIG_INSTANCE *Instance,
|
||||
IN BOOLEAN OtherInfoOnly
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize an IP6_CONFIG_INSTANCE.
|
||||
|
||||
@param[out] Instance The buffer of IP6_CONFIG_INSTANCE to be initialized.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
|
||||
@retval EFI_SUCCESS The IP6_CONFIG_INSTANCE initialized successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ConfigInitInstance (
|
||||
OUT IP6_CONFIG_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Release an IP6_CONFIG_INSTANCE.
|
||||
|
||||
@param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6ConfigCleanInstance (
|
||||
IN OUT IP6_CONFIG_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Destory the Dhcp6 child in IP6_CONFIG_INSTANCE and release the resources.
|
||||
|
||||
@param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
|
||||
|
||||
@retval EFI_SUCCESS The child was successfully destroyed.
|
||||
@retval Others Failed to destory the child.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ConfigDestroyDhcp6 (
|
||||
IN OUT IP6_CONFIG_INSTANCE *Instance
|
||||
);
|
||||
|
||||
#endif
|
2116
NetworkPkg/Ip6Dxe/Ip6ConfigNv.c
Normal file
2116
NetworkPkg/Ip6Dxe/Ip6ConfigNv.c
Normal file
File diff suppressed because it is too large
Load Diff
73
NetworkPkg/Ip6Dxe/Ip6ConfigNv.h
Normal file
73
NetworkPkg/Ip6Dxe/Ip6ConfigNv.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/** @file
|
||||
The header file of Ip6ConfigNv.c.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _IP6_CONFIGNV_H_
|
||||
#define _IP6_CONFIGNV_H_
|
||||
|
||||
#include "Ip6NvData.h"
|
||||
#include "Ip6ConfigImpl.h"
|
||||
|
||||
extern UINT8 Ip6ConfigBin[];
|
||||
extern UINT8 Ip6DxeStrings[];
|
||||
|
||||
#define IP6_HII_VENDOR_DEVICE_PATH_GUID \
|
||||
{ \
|
||||
0x13288098, 0xb11f, 0x45b9, { 0xbc, 0x4f, 0x91, 0xb5, 0x4b, 0xa3, 0x39, 0xb9 } \
|
||||
}
|
||||
|
||||
#define IP6_ETHERNET L"Ethernet"
|
||||
#define IP6_EXPERIMENTAL_ETHERNET L"Experimental Ethernet"
|
||||
#define IP6_ADDRESS_DELIMITER L' '
|
||||
#define IP6_LINK_LOCAL_PREFIX L"FE80::"
|
||||
|
||||
typedef enum {
|
||||
Ip6InterfaceTypeEthernet = 1,
|
||||
Ip6InterfaceTypeExperimentalEthernet
|
||||
} IP6_INTERFACE_TYPE;
|
||||
|
||||
typedef enum {
|
||||
Ip6ConfigNvHostAddress,
|
||||
Ip6ConfigNvGatewayAddress,
|
||||
Ip6ConfigNvDnsAddress,
|
||||
Ip6ConfigNvRouteTable
|
||||
} IP6_CONFIG_NV_ADDRESS_TYPE;
|
||||
|
||||
/**
|
||||
Install HII Config Access protocol for network device and allocate resources.
|
||||
|
||||
@param[in, out] Instance The IP6_CONFIG_INSTANCE to create a form.
|
||||
|
||||
@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
|
||||
Ip6ConfigFormInit (
|
||||
IN OUT IP6_CONFIG_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Uninstall HII Config Access protocol for network device and free resource.
|
||||
|
||||
@param[in, out] Instance The IP6_CONFIG_INSTANCE to unload a form.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6ConfigFormUnload (
|
||||
IN OUT IP6_CONFIG_INSTANCE *Instance
|
||||
);
|
||||
|
||||
#endif
|
930
NetworkPkg/Ip6Dxe/Ip6Driver.c
Normal file
930
NetworkPkg/Ip6Dxe/Ip6Driver.c
Normal file
@@ -0,0 +1,930 @@
|
||||
/** @file
|
||||
The driver binding and service binding protocol for IP6 driver.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip6Impl.h"
|
||||
|
||||
EFI_DRIVER_BINDING_PROTOCOL gIp6DriverBinding = {
|
||||
Ip6DriverBindingSupported,
|
||||
Ip6DriverBindingStart,
|
||||
Ip6DriverBindingStop,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/**
|
||||
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 IP6 driver which installs 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
|
||||
Ip6DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
return EfiLibInstallDriverBindingComponentName2 (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gIp6DriverBinding,
|
||||
ImageHandle,
|
||||
&gIp6ComponentName,
|
||||
&gIp6ComponentName2
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle.
|
||||
|
||||
@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
|
||||
Ip6DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
//
|
||||
// Test for the MNP service binding Protocol
|
||||
//
|
||||
return gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Clean up an IP6 service binding instance. It releases all
|
||||
the resource allocated by the instance. The instance may be
|
||||
partly initialized, or partly destroyed. If a resource is
|
||||
destroyed, it is marked as that in case the destory failed and
|
||||
being called again later.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance to clean up.
|
||||
|
||||
@retval EFI_SUCCESS The resource used by the instance are cleaned up.
|
||||
@retval Others Failed to clean up some of the resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6CleanService (
|
||||
IN IP6_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_IPv6_ADDRESS AllNodes;
|
||||
IP6_NEIGHBOR_ENTRY *NeighborCache;
|
||||
|
||||
Ip6ConfigCleanInstance (&IpSb->Ip6ConfigInstance);
|
||||
|
||||
//
|
||||
// Leave link-scope all-nodes multicast address (FF02::1)
|
||||
//
|
||||
Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
|
||||
|
||||
Status = Ip6LeaveGroup (IpSb, &AllNodes);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (IpSb->DefaultInterface != NULL) {
|
||||
Ip6CleanInterface (IpSb->DefaultInterface, NULL);
|
||||
IpSb->DefaultInterface = NULL;
|
||||
}
|
||||
|
||||
Ip6CleanDefaultRouterList (IpSb);
|
||||
|
||||
Ip6CleanPrefixListTable (IpSb, &IpSb->OnlinkPrefix);
|
||||
Ip6CleanPrefixListTable (IpSb, &IpSb->AutonomousPrefix);
|
||||
|
||||
if (IpSb->RouteTable != NULL) {
|
||||
Ip6CleanRouteTable (IpSb->RouteTable);
|
||||
IpSb->RouteTable = NULL;
|
||||
}
|
||||
|
||||
if (IpSb->InterfaceId != NULL) {
|
||||
FreePool (IpSb->InterfaceId);
|
||||
}
|
||||
|
||||
IpSb->InterfaceId = NULL;
|
||||
|
||||
Ip6CleanAssembleTable (&IpSb->Assemble);
|
||||
|
||||
if (IpSb->MnpChildHandle != NULL) {
|
||||
if (IpSb->Mnp != NULL) {
|
||||
IpSb->Mnp->Cancel (IpSb->Mnp, NULL);
|
||||
IpSb->Mnp->Configure (IpSb->Mnp, NULL);
|
||||
gBS->CloseProtocol (
|
||||
IpSb->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
IpSb->Image,
|
||||
IpSb->Controller
|
||||
);
|
||||
|
||||
IpSb->Mnp = NULL;
|
||||
}
|
||||
|
||||
NetLibDestroyServiceChild (
|
||||
IpSb->Controller,
|
||||
IpSb->Image,
|
||||
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
||||
IpSb->MnpChildHandle
|
||||
);
|
||||
|
||||
IpSb->MnpChildHandle = NULL;
|
||||
}
|
||||
|
||||
if (IpSb->RecvRequest.MnpToken.Event != NULL) {
|
||||
gBS->CloseEvent (IpSb->RecvRequest.MnpToken.Event);
|
||||
}
|
||||
|
||||
if (IpSb->Timer != NULL) {
|
||||
gBS->SetTimer (IpSb->Timer, TimerCancel, 0);
|
||||
gBS->CloseEvent (IpSb->Timer);
|
||||
|
||||
IpSb->Timer = NULL;
|
||||
}
|
||||
|
||||
if (IpSb->FasterTimer != NULL) {
|
||||
gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0);
|
||||
gBS->CloseEvent (IpSb->FasterTimer);
|
||||
|
||||
IpSb->FasterTimer = NULL;
|
||||
}
|
||||
//
|
||||
// Free the Neighbor Discovery resources
|
||||
//
|
||||
while (!IsListEmpty (&IpSb->NeighborTable)) {
|
||||
NeighborCache = NET_LIST_HEAD (&IpSb->NeighborTable, IP6_NEIGHBOR_ENTRY, Link);
|
||||
Ip6FreeNeighborEntry (IpSb, NeighborCache, FALSE, TRUE, EFI_SUCCESS, NULL, NULL);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Create a new IP6 driver service binding protocol.
|
||||
|
||||
@param[in] Controller The controller that has MNP service binding
|
||||
installed.
|
||||
@param[in] ImageHandle The IP6 driver's image handle.
|
||||
@param[out] Service The variable to receive the newly created IP6
|
||||
service.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
|
||||
@retval EFI_SUCCESS A new IP6 service binding private is created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6CreateService (
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
OUT IP6_SERVICE **Service
|
||||
)
|
||||
{
|
||||
IP6_SERVICE *IpSb;
|
||||
EFI_STATUS Status;
|
||||
EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
|
||||
EFI_MANAGED_NETWORK_CONFIG_DATA *Config;
|
||||
IP6_CONFIG_DATA_ITEM *DataItem;
|
||||
|
||||
ASSERT (Service != NULL);
|
||||
|
||||
*Service = NULL;
|
||||
|
||||
//
|
||||
// allocate a service private data then initialize all the filed to
|
||||
// empty resources, so if any thing goes wrong when allocating
|
||||
// resources, Ip6CleanService can be called to clean it up.
|
||||
//
|
||||
IpSb = AllocateZeroPool (sizeof (IP6_SERVICE));
|
||||
|
||||
if (IpSb == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
IpSb->Signature = IP6_SERVICE_SIGNATURE;
|
||||
IpSb->ServiceBinding.CreateChild = Ip6ServiceBindingCreateChild;
|
||||
IpSb->ServiceBinding.DestroyChild = Ip6ServiceBindingDestroyChild;
|
||||
IpSb->State = IP6_SERVICE_UNSTARTED;
|
||||
IpSb->InDestroy = FALSE;
|
||||
|
||||
IpSb->NumChildren = 0;
|
||||
InitializeListHead (&IpSb->Children);
|
||||
|
||||
InitializeListHead (&IpSb->Interfaces);
|
||||
IpSb->DefaultInterface = NULL;
|
||||
IpSb->RouteTable = NULL;
|
||||
|
||||
IpSb->RecvRequest.Signature = IP6_LINK_RX_SIGNATURE;
|
||||
IpSb->RecvRequest.CallBack = NULL;
|
||||
IpSb->RecvRequest.Context = NULL;
|
||||
MnpToken = &IpSb->RecvRequest.MnpToken;
|
||||
MnpToken->Event = NULL;
|
||||
MnpToken->Status = EFI_NOT_READY;
|
||||
MnpToken->Packet.RxData = NULL;
|
||||
|
||||
Ip6CreateAssembleTable (&IpSb->Assemble);
|
||||
|
||||
IpSb->MldCtrl.Mldv1QuerySeen = 0;
|
||||
InitializeListHead (&IpSb->MldCtrl.Groups);
|
||||
|
||||
ZeroMem (&IpSb->LinkLocalAddr, sizeof (EFI_IPv6_ADDRESS));
|
||||
IpSb->LinkLocalOk = FALSE;
|
||||
IpSb->LinkLocalDadFail = FALSE;
|
||||
IpSb->Dhcp6NeedStart = FALSE;
|
||||
IpSb->Dhcp6NeedInfoRequest = FALSE;
|
||||
|
||||
IpSb->CurHopLimit = IP6_HOP_LIMIT;
|
||||
IpSb->LinkMTU = IP6_MIN_LINK_MTU;
|
||||
IpSb->BaseReachableTime = IP6_REACHABLE_TIME;
|
||||
Ip6UpdateReachableTime (IpSb);
|
||||
//
|
||||
// RFC4861 RETRANS_TIMER: 1,000 milliseconds
|
||||
//
|
||||
IpSb->RetransTimer = IP6_RETRANS_TIMER;
|
||||
|
||||
IpSb->RoundRobin = 0;
|
||||
|
||||
InitializeListHead (&IpSb->NeighborTable);
|
||||
InitializeListHead (&IpSb->DefaultRouterList);
|
||||
InitializeListHead (&IpSb->OnlinkPrefix);
|
||||
InitializeListHead (&IpSb->AutonomousPrefix);
|
||||
|
||||
IpSb->InterfaceIdLen = IP6_IF_ID_LEN;
|
||||
IpSb->InterfaceId = NULL;
|
||||
|
||||
IpSb->RouterAdvertiseReceived = FALSE;
|
||||
IpSb->SolicitTimer = IP6_MAX_RTR_SOLICITATIONS;
|
||||
IpSb->Ticks = 0;
|
||||
|
||||
IpSb->Image = ImageHandle;
|
||||
IpSb->Controller = Controller;
|
||||
|
||||
IpSb->MnpChildHandle = NULL;
|
||||
IpSb->Mnp = NULL;
|
||||
|
||||
Config = &IpSb->MnpConfigData;
|
||||
Config->ReceivedQueueTimeoutValue = 0;
|
||||
Config->TransmitQueueTimeoutValue = 0;
|
||||
Config->ProtocolTypeFilter = IP6_ETHER_PROTO;
|
||||
Config->EnableUnicastReceive = TRUE;
|
||||
Config->EnableMulticastReceive = TRUE;
|
||||
Config->EnableBroadcastReceive = TRUE;
|
||||
Config->EnablePromiscuousReceive = FALSE;
|
||||
Config->FlushQueuesOnReset = TRUE;
|
||||
Config->EnableReceiveTimestamps = FALSE;
|
||||
Config->DisableBackgroundPolling = FALSE;
|
||||
|
||||
ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));
|
||||
|
||||
IpSb->Timer = NULL;
|
||||
IpSb->FasterTimer = NULL;
|
||||
|
||||
ZeroMem (&IpSb->Ip6ConfigInstance, sizeof (IP6_CONFIG_INSTANCE));
|
||||
|
||||
IpSb->MacString = NULL;
|
||||
|
||||
//
|
||||
// Create various resources. First create the route table, timer
|
||||
// event, MNP token event and MNP child.
|
||||
//
|
||||
|
||||
IpSb->RouteTable = Ip6CreateRouteTable ();
|
||||
if (IpSb->RouteTable == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
||||
TPL_CALLBACK,
|
||||
Ip6TimerTicking,
|
||||
IpSb,
|
||||
&IpSb->Timer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
||||
TPL_CALLBACK,
|
||||
Ip6NdFasterTimerTicking,
|
||||
IpSb,
|
||||
&IpSb->FasterTimer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = NetLibCreateServiceChild (
|
||||
Controller,
|
||||
ImageHandle,
|
||||
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
||||
&IpSb->MnpChildHandle
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
IpSb->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
(VOID **) (&IpSb->Mnp),
|
||||
ImageHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip6ServiceConfigMnp (IpSb, TRUE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &IpSb->SnpMode);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
IpSb->MaxPacketSize = IP6_MIN_LINK_MTU - sizeof (EFI_IP6_HEADER);
|
||||
if (NetLibGetVlanId (IpSb->Controller) != 0) {
|
||||
//
|
||||
// This is a VLAN device, reduce MTU by VLAN tag length
|
||||
//
|
||||
IpSb->MaxPacketSize -= NET_VLAN_TAG_LEN;
|
||||
}
|
||||
IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;
|
||||
|
||||
//
|
||||
// Currently only ETHERNET is supported in IPv6 stack, since
|
||||
// link local address requires an IEEE 802 48-bit MACs for
|
||||
// EUI-64 format interface identifier mapping.
|
||||
//
|
||||
if (IpSb->SnpMode.IfType != NET_IFTYPE_ETHERNET) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip6InitMld (IpSb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// The timer expires every 100 (IP6_TIMER_INTERVAL_IN_MS) milliseconds.
|
||||
//
|
||||
Status = gBS->SetTimer (IpSb->FasterTimer, TimerPeriodic, TICKS_PER_MS * IP6_TIMER_INTERVAL_IN_MS);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// The timer expires every 1000 (IP6_ONE_SECOND_IN_MS) milliseconds.
|
||||
//
|
||||
Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_MS * IP6_ONE_SECOND_IN_MS);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
Ip6OnFrameReceived,
|
||||
&IpSb->RecvRequest,
|
||||
&MnpToken->Event
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip6ReceiveFrame (Ip6AcceptFrame, IpSb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip6ConfigInitInstance (&IpSb->Ip6ConfigInstance);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
IpSb->DefaultInterface = Ip6CreateInterface (IpSb, TRUE);
|
||||
if (IpSb->DefaultInterface == NULL) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// If there is any manual address, set it.
|
||||
//
|
||||
DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeManualAddress];
|
||||
if (DataItem->Data.Ptr != NULL) {
|
||||
DataItem->SetData (
|
||||
&IpSb->Ip6ConfigInstance,
|
||||
DataItem->DataSize,
|
||||
DataItem->Data.Ptr
|
||||
);
|
||||
}
|
||||
|
||||
InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);
|
||||
|
||||
*Service = IpSb;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
Ip6CleanService (IpSb);
|
||||
FreePool (IpSb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to bind driver to.
|
||||
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCES 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
|
||||
Ip6DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
IP6_SERVICE *IpSb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Test for the Ip6 service binding protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp6ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (Status == EFI_SUCCESS) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
Status = Ip6CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
ASSERT (IpSb != NULL);
|
||||
|
||||
//
|
||||
// Install the Ip6ServiceBinding Protocol onto ControlerHandle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&ControllerHandle,
|
||||
&gEfiIp6ServiceBindingProtocolGuid,
|
||||
&IpSb->ServiceBinding,
|
||||
&gEfiIp6ConfigProtocolGuid,
|
||||
&IpSb->Ip6ConfigInstance.Ip6Config,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
Ip6CleanService (IpSb);
|
||||
FreePool (IpSb);
|
||||
} else {
|
||||
//
|
||||
// Initialize the IP6 ID
|
||||
//
|
||||
mIp6Id = NET_RANDOM (NetRandomInitSeed ());
|
||||
|
||||
Ip6SetVariableData (IpSb);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle.
|
||||
|
||||
@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 An array of child handles to be freed. May be NULL
|
||||
if NumberOfChildren is 0.
|
||||
|
||||
@retval EFI_SUCCESS The device was stopped.
|
||||
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip6DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
IP6_SERVICE *IpSb;
|
||||
IP6_PROTOCOL *IpInstance;
|
||||
EFI_HANDLE NicHandle;
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN IsDhcp6;
|
||||
EFI_TPL OldTpl;
|
||||
INTN State;
|
||||
|
||||
IsDhcp6 = FALSE;
|
||||
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);
|
||||
|
||||
if (NicHandle != NULL) {
|
||||
//
|
||||
// DriverBindingStop is triggered by the uninstallation of the EFI DHCPv6
|
||||
// Protocol used by Ip6Config.
|
||||
//
|
||||
IsDhcp6 = TRUE;
|
||||
} else {
|
||||
|
||||
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
|
||||
|
||||
if (NicHandle == NULL) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
NicHandle,
|
||||
&gEfiIp6ServiceBindingProtocolGuid,
|
||||
(VOID **) &ServiceBinding,
|
||||
This->DriverBindingHandle,
|
||||
NicHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
IpSb = IP6_SERVICE_FROM_PROTOCOL (ServiceBinding);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
if (IpSb->InDestroy) {
|
||||
Status = EFI_SUCCESS;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (IsDhcp6) {
|
||||
|
||||
Status = Ip6ConfigDestroyDhcp6 (&IpSb->Ip6ConfigInstance);
|
||||
gBS->CloseEvent (IpSb->Ip6ConfigInstance.Dhcp6Event);
|
||||
IpSb->Ip6ConfigInstance.Dhcp6Event = NULL;
|
||||
} else if (NumberOfChildren == 0) {
|
||||
|
||||
IpSb->InDestroy = TRUE;
|
||||
State = IpSb->State;
|
||||
IpSb->State = IP6_SERVICE_DESTROY;
|
||||
|
||||
//
|
||||
// Clear the variable data.
|
||||
//
|
||||
Ip6ClearVariableData (IpSb);
|
||||
|
||||
Status = Ip6CleanService (IpSb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
IpSb->State = State;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
NicHandle,
|
||||
&gEfiIp6ServiceBindingProtocolGuid,
|
||||
ServiceBinding,
|
||||
&gEfiIp6ConfigProtocolGuid,
|
||||
&IpSb->Ip6ConfigInstance.Ip6Config,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
FreePool (IpSb);
|
||||
} else {
|
||||
//
|
||||
// NumberOfChildren is not zero, destroy all IP6 children instances.
|
||||
//
|
||||
while (!IsListEmpty (&IpSb->Children)) {
|
||||
IpInstance = NET_LIST_HEAD (&IpSb->Children, IP6_PROTOCOL, Link);
|
||||
ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);
|
||||
}
|
||||
|
||||
if (IpSb->NumChildren != 0) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates a child handle with a set of I/O services.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ChildHandle Pointer to the handle of the child to create. If
|
||||
it is NULL, then a new handle is created. If it
|
||||
is not NULL, then the I/O services are added to
|
||||
the existing child handle.
|
||||
|
||||
@retval EFI_SUCCES The child handle was created with the I/O services.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
|
||||
the child.
|
||||
@retval other The child handle was not created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip6ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
)
|
||||
{
|
||||
IP6_SERVICE *IpSb;
|
||||
IP6_PROTOCOL *IpInstance;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
VOID *Mnp;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
IpSb = IP6_SERVICE_FROM_PROTOCOL (This);
|
||||
|
||||
if (IpSb->LinkLocalDadFail) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
IpInstance = AllocatePool (sizeof (IP6_PROTOCOL));
|
||||
|
||||
if (IpInstance == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Ip6InitProtocol (IpSb, IpInstance);
|
||||
|
||||
//
|
||||
// Install Ip6 onto ChildHandle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiIp6ProtocolGuid,
|
||||
&IpInstance->Ip6Proto,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
IpInstance->Handle = *ChildHandle;
|
||||
|
||||
//
|
||||
// Open the Managed Network protocol BY_CHILD.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
IpSb->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
(VOID **) &Mnp,
|
||||
gIp6DriverBinding.DriverBindingHandle,
|
||||
IpInstance->Handle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiIp6ProtocolGuid,
|
||||
&IpInstance->Ip6Proto,
|
||||
NULL
|
||||
);
|
||||
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert it into the service binding instance.
|
||||
//
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
InsertTailList (&IpSb->Children, &IpInstance->Link);
|
||||
IpSb->NumChildren++;
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
Ip6CleanProtocol (IpInstance);
|
||||
|
||||
FreePool (IpInstance);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Destroys a child handle with a set of I/O services.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ChildHandle Handle of the child to destroy.
|
||||
|
||||
@retval EFI_SUCCES The I/O services were removed from the child
|
||||
handle.
|
||||
@retval EFI_UNSUPPORTED The child handle does not support the I/O services
|
||||
that are being removed.
|
||||
@retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
|
||||
@retval EFI_ACCESS_DENIED The child handle could not be destroyed because
|
||||
its I/O services are being used.
|
||||
@retval other The child handle was not destroyed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip6ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IP6_SERVICE *IpSb;
|
||||
IP6_PROTOCOL *IpInstance;
|
||||
EFI_IP6_PROTOCOL *Ip6;
|
||||
EFI_TPL OldTpl;
|
||||
INTN State;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the private context data structures
|
||||
//
|
||||
IpSb = IP6_SERVICE_FROM_PROTOCOL (This);
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiIp6ProtocolGuid,
|
||||
(VOID **) &Ip6,
|
||||
gIp6DriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
IpInstance = IP6_INSTANCE_FROM_PROTOCOL (Ip6);
|
||||
|
||||
if (IpInstance->Service != IpSb) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
//
|
||||
// A child can be destroyed more than once. For example,
|
||||
// Ip6DriverBindingStop will destory all of its children.
|
||||
// when UDP driver is being stopped, it will destory all
|
||||
// the IP child it opens.
|
||||
//
|
||||
if (IpInstance->State == IP6_STATE_DESTROY) {
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
State = IpInstance->State;
|
||||
IpInstance->State = IP6_STATE_DESTROY;
|
||||
|
||||
//
|
||||
// Close the Managed Network protocol.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
IpSb->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
gIp6DriverBinding.DriverBindingHandle,
|
||||
ChildHandle
|
||||
);
|
||||
|
||||
//
|
||||
// Uninstall the IP6 protocol first. Many thing happens during
|
||||
// this:
|
||||
// 1. The consumer of the IP6 protocol will be stopped if it
|
||||
// opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
|
||||
// stopped, IP driver's stop function will be called, and uninstall
|
||||
// EFI_IP6_PROTOCOL will trigger the UDP's stop function. This
|
||||
// makes it possible to create the network stack bottom up, and
|
||||
// stop it top down.
|
||||
// 2. the upper layer will recycle the received packet. The recycle
|
||||
// event's TPL is higher than this function. The recycle events
|
||||
// will be called back before preceeding. If any packets not recycled,
|
||||
// that means there is a resource leak.
|
||||
//
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
ChildHandle,
|
||||
&gEfiIp6ProtocolGuid,
|
||||
&IpInstance->Ip6Proto
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip6CleanProtocol (IpInstance);
|
||||
|
||||
Ip6SetVariableData (IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->InstallMultipleProtocolInterfaces (
|
||||
&ChildHandle,
|
||||
&gEfiIp6ProtocolGuid,
|
||||
Ip6,
|
||||
NULL
|
||||
);
|
||||
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
RemoveEntryList (&IpInstance->Link);
|
||||
ASSERT (IpSb->NumChildren > 0);
|
||||
IpSb->NumChildren--;
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
FreePool (IpInstance);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
IpInstance->State = State;
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
185
NetworkPkg/Ip6Dxe/Ip6Driver.h
Normal file
185
NetworkPkg/Ip6Dxe/Ip6Driver.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/** @file
|
||||
The driver binding and service binding protocol for IP6 driver.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP6_DRIVER_H__
|
||||
#define __EFI_IP6_DRIVER_H__
|
||||
|
||||
extern EFI_DRIVER_BINDING_PROTOCOL gIp6DriverBinding;
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gIp6ComponentName;
|
||||
extern EFI_COMPONENT_NAME2_PROTOCOL gIp6ComponentName2;
|
||||
|
||||
/**
|
||||
Clean up an IP6 service binding instance. It releases all
|
||||
the resource allocated by the instance. The instance may be
|
||||
partly initialized, or partly destroyed. If a resource is
|
||||
destroyed, it is marked as that in case the destory failed and
|
||||
being called again later.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance to clean up.
|
||||
|
||||
@retval EFI_SUCCESS The resource used by the instance are cleaned up.
|
||||
@retval Others Failed to clean up some of the resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6CleanService (
|
||||
IN IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
//
|
||||
// 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 IP6 driver which installs 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
|
||||
Ip6DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
//
|
||||
// Function prototypes for the Drivr Binding Protocol
|
||||
//
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle.
|
||||
|
||||
@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
|
||||
Ip6DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to bind driver to.
|
||||
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCES 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
|
||||
Ip6DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle.
|
||||
|
||||
@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 An array of child handles to be freed. May be NULL
|
||||
if NumberOfChildren is 0.
|
||||
|
||||
@retval EFI_SUCCESS The device was stopped.
|
||||
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip6DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
|
||||
);
|
||||
|
||||
//
|
||||
// Function ptototypes for the ServiceBinding Prococol
|
||||
//
|
||||
|
||||
/**
|
||||
Creates a child handle with a set of I/O services.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ChildHandle Pointer to the handle of the child to create. If
|
||||
it is NULL, then a new handle is created. If it
|
||||
is not NULL, then the I/O services are added to
|
||||
the existing child handle.
|
||||
|
||||
@retval EFI_SUCCES The child handle was created with the I/O services.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
|
||||
the child.
|
||||
@retval other The child handle was not created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip6ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
);
|
||||
|
||||
/**
|
||||
Destroys a child handle with a set of I/O services.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ChildHandle Handle of the child to destroy.
|
||||
|
||||
@retval EFI_SUCCES The I/O services were removed from the child
|
||||
handle.
|
||||
@retval EFI_UNSUPPORTED The child handle does not support the I/O services
|
||||
that are being removed.
|
||||
@retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
|
||||
@retval EFI_ACCESS_DENIED The child handle could not be destroyed because
|
||||
its I/O services are being used.
|
||||
@retval other The child handle was not destroyed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip6ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
);
|
||||
|
||||
#endif
|
100
NetworkPkg/Ip6Dxe/Ip6Dxe.inf
Normal file
100
NetworkPkg/Ip6Dxe/Ip6Dxe.inf
Normal file
@@ -0,0 +1,100 @@
|
||||
## @file
|
||||
# Component description file for Ip6 module.
|
||||
#
|
||||
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = Ip6Dxe
|
||||
FILE_GUID = 5BEDB5CC-D830-4eb2-8742-2D4CC9B54F2C
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = Ip6DriverEntryPoint
|
||||
UNLOAD_IMAGE = NetLibDefaultUnload
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
# DRIVER_BINDING = gIp6DriverBinding
|
||||
# COMPONENT_NAME = gIp6ComponentName
|
||||
# COMPONENT_NAME2 = gIp6ComponentName2
|
||||
#
|
||||
|
||||
[Sources]
|
||||
Ip6Output.h
|
||||
Ip6Option.h
|
||||
Ip6Input.h
|
||||
Ip6Nd.h
|
||||
Ip6Mld.h
|
||||
Ip6Impl.c
|
||||
Ip6Driver.c
|
||||
ComponentName.c
|
||||
Ip6Nd.c
|
||||
Ip6Input.c
|
||||
Ip6ConfigImpl.c
|
||||
Ip6ConfigImpl.h
|
||||
Ip6Impl.h
|
||||
Ip6Option.c
|
||||
Ip6If.h
|
||||
Ip6Icmp.h
|
||||
Ip6Mld.c
|
||||
Ip6Common.c
|
||||
Ip6Route.c
|
||||
Ip6If.c
|
||||
Ip6Driver.h
|
||||
Ip6Output.c
|
||||
Ip6Icmp.c
|
||||
Ip6Common.h
|
||||
Ip6Route.h
|
||||
Ip6DxeStrings.uni
|
||||
Ip6NvData.h
|
||||
Ip6ConfigNv.c
|
||||
Ip6ConfigNv.h
|
||||
Ip6Config.vfr
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DevicePathLib
|
||||
HiiLib
|
||||
UefiHiiServicesLib
|
||||
PrintLib
|
||||
MemoryAllocationLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
UefiLib
|
||||
DebugLib
|
||||
NetLib
|
||||
DpcLib
|
||||
|
||||
[Protocols]
|
||||
gEfiManagedNetworkServiceBindingProtocolGuid
|
||||
gEfiManagedNetworkProtocolGuid
|
||||
gEfiIp6ServiceBindingProtocolGuid
|
||||
gEfiIp6ProtocolGuid
|
||||
gEfiIp6ConfigProtocolGuid
|
||||
gEfiDhcp6ServiceBindingProtocolGuid
|
||||
gEfiDhcp6ProtocolGuid
|
||||
gEfiIpSecProtocolGuid
|
||||
gEfiHiiConfigAccessProtocolGuid
|
||||
|
||||
[Guids]
|
||||
gEfiIfrTianoGuid ## CONSUMES ## GUID
|
BIN
NetworkPkg/Ip6Dxe/Ip6DxeStrings.uni
Normal file
BIN
NetworkPkg/Ip6Dxe/Ip6DxeStrings.uni
Normal file
Binary file not shown.
684
NetworkPkg/Ip6Dxe/Ip6Icmp.c
Normal file
684
NetworkPkg/Ip6Dxe/Ip6Icmp.c
Normal file
@@ -0,0 +1,684 @@
|
||||
/** @file
|
||||
The ICMPv6 handle routines to process the ICMPv6 control messages.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip6Impl.h"
|
||||
|
||||
EFI_IP6_ICMP_TYPE mIp6SupportedIcmp[23] = {
|
||||
|
||||
{
|
||||
ICMP_V6_DEST_UNREACHABLE,
|
||||
ICMP_V6_NO_ROUTE_TO_DEST
|
||||
},
|
||||
{
|
||||
ICMP_V6_DEST_UNREACHABLE,
|
||||
ICMP_V6_COMM_PROHIBITED
|
||||
},
|
||||
{
|
||||
ICMP_V6_DEST_UNREACHABLE,
|
||||
ICMP_V6_BEYOND_SCOPE
|
||||
},
|
||||
{
|
||||
ICMP_V6_DEST_UNREACHABLE,
|
||||
ICMP_V6_ADDR_UNREACHABLE
|
||||
},
|
||||
{
|
||||
ICMP_V6_DEST_UNREACHABLE,
|
||||
ICMP_V6_PORT_UNREACHABLE
|
||||
},
|
||||
{
|
||||
ICMP_V6_DEST_UNREACHABLE,
|
||||
ICMP_V6_SOURCE_ADDR_FAILED
|
||||
},
|
||||
{
|
||||
ICMP_V6_DEST_UNREACHABLE,
|
||||
ICMP_V6_ROUTE_REJECTED
|
||||
},
|
||||
|
||||
{
|
||||
ICMP_V6_PACKET_TOO_BIG,
|
||||
ICMP_V6_DEFAULT_CODE
|
||||
},
|
||||
|
||||
{
|
||||
ICMP_V6_TIME_EXCEEDED,
|
||||
ICMP_V6_TIMEOUT_HOP_LIMIT
|
||||
},
|
||||
{
|
||||
ICMP_V6_TIME_EXCEEDED,
|
||||
ICMP_V6_TIMEOUT_REASSEMBLE
|
||||
},
|
||||
|
||||
{
|
||||
ICMP_V6_PARAMETER_PROBLEM,
|
||||
ICMP_V6_ERRONEOUS_HEADER
|
||||
},
|
||||
{
|
||||
ICMP_V6_PARAMETER_PROBLEM,
|
||||
ICMP_V6_UNRECOGNIZE_NEXT_HDR
|
||||
},
|
||||
{
|
||||
ICMP_V6_PARAMETER_PROBLEM,
|
||||
ICMP_V6_UNRECOGNIZE_OPTION
|
||||
},
|
||||
|
||||
{
|
||||
ICMP_V6_ECHO_REQUEST,
|
||||
ICMP_V6_DEFAULT_CODE
|
||||
},
|
||||
{
|
||||
ICMP_V6_ECHO_REPLY,
|
||||
ICMP_V6_DEFAULT_CODE
|
||||
},
|
||||
|
||||
{
|
||||
ICMP_V6_LISTENER_QUERY,
|
||||
ICMP_V6_DEFAULT_CODE
|
||||
},
|
||||
{
|
||||
ICMP_V6_LISTENER_REPORT,
|
||||
ICMP_V6_DEFAULT_CODE
|
||||
},
|
||||
{
|
||||
ICMP_V6_LISTENER_REPORT_2,
|
||||
ICMP_V6_DEFAULT_CODE
|
||||
},
|
||||
{
|
||||
ICMP_V6_LISTENER_DONE,
|
||||
ICMP_V6_DEFAULT_CODE
|
||||
},
|
||||
|
||||
{
|
||||
ICMP_V6_ROUTER_SOLICIT,
|
||||
ICMP_V6_DEFAULT_CODE
|
||||
},
|
||||
{
|
||||
ICMP_V6_ROUTER_ADVERTISE,
|
||||
ICMP_V6_DEFAULT_CODE
|
||||
},
|
||||
{
|
||||
ICMP_V6_NEIGHBOR_SOLICIT,
|
||||
ICMP_V6_DEFAULT_CODE
|
||||
},
|
||||
{
|
||||
ICMP_V6_NEIGHBOR_ADVERTISE,
|
||||
ICMP_V6_DEFAULT_CODE
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
Reply an ICMPv6 echo request.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the ICMPv6 informational message.
|
||||
@param[in] Packet The content of the ICMPv6 message with the IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
|
||||
@retval EFI_SUCCESS Successfully answered the ICMPv6 Echo request.
|
||||
@retval Others Failed to answer the ICMPv6 Echo request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6IcmpReplyEcho (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP6_ICMP_INFORMATION_HEAD *Icmp;
|
||||
NET_BUF *Data;
|
||||
EFI_STATUS Status;
|
||||
EFI_IP6_HEADER ReplyHead;
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
//
|
||||
// make a copy the packet, it is really a bad idea to
|
||||
// send the MNP's buffer back to MNP.
|
||||
//
|
||||
Data = NetbufDuplicate (Packet, NULL, IP6_MAX_HEADLEN);
|
||||
if (Data == NULL) {
|
||||
goto 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 = (IP6_ICMP_INFORMATION_HEAD *) NetbufGetByte (Data, 0, NULL);
|
||||
if (Icmp == NULL) {
|
||||
NetbufFree (Data);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Icmp->Head.Type = ICMP_V6_ECHO_REPLY;
|
||||
Icmp->Head.Checksum = 0;
|
||||
|
||||
//
|
||||
// Generate the IPv6 basic header
|
||||
// If the Echo Reply is a response to a Echo Request sent to one of the node's unicast address,
|
||||
// the Source address of the Echo Reply must be the same address.
|
||||
//
|
||||
ZeroMem (&ReplyHead, sizeof (EFI_IP6_HEADER));
|
||||
|
||||
ReplyHead.PayloadLength = HTONS ((UINT16) (Packet->TotalSize));
|
||||
ReplyHead.NextHeader = IP6_ICMP;
|
||||
ReplyHead.HopLimit = IpSb->CurHopLimit;
|
||||
IP6_COPY_ADDRESS (&ReplyHead.DestinationAddress, &Head->SourceAddress);
|
||||
|
||||
if (Ip6IsOneOfSetAddress (IpSb, &Head->DestinationAddress, NULL, NULL)) {
|
||||
IP6_COPY_ADDRESS (&ReplyHead.SourceAddress, &Head->DestinationAddress);
|
||||
}
|
||||
|
||||
//
|
||||
// If source is unspecified, Ip6Output will select a source for us
|
||||
//
|
||||
Status = Ip6Output (
|
||||
IpSb,
|
||||
NULL,
|
||||
NULL,
|
||||
Data,
|
||||
&ReplyHead,
|
||||
NULL,
|
||||
0,
|
||||
Ip6SysPacketSent,
|
||||
NULL
|
||||
);
|
||||
|
||||
Exit:
|
||||
NetbufFree (Packet);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Process Packet Too Big message sent by a router in response to a packet that
|
||||
it cannot forward because the packet is larger than the MTU of outgoing link.
|
||||
Since this driver already uses IPv6 minimum link MTU as the maximum packet size,
|
||||
if Packet Too Big message is still received, do not reduce the packet size, but
|
||||
rather include a Fragment header in the subsequent packets.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the ICMPv6 error packet.
|
||||
@param[in] Packet The content of the ICMPv6 error with the IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_SUCCESS The ICMPv6 error processed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to finish the operation due to lack of
|
||||
resource.
|
||||
@retval EFI_NOT_FOUND The packet too big message is not sent to us.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ProcessPacketTooBig (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP6_ICMP_ERROR_HEAD Icmp;
|
||||
UINT32 Mtu;
|
||||
IP6_ROUTE_ENTRY *RouteEntry;
|
||||
EFI_IPv6_ADDRESS *DestAddress;
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
Mtu = NTOHL (Icmp.Fourth);
|
||||
DestAddress = &Icmp.IpHead.DestinationAddress;
|
||||
|
||||
if (Mtu < IP6_MIN_LINK_MTU) {
|
||||
//
|
||||
// Normally the multicast address is considered to be on-link and not recorded
|
||||
// in route table. Here it is added into the table since the MTU information
|
||||
// need be recorded.
|
||||
//
|
||||
if (IP6_IS_MULTICAST (DestAddress)) {
|
||||
RouteEntry = Ip6CreateRouteEntry (DestAddress, 128, NULL);
|
||||
if (RouteEntry == NULL) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
RouteEntry->Flag = IP6_DIRECT_ROUTE | IP6_PACKET_TOO_BIG;
|
||||
InsertHeadList (&IpSb->RouteTable->RouteArea[128], &RouteEntry->Link);
|
||||
IpSb->RouteTable->TotalNum++;
|
||||
} else {
|
||||
RouteEntry = Ip6FindRouteEntry (IpSb->RouteTable, DestAddress, NULL);
|
||||
if (RouteEntry == NULL) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
RouteEntry->Flag = RouteEntry->Flag | IP6_PACKET_TOO_BIG;
|
||||
|
||||
Ip6FreeRouteEntry (RouteEntry);
|
||||
}
|
||||
}
|
||||
|
||||
NetbufFree (Packet);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Process the ICMPv6 error packet, and deliver the packet to upper layer.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the ICMPv6 error packet.
|
||||
@param[in] Packet The content of the ICMPv6 error with the IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_SUCCESS The ICMPv6 error processed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid.
|
||||
@retval Others Failed to process the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ProcessIcmpError (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP6_ICMP_ERROR_HEAD Icmp;
|
||||
|
||||
//
|
||||
// Check the validity of the packet
|
||||
//
|
||||
if (Packet->TotalSize < sizeof (Icmp)) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
if (Icmp.Head.Type == ICMP_V6_PACKET_TOO_BIG) {
|
||||
return Ip6ProcessPacketTooBig (IpSb, Head, Packet);
|
||||
}
|
||||
|
||||
//
|
||||
// Notify the upper-layer process that an ICMPv6 eror message is received.
|
||||
//
|
||||
IP6_GET_CLIP_INFO (Packet)->Status = EFI_ICMP_ERROR;
|
||||
return Ip6Demultiplex (IpSb, Head, Packet);
|
||||
|
||||
DROP:
|
||||
NetbufFree (Packet);
|
||||
Packet = NULL;
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/**
|
||||
Process the ICMPv6 informational messages. If it is an ICMPv6 echo
|
||||
request, answer it. If it is a MLD message, trigger MLD routines to
|
||||
process it. If it is a ND message, trigger ND routines to process it.
|
||||
Otherwise, deliver it to upper layer.
|
||||
|
||||
@param[in] IpSb The IP service that receivd the packet.
|
||||
@param[in] Head The IP head of the ICMPv6 informational packet.
|
||||
@param[in] Packet The content of the ICMPv6 informational packet
|
||||
with IP head removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid.
|
||||
@retval EFI_SUCCESS The ICMPv6 informational message processed.
|
||||
@retval Others Failed to process ICMPv6 informational message.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ProcessIcmpInformation (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP6_ICMP_INFORMATION_HEAD Icmp;
|
||||
EFI_STATUS Status;
|
||||
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
NET_CHECK_SIGNATURE (Packet, NET_BUF_SIGNATURE);
|
||||
ASSERT (Head != NULL);
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
|
||||
switch (Icmp.Head.Type) {
|
||||
case ICMP_V6_ECHO_REQUEST:
|
||||
//
|
||||
// If ICMPv6 echo, reply it
|
||||
//
|
||||
if (Icmp.Head.Code == 0) {
|
||||
Status = Ip6IcmpReplyEcho (IpSb, Head, Packet);
|
||||
}
|
||||
break;
|
||||
case ICMP_V6_LISTENER_QUERY:
|
||||
Status = Ip6ProcessMldQuery (IpSb, Head, Packet);
|
||||
break;
|
||||
case ICMP_V6_LISTENER_REPORT:
|
||||
case ICMP_V6_LISTENER_REPORT_2:
|
||||
Status = Ip6ProcessMldReport (IpSb, Head, Packet);
|
||||
break;
|
||||
case ICMP_V6_NEIGHBOR_SOLICIT:
|
||||
Status = Ip6ProcessNeighborSolicit (IpSb, Head, Packet);
|
||||
break;
|
||||
case ICMP_V6_NEIGHBOR_ADVERTISE:
|
||||
Status = Ip6ProcessNeighborAdvertise (IpSb, Head, Packet);
|
||||
break;
|
||||
case ICMP_V6_ROUTER_ADVERTISE:
|
||||
Status = Ip6ProcessRouterAdvertise (IpSb, Head, Packet);
|
||||
break;
|
||||
case ICMP_V6_REDIRECT:
|
||||
Status = Ip6ProcessRedirect (IpSb, Head, Packet);
|
||||
break;
|
||||
case ICMP_V6_ECHO_REPLY:
|
||||
Status = Ip6Demultiplex (IpSb, Head, Packet);
|
||||
break;
|
||||
default:
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Handle the ICMPv6 packet. First validate the message format,
|
||||
then, according to the message types, process it as an informational packet or
|
||||
an error packet.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the ICMPv6 packet.
|
||||
@param[in] Packet The content of the ICMPv6 packet with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformated.
|
||||
@retval EFI_SUCCESS The ICMPv6 message successfully processed.
|
||||
@retval Others Failed to handle the ICMPv6 packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6IcmpHandle (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP6_ICMP_HEAD Icmp;
|
||||
UINT16 PseudoCheckSum;
|
||||
UINT16 CheckSum;
|
||||
|
||||
//
|
||||
// Check the validity of the incoming packet.
|
||||
//
|
||||
if (Packet->TotalSize < sizeof (Icmp)) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
|
||||
//
|
||||
// Make sure checksum is valid.
|
||||
//
|
||||
PseudoCheckSum = NetIp6PseudoHeadChecksum (
|
||||
&Head->SourceAddress,
|
||||
&Head->DestinationAddress,
|
||||
IP6_ICMP,
|
||||
Packet->TotalSize
|
||||
);
|
||||
CheckSum = (UINT16) ~NetAddChecksum (PseudoCheckSum, NetbufChecksum (Packet));
|
||||
if (CheckSum != 0) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
//
|
||||
// According to the packet type, call corresponding process
|
||||
//
|
||||
if (Icmp.Type <= ICMP_V6_ERROR_MAX) {
|
||||
return Ip6ProcessIcmpError (IpSb, Head, Packet);
|
||||
} else {
|
||||
return Ip6ProcessIcmpInformation (IpSb, Head, Packet);
|
||||
}
|
||||
|
||||
DROP:
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieve the Prefix address according to the PrefixLength by clear the useless
|
||||
bits.
|
||||
|
||||
@param[in] PrefixLength The prefix length of the prefix.
|
||||
@param[in, out] Prefix On input, points to the original prefix address
|
||||
with dirty bits; on output, points to the updated
|
||||
address with useless bit clear.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6GetPrefix (
|
||||
IN UINT8 PrefixLength,
|
||||
IN OUT EFI_IPv6_ADDRESS *Prefix
|
||||
)
|
||||
{
|
||||
UINT8 Byte;
|
||||
UINT8 Bit;
|
||||
UINT8 Mask;
|
||||
UINT8 Value;
|
||||
|
||||
ASSERT ((Prefix != NULL) && (PrefixLength < IP6_PREFIX_NUM));
|
||||
|
||||
if (PrefixLength == 0) {
|
||||
ZeroMem (Prefix, sizeof (EFI_IPv6_ADDRESS));
|
||||
return ;
|
||||
}
|
||||
|
||||
if (PrefixLength == IP6_PREFIX_NUM - 1) {
|
||||
return ;
|
||||
}
|
||||
|
||||
Byte = (UINT8) (PrefixLength / 8);
|
||||
Bit = (UINT8) (PrefixLength % 8);
|
||||
Value = Prefix->Addr[Byte];
|
||||
|
||||
if ((Byte > 0) && (Byte < 16)) {
|
||||
ZeroMem (Prefix->Addr + Byte, 16 - Byte);
|
||||
}
|
||||
|
||||
if (Bit > 0) {
|
||||
Mask = (UINT8) (0xFF << (8 - Bit));
|
||||
Prefix->Addr[Byte] = (UINT8) (Value & Mask);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether the DestinationAddress is an anycast address.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] DestinationAddress Points to the Destination Address of the packet.
|
||||
|
||||
@retval TRUE The DestinationAddress is anycast address.
|
||||
@retval FALSE The DestinationAddress is not anycast address.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsAnycast (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *DestinationAddress
|
||||
)
|
||||
{
|
||||
IP6_PREFIX_LIST_ENTRY *PrefixEntry;
|
||||
EFI_IPv6_ADDRESS Prefix;
|
||||
BOOLEAN Flag;
|
||||
|
||||
ZeroMem (&Prefix, sizeof (EFI_IPv6_ADDRESS));
|
||||
|
||||
Flag = FALSE;
|
||||
|
||||
//
|
||||
// If the address is known as on-link or autonomous prefix, record it as
|
||||
// anycast address.
|
||||
//
|
||||
do {
|
||||
PrefixEntry = Ip6FindPrefixListEntry (IpSb, Flag, 255, DestinationAddress);
|
||||
if (PrefixEntry != NULL) {
|
||||
IP6_COPY_ADDRESS (&Prefix, &PrefixEntry->Prefix);
|
||||
Ip6GetPrefix (PrefixEntry->PrefixLength, &Prefix);
|
||||
if (EFI_IP6_EQUAL (&Prefix, DestinationAddress)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Flag = (BOOLEAN) !Flag;
|
||||
} while (Flag);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Generate ICMPv6 error message and send it out to DestinationAddress. Currently
|
||||
Destination Unreachable message, Time Exceeded message and Parameter Problem
|
||||
message are supported.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Packet The packet which invoking ICMPv6 error.
|
||||
@param[in] SourceAddress If not NULL, points to the SourceAddress.
|
||||
Otherwise, the IP layer will select a source address
|
||||
according to the DestinationAddress.
|
||||
@param[in] DestinationAddress Points to the Destination Address of the ICMPv6
|
||||
error message.
|
||||
@param[in] Type The type of the ICMPv6 message.
|
||||
@param[in] Code The additional level of the ICMPv6 message.
|
||||
@param[in] Pointer If not NULL, identifies the octet offset within
|
||||
the invoking packet where the error was detected.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformated.
|
||||
@retval EFI_OUT_OF_RESOURCES There is no sufficient resource to complete the
|
||||
operation.
|
||||
@retval EFI_SUCCESS The ICMPv6 message was successfully sent out.
|
||||
@retval Others Failed to generate the ICMPv6 packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SendIcmpError (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
|
||||
IN EFI_IPv6_ADDRESS *DestinationAddress,
|
||||
IN UINT8 Type,
|
||||
IN UINT8 Code,
|
||||
IN UINT32 *Pointer OPTIONAL
|
||||
)
|
||||
{
|
||||
UINT32 PacketLen;
|
||||
NET_BUF *ErrorMsg;
|
||||
UINT16 PayloadLen;
|
||||
EFI_IP6_HEADER Head;
|
||||
IP6_ICMP_INFORMATION_HEAD *IcmpHead;
|
||||
UINT8 *ErrorBody;
|
||||
|
||||
if (DestinationAddress == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// An ICMPv6 error message must not be originated as a result of receiving
|
||||
// a packet whose source address does not uniquely identify a single node --
|
||||
// e.g., the IPv6 Unspecified Address, an IPv6 multicast address, or an address
|
||||
// known by the ICMP message originator to be an IPv6 anycast address.
|
||||
//
|
||||
if (NetIp6IsUnspecifiedAddr (DestinationAddress) ||
|
||||
IP6_IS_MULTICAST (DestinationAddress) ||
|
||||
Ip6IsAnycast (IpSb, DestinationAddress)
|
||||
) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
switch (Type) {
|
||||
case ICMP_V6_DEST_UNREACHABLE:
|
||||
case ICMP_V6_TIME_EXCEEDED:
|
||||
break;
|
||||
|
||||
case ICMP_V6_PARAMETER_PROBLEM:
|
||||
if (Pointer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
PacketLen = sizeof (IP6_ICMP_ERROR_HEAD) + Packet->TotalSize;
|
||||
|
||||
if (PacketLen > IpSb->MaxPacketSize) {
|
||||
PacketLen = IpSb->MaxPacketSize;
|
||||
}
|
||||
|
||||
ErrorMsg = NetbufAlloc (PacketLen);
|
||||
if (ErrorMsg == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
PayloadLen = (UINT16) (PacketLen - sizeof (EFI_IP6_HEADER));
|
||||
|
||||
//
|
||||
// Create the basic IPv6 header.
|
||||
//
|
||||
ZeroMem (&Head, sizeof (EFI_IP6_HEADER));
|
||||
|
||||
Head.PayloadLength = HTONS (PayloadLen);
|
||||
Head.NextHeader = IP6_ICMP;
|
||||
Head.HopLimit = IpSb->CurHopLimit;
|
||||
|
||||
if (SourceAddress != NULL) {
|
||||
IP6_COPY_ADDRESS (&Head.SourceAddress, SourceAddress);
|
||||
} else {
|
||||
ZeroMem (&Head.SourceAddress, sizeof (EFI_IPv6_ADDRESS));
|
||||
}
|
||||
|
||||
IP6_COPY_ADDRESS (&Head.DestinationAddress, DestinationAddress);
|
||||
|
||||
NetbufReserve (ErrorMsg, sizeof (EFI_IP6_HEADER));
|
||||
|
||||
//
|
||||
// Fill in the ICMP error message head
|
||||
//
|
||||
IcmpHead = (IP6_ICMP_INFORMATION_HEAD *) NetbufAllocSpace (ErrorMsg, sizeof (IP6_ICMP_INFORMATION_HEAD), FALSE);
|
||||
if (IcmpHead == NULL) {
|
||||
NetbufFree (ErrorMsg);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
ZeroMem (IcmpHead, sizeof (IP6_ICMP_INFORMATION_HEAD));
|
||||
IcmpHead->Head.Type = Type;
|
||||
IcmpHead->Head.Code = Code;
|
||||
|
||||
if (Pointer != NULL) {
|
||||
IcmpHead->Fourth = HTONL (*Pointer);
|
||||
}
|
||||
|
||||
//
|
||||
// Fill in the ICMP error message body
|
||||
//
|
||||
PayloadLen -= sizeof (IP6_ICMP_INFORMATION_HEAD);
|
||||
ErrorBody = NetbufAllocSpace (ErrorMsg, PayloadLen, FALSE);
|
||||
if (ErrorBody != NULL) {
|
||||
ZeroMem (ErrorBody, PayloadLen);
|
||||
NetbufCopy (Packet, 0, PayloadLen, ErrorBody);
|
||||
}
|
||||
|
||||
//
|
||||
// Transmit the packet
|
||||
//
|
||||
return Ip6Output (IpSb, NULL, NULL, ErrorMsg, &Head, NULL, 0, Ip6SysPacketSent, NULL);
|
||||
}
|
||||
|
108
NetworkPkg/Ip6Dxe/Ip6Icmp.h
Normal file
108
NetworkPkg/Ip6Dxe/Ip6Icmp.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/** @file
|
||||
Header file for ICMPv6 protocol.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP6_ICMP_H__
|
||||
#define __EFI_IP6_ICMP_H__
|
||||
|
||||
#define ICMP_V6_DEFAULT_CODE 0
|
||||
|
||||
#define ICMP_V6_ERROR_MAX 127
|
||||
|
||||
//
|
||||
// ICMPv6 message classes, each class of ICMPv6 message shares
|
||||
// a common message format. INVALID_MESSAGE is only a flag.
|
||||
//
|
||||
#define ICMP_V6_INVALID_MESSAGE 0
|
||||
#define ICMP_V6_ERROR_MESSAGE 1
|
||||
#define ICMP_V6_INFORMATION_MESSAGE 2
|
||||
|
||||
|
||||
extern EFI_IP6_ICMP_TYPE mIp6SupportedIcmp[];
|
||||
|
||||
/**
|
||||
Handle the ICMPv6 packet. First validate the message format,
|
||||
then, according to the message types, process it as an informational packet or
|
||||
an error packet.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the ICMPv6 packet.
|
||||
@param[in] Packet The content of the ICMPv6 packet with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformated.
|
||||
@retval EFI_SUCCESS The ICMPv6 message successfully processed.
|
||||
@retval Others Failed to handle the ICMPv6 packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6IcmpHandle (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether the DestinationAddress is an anycast address.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] DestinationAddress Points to the Destination Address of the packet.
|
||||
|
||||
@retval TRUE The DestinationAddress is anycast address.
|
||||
@retval FALSE The DestinationAddress is not anycast address.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsAnycast (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *DestinationAddress
|
||||
);
|
||||
|
||||
/**
|
||||
Generate ICMPv6 error message and send it out to DestinationAddress. Currently
|
||||
Destination Unreachable message, Time Exceeded message and Parameter Problem
|
||||
message are supported.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Packet The packet which invoking ICMPv6 error.
|
||||
@param[in] SourceAddress If not NULL, points to the SourceAddress.
|
||||
Otherwise, the IP layer will select a source address
|
||||
according to the DestinationAddress.
|
||||
@param[in] DestinationAddress Points to the Destination Address of the ICMPv6
|
||||
error message.
|
||||
@param[in] Type The type of the ICMPv6 message.
|
||||
@param[in] Code The additional level of the ICMPv6 message.
|
||||
@param[in] Pointer If not NULL, identifies the octet offset within
|
||||
the invoking packet where the error was detected.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformated.
|
||||
@retval EFI_OUT_OF_RESOURCES There is no sufficient resource to complete the
|
||||
operation.
|
||||
@retval EFI_SUCCESS The ICMPv6 message was successfully sent out.
|
||||
@retval Others Failed to generate the ICMPv6 packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SendIcmpError (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
|
||||
IN EFI_IPv6_ADDRESS *DestinationAddress,
|
||||
IN UINT8 Type,
|
||||
IN UINT8 Code,
|
||||
IN UINT32 *Pointer OPTIONAL
|
||||
);
|
||||
|
||||
#endif
|
||||
|
802
NetworkPkg/Ip6Dxe/Ip6If.c
Normal file
802
NetworkPkg/Ip6Dxe/Ip6If.c
Normal file
@@ -0,0 +1,802 @@
|
||||
/** @file
|
||||
Implement IP6 pesudo interface.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip6Impl.h"
|
||||
|
||||
/**
|
||||
Request Ip6OnFrameSentDpc as a DPC at TPL_CALLBACK.
|
||||
|
||||
@param[in] Event The transmit token's event.
|
||||
@param[in] Context The Context which is pointed to the token.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip6OnFrameSent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Fileter function to cancel all the frame related to an IP instance.
|
||||
|
||||
@param[in] Frame The transmit request to test whether to cancel.
|
||||
@param[in] Context The context which is the Ip instance that issued
|
||||
the transmit.
|
||||
|
||||
@retval TRUE The frame belongs to this instance and is to be
|
||||
removed.
|
||||
@retval FALSE The frame doesn't belong to this instance.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6CancelInstanceFrame (
|
||||
IN IP6_LINK_TX_TOKEN *Frame,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
if (Frame->IpInstance == (IP6_PROTOCOL *) Context) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the interface's address. This will trigger the DAD process for the
|
||||
address to set. To set an already set address, the lifetimes wil be
|
||||
updated to the new value passed in.
|
||||
|
||||
@param[in] Interface The interface to set the address.
|
||||
@param[in] Ip6Addr The interface's to be assigned IPv6 address.
|
||||
@param[in] IsAnycast If TRUE, the unicast IPv6 address is anycast.
|
||||
Otherwise, it is not anycast.
|
||||
@param[in] PrefixLength The prefix length of the Ip6Addr.
|
||||
@param[in] ValidLifetime The valid lifetime for this address.
|
||||
@param[in] PreferredLifetime The preferred lifetime for this address.
|
||||
@param[in] DadCallback The caller's callback to trigger when DAD finishes.
|
||||
This is an optional parameter that may be NULL.
|
||||
@param[in] Context The context that will be passed to DadCallback.
|
||||
This is an optional parameter that may be NULL.
|
||||
|
||||
@retval EFI_SUCCESS The interface is scheduled to be configured with
|
||||
the specified address.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to set the interface's address due to
|
||||
lack of resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SetAddress (
|
||||
IN IP6_INTERFACE *Interface,
|
||||
IN EFI_IPv6_ADDRESS *Ip6Addr,
|
||||
IN BOOLEAN IsAnycast,
|
||||
IN UINT8 PrefixLength,
|
||||
IN UINT32 ValidLifetime,
|
||||
IN UINT32 PreferredLifetime,
|
||||
IN IP6_DAD_CALLBACK DadCallback OPTIONAL,
|
||||
IN VOID *Context OPTIONAL
|
||||
)
|
||||
{
|
||||
IP6_SERVICE *IpSb;
|
||||
IP6_ADDRESS_INFO *AddressInfo;
|
||||
LIST_ENTRY *Entry;
|
||||
IP6_PREFIX_LIST_ENTRY *PrefixEntry;
|
||||
UINT64 Delay;
|
||||
IP6_DELAY_JOIN_LIST *DelayNode;
|
||||
|
||||
NET_CHECK_SIGNATURE (Interface, IP6_INTERFACE_SIGNATURE);
|
||||
|
||||
IpSb = Interface->Service;
|
||||
|
||||
if (Ip6IsOneOfSetAddress (IpSb, Ip6Addr, NULL, &AddressInfo)) {
|
||||
ASSERT (AddressInfo != NULL);
|
||||
//
|
||||
// Update the lifetime.
|
||||
//
|
||||
AddressInfo->ValidLifetime = ValidLifetime;
|
||||
AddressInfo->PreferredLifetime = PreferredLifetime;
|
||||
|
||||
if (DadCallback != NULL) {
|
||||
DadCallback (TRUE, Ip6Addr, Context);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
AddressInfo = (IP6_ADDRESS_INFO *) AllocatePool (sizeof (IP6_ADDRESS_INFO));
|
||||
if (AddressInfo == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
AddressInfo->Signature = IP6_ADDR_INFO_SIGNATURE;
|
||||
IP6_COPY_ADDRESS (&AddressInfo->Address, Ip6Addr);
|
||||
AddressInfo->IsAnycast = IsAnycast;
|
||||
AddressInfo->PrefixLength = PrefixLength;
|
||||
AddressInfo->ValidLifetime = ValidLifetime;
|
||||
AddressInfo->PreferredLifetime = PreferredLifetime;
|
||||
|
||||
if (AddressInfo->PrefixLength == 0) {
|
||||
//
|
||||
// Find an appropriate prefix from on-link prefixes and update the prefixlength.
|
||||
// Longest prefix match is used here.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->OnlinkPrefix) {
|
||||
PrefixEntry = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
|
||||
|
||||
if (NetIp6IsNetEqual (&PrefixEntry->Prefix, &AddressInfo->Address, PrefixEntry->PrefixLength)) {
|
||||
AddressInfo->PrefixLength = PrefixEntry->PrefixLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AddressInfo->PrefixLength == 0) {
|
||||
//
|
||||
// If the prefix length is still zero, try the autonomous prefixes.
|
||||
// Longest prefix match is used here.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->AutonomousPrefix) {
|
||||
PrefixEntry = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
|
||||
|
||||
if (NetIp6IsNetEqual (&PrefixEntry->Prefix, &AddressInfo->Address, PrefixEntry->PrefixLength)) {
|
||||
AddressInfo->PrefixLength = PrefixEntry->PrefixLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AddressInfo->PrefixLength == 0) {
|
||||
//
|
||||
// BUGBUG: Stil fail, use 64 as the default prefix length.
|
||||
//
|
||||
AddressInfo->PrefixLength = IP6_LINK_LOCAL_PREFIX_LENGTH;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Node should delay joining the solicited-node mulitcast address by a random delay
|
||||
// between 0 and MAX_RTR_SOLICITATION_DELAY (1 second).
|
||||
// Thus queue the address to be processed in Duplicate Address Detection module
|
||||
// after the delay time (in milliseconds).
|
||||
//
|
||||
Delay = (UINT64) NET_RANDOM (NetRandomInitSeed ());
|
||||
Delay = MultU64x32 (Delay, IP6_ONE_SECOND_IN_MS);
|
||||
Delay = RShiftU64 (Delay, 32);
|
||||
|
||||
DelayNode = (IP6_DELAY_JOIN_LIST *) AllocatePool (sizeof (IP6_DELAY_JOIN_LIST));
|
||||
if (DelayNode == NULL) {
|
||||
FreePool (AddressInfo);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
DelayNode->DelayTime = (UINT32) (DivU64x32 (Delay, IP6_TIMER_INTERVAL_IN_MS));
|
||||
DelayNode->Interface = Interface;
|
||||
DelayNode->AddressInfo = AddressInfo;
|
||||
DelayNode->DadCallback = DadCallback;
|
||||
DelayNode->Context = Context;
|
||||
|
||||
InsertTailList (&Interface->DelayJoinList, &DelayNode->Link);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Create an IP6_INTERFACE.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
@param[in] LinkLocal If TRUE, the instance is created for link-local address.
|
||||
Otherwise, it is not for a link-local address.
|
||||
|
||||
@return Point to the created IP6_INTERFACE, otherwise NULL.
|
||||
|
||||
**/
|
||||
IP6_INTERFACE *
|
||||
Ip6CreateInterface (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN BOOLEAN LinkLocal
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IP6_INTERFACE *Interface;
|
||||
EFI_IPv6_ADDRESS *Ip6Addr;
|
||||
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
|
||||
Interface = AllocatePool (sizeof (IP6_INTERFACE));
|
||||
if (Interface == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Interface->Signature = IP6_INTERFACE_SIGNATURE;
|
||||
Interface->RefCnt = 1;
|
||||
|
||||
InitializeListHead (&Interface->AddressList);
|
||||
Interface->AddressCount = 0;
|
||||
Interface->Configured = FALSE;
|
||||
|
||||
Interface->Service = IpSb;
|
||||
Interface->Controller = IpSb->Controller;
|
||||
Interface->Image = IpSb->Image;
|
||||
|
||||
InitializeListHead (&Interface->ArpQues);
|
||||
InitializeListHead (&Interface->SentFrames);
|
||||
|
||||
Interface->DupAddrDetect = IpSb->Ip6ConfigInstance.DadXmits.DupAddrDetectTransmits;
|
||||
InitializeListHead (&Interface->DupAddrDetectList);
|
||||
|
||||
InitializeListHead (&Interface->DelayJoinList);
|
||||
|
||||
InitializeListHead (&Interface->IpInstances);
|
||||
Interface->PromiscRecv = FALSE;
|
||||
|
||||
if (!LinkLocal) {
|
||||
return Interface;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the link local addr
|
||||
//
|
||||
Ip6Addr = Ip6CreateLinkLocalAddr (IpSb);
|
||||
if (Ip6Addr == NULL) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Perform DAD - Duplicate Address Detection.
|
||||
//
|
||||
Status = Ip6SetAddress (
|
||||
Interface,
|
||||
Ip6Addr,
|
||||
FALSE,
|
||||
IP6_LINK_LOCAL_PREFIX_LENGTH,
|
||||
(UINT32) IP6_INFINIT_LIFETIME,
|
||||
(UINT32) IP6_INFINIT_LIFETIME,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
FreePool (Ip6Addr);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
return Interface;
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
FreePool (Interface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Free the interface used by IpInstance. All the IP instance with
|
||||
the same Ip/prefix pair share the same interface. It is reference
|
||||
counted. All the frames that haven't been sent will be cancelled.
|
||||
Because the IpInstance is optional, the caller must remove
|
||||
IpInstance from the interface's instance list.
|
||||
|
||||
@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.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CleanInterface (
|
||||
IN IP6_INTERFACE *Interface,
|
||||
IN IP6_PROTOCOL *IpInstance OPTIONAL
|
||||
)
|
||||
{
|
||||
IP6_DAD_ENTRY *Duplicate;
|
||||
IP6_DELAY_JOIN_LIST *Delay;
|
||||
|
||||
NET_CHECK_SIGNATURE (Interface, IP6_INTERFACE_SIGNATURE);
|
||||
ASSERT (Interface->RefCnt > 0);
|
||||
|
||||
//
|
||||
// Remove all the pending transmit token related to this IP instance.
|
||||
//
|
||||
Ip6CancelFrames (Interface, EFI_ABORTED, Ip6CancelInstanceFrame, IpInstance);
|
||||
|
||||
if (--Interface->RefCnt > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Destory the interface if this is the last IP instance.
|
||||
// Remove all the system transmitted packets
|
||||
// from this interface, cancel the receive request if exists.
|
||||
//
|
||||
Ip6CancelFrames (Interface, EFI_ABORTED, Ip6CancelInstanceFrame, NULL);
|
||||
|
||||
ASSERT (IsListEmpty (&Interface->IpInstances));
|
||||
ASSERT (IsListEmpty (&Interface->ArpQues));
|
||||
ASSERT (IsListEmpty (&Interface->SentFrames));
|
||||
|
||||
while (!IsListEmpty (&Interface->DupAddrDetectList)) {
|
||||
Duplicate = NET_LIST_HEAD (&Interface->DupAddrDetectList, IP6_DAD_ENTRY, Link);
|
||||
NetListRemoveHead (&Interface->DupAddrDetectList);
|
||||
FreePool (Duplicate);
|
||||
}
|
||||
|
||||
while (!IsListEmpty (&Interface->DelayJoinList)) {
|
||||
Delay = NET_LIST_HEAD (&Interface->DelayJoinList, IP6_DELAY_JOIN_LIST, Link);
|
||||
NetListRemoveHead (&Interface->DelayJoinList);
|
||||
FreePool (Delay);
|
||||
}
|
||||
|
||||
Ip6RemoveAddr (Interface->Service, &Interface->AddressList, &Interface->AddressCount, NULL, 0);
|
||||
|
||||
RemoveEntryList (&Interface->Link);
|
||||
FreePool (Interface);
|
||||
}
|
||||
|
||||
/**
|
||||
Create and wrap a transmit request into a newly allocated IP6_LINK_TX_TOKEN.
|
||||
|
||||
@param[in] Interface The interface to send out from.
|
||||
@param[in] IpInstance The IpInstance that transmit the packet. NULL if
|
||||
the packet is sent by the IP6 driver itself.
|
||||
@param[in] Packet The packet to transmit
|
||||
@param[in] CallBack Call back function to execute if transmission
|
||||
finished.
|
||||
@param[in] Context Opaque parameter to the callback.
|
||||
|
||||
@return The wrapped token if succeed or NULL.
|
||||
|
||||
**/
|
||||
IP6_LINK_TX_TOKEN *
|
||||
Ip6CreateLinkTxToken (
|
||||
IN IP6_INTERFACE *Interface,
|
||||
IN IP6_PROTOCOL *IpInstance OPTIONAL,
|
||||
IN NET_BUF *Packet,
|
||||
IN IP6_FRAME_CALLBACK CallBack,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
|
||||
EFI_MANAGED_NETWORK_TRANSMIT_DATA *MnpTxData;
|
||||
IP6_LINK_TX_TOKEN *Token;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Count;
|
||||
|
||||
Token = AllocatePool (sizeof (IP6_LINK_TX_TOKEN) + (Packet->BlockOpNum - 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA));
|
||||
|
||||
if (Token == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Token->Signature = IP6_LINK_TX_SIGNATURE;
|
||||
InitializeListHead (&Token->Link);
|
||||
|
||||
Token->IpInstance = IpInstance;
|
||||
Token->CallBack = CallBack;
|
||||
Token->Packet = Packet;
|
||||
Token->Context = Context;
|
||||
ZeroMem (&Token->DstMac, sizeof (EFI_MAC_ADDRESS));
|
||||
IP6_COPY_LINK_ADDRESS (&Token->SrcMac, &Interface->Service->SnpMode.CurrentAddress);
|
||||
|
||||
MnpToken = &(Token->MnpToken);
|
||||
MnpToken->Status = EFI_NOT_READY;
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
Ip6OnFrameSent,
|
||||
Token,
|
||||
&MnpToken->Event
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Token);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MnpTxData = &Token->MnpTxData;
|
||||
MnpToken->Packet.TxData = MnpTxData;
|
||||
|
||||
MnpTxData->DestinationAddress = &Token->DstMac;
|
||||
MnpTxData->SourceAddress = &Token->SrcMac;
|
||||
MnpTxData->ProtocolType = IP6_ETHER_PROTO;
|
||||
MnpTxData->DataLength = Packet->TotalSize;
|
||||
MnpTxData->HeaderLength = 0;
|
||||
|
||||
Count = Packet->BlockOpNum;
|
||||
|
||||
NetbufBuildExt (Packet, (NET_FRAGMENT *) MnpTxData->FragmentTable, &Count);
|
||||
MnpTxData->FragmentCount = (UINT16)Count;
|
||||
|
||||
return Token;
|
||||
}
|
||||
|
||||
/**
|
||||
Free the link layer transmit token. It will close the event,
|
||||
then free the memory used.
|
||||
|
||||
@param[in] Token Token to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6FreeLinkTxToken (
|
||||
IN IP6_LINK_TX_TOKEN *Token
|
||||
)
|
||||
{
|
||||
NET_CHECK_SIGNATURE (Token, IP6_LINK_TX_SIGNATURE);
|
||||
|
||||
gBS->CloseEvent (Token->MnpToken.Event);
|
||||
FreePool (Token);
|
||||
}
|
||||
|
||||
/**
|
||||
Callback function when the received packet is freed.
|
||||
Check Ip6OnFrameReceived for information.
|
||||
|
||||
@param[in] Context Points to EFI_MANAGED_NETWORK_RECEIVE_DATA.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip6RecycleFrame (
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData;
|
||||
|
||||
RxData = (EFI_MANAGED_NETWORK_RECEIVE_DATA *) Context;
|
||||
|
||||
gBS->SignalEvent (RxData->RecycleEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
Received a frame from MNP. Wrap it in net buffer then deliver
|
||||
it to IP's input function. The ownship of the packet also
|
||||
is transferred to IP. When Ip is finished with this packet, it
|
||||
will call NetbufFree to release the packet, NetbufFree will
|
||||
again call the Ip6RecycleFrame to signal MNP's event and free
|
||||
the token used.
|
||||
|
||||
@param[in] Context Context for the callback.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip6OnFrameReceivedDpc (
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
|
||||
EFI_MANAGED_NETWORK_RECEIVE_DATA *MnpRxData;
|
||||
IP6_LINK_RX_TOKEN *Token;
|
||||
NET_FRAGMENT Netfrag;
|
||||
NET_BUF *Packet;
|
||||
UINT32 Flag;
|
||||
IP6_SERVICE *IpSb;
|
||||
|
||||
Token = (IP6_LINK_RX_TOKEN *) Context;
|
||||
NET_CHECK_SIGNATURE (Token, IP6_LINK_RX_SIGNATURE);
|
||||
|
||||
//
|
||||
// First clear the interface's receive request in case the
|
||||
// caller wants to call Ip6ReceiveFrame in the callback.
|
||||
//
|
||||
IpSb = (IP6_SERVICE *) Token->Context;
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
|
||||
|
||||
MnpToken = &Token->MnpToken;
|
||||
MnpRxData = MnpToken->Packet.RxData;
|
||||
|
||||
if (EFI_ERROR (MnpToken->Status) || (MnpRxData == NULL)) {
|
||||
Token->CallBack (NULL, MnpToken->Status, 0, Token->Context);
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Wrap the frame in a net buffer then deliever it to IP input.
|
||||
// IP will reassemble the packet, and deliver it to upper layer
|
||||
//
|
||||
Netfrag.Len = MnpRxData->DataLength;
|
||||
Netfrag.Bulk = MnpRxData->PacketData;
|
||||
|
||||
Packet = NetbufFromExt (&Netfrag, 1, IP6_MAX_HEADLEN, 0, Ip6RecycleFrame, Token->MnpToken.Packet.RxData);
|
||||
|
||||
if (Packet == NULL) {
|
||||
gBS->SignalEvent (MnpRxData->RecycleEvent);
|
||||
|
||||
Token->CallBack (NULL, EFI_OUT_OF_RESOURCES, 0, Token->Context);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
Flag = (MnpRxData->BroadcastFlag ? IP6_LINK_BROADCAST : 0);
|
||||
Flag |= (MnpRxData->MulticastFlag ? IP6_LINK_MULTICAST : 0);
|
||||
Flag |= (MnpRxData->PromiscuousFlag ? IP6_LINK_PROMISC : 0);
|
||||
|
||||
Token->CallBack (Packet, EFI_SUCCESS, Flag, Token->Context);
|
||||
}
|
||||
|
||||
/**
|
||||
Request Ip6OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
|
||||
|
||||
@param Event The receive event delivered to MNP for receive.
|
||||
@param Context Context for the callback.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip6OnFrameReceived (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
//
|
||||
// Request Ip6OnFrameReceivedDpc as a DPC at TPL_CALLBACK
|
||||
//
|
||||
QueueDpc (TPL_CALLBACK, Ip6OnFrameReceivedDpc, Context);
|
||||
}
|
||||
|
||||
/**
|
||||
Request to receive the packet from the interface.
|
||||
|
||||
@param[in] CallBack Function to call when receive finished.
|
||||
@param[in] IpSb Points to IP6 service binding instance.
|
||||
|
||||
@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.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ReceiveFrame (
|
||||
IN IP6_FRAME_CALLBACK CallBack,
|
||||
IN IP6_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IP6_LINK_RX_TOKEN *Token;
|
||||
|
||||
if (IpSb->InDestroy) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
|
||||
Token = &IpSb->RecvRequest;
|
||||
Token->CallBack = CallBack;
|
||||
Token->Context = (VOID *) IpSb;
|
||||
|
||||
Status = IpSb->Mnp->Receive (IpSb->Mnp, &Token->MnpToken);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Callback funtion when frame transmission is finished. It will
|
||||
call the frame owner's callback function to tell it the result.
|
||||
|
||||
@param[in] Context Context which points to the token.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip6OnFrameSentDpc (
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
IP6_LINK_TX_TOKEN *Token;
|
||||
|
||||
Token = (IP6_LINK_TX_TOKEN *) Context;
|
||||
NET_CHECK_SIGNATURE (Token, IP6_LINK_TX_SIGNATURE);
|
||||
|
||||
RemoveEntryList (&Token->Link);
|
||||
|
||||
Token->CallBack (
|
||||
Token->Packet,
|
||||
Token->MnpToken.Status,
|
||||
0,
|
||||
Token->Context
|
||||
);
|
||||
|
||||
Ip6FreeLinkTxToken (Token);
|
||||
}
|
||||
|
||||
/**
|
||||
Request Ip6OnFrameSentDpc as a DPC at TPL_CALLBACK.
|
||||
|
||||
@param[in] Event The transmit token's event.
|
||||
@param[in] Context Context which points to the token.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip6OnFrameSent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
//
|
||||
// Request Ip6OnFrameSentDpc as a DPC at TPL_CALLBACK
|
||||
//
|
||||
QueueDpc (TPL_CALLBACK, Ip6OnFrameSentDpc, Context);
|
||||
}
|
||||
|
||||
/**
|
||||
Send a frame from the interface. If the next hop is a multicast address,
|
||||
it is transmitted immediately. If the next hop is a unicast,
|
||||
and the NextHop's MAC is not known, it will perform address resolution.
|
||||
If an error occurred, 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 IP6 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 callback.
|
||||
|
||||
@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 successfully transmitted.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SendFrame (
|
||||
IN IP6_INTERFACE *Interface,
|
||||
IN IP6_PROTOCOL *IpInstance OPTIONAL,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_IPv6_ADDRESS *NextHop,
|
||||
IN IP6_FRAME_CALLBACK CallBack,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
IP6_SERVICE *IpSb;
|
||||
IP6_LINK_TX_TOKEN *Token;
|
||||
EFI_STATUS Status;
|
||||
IP6_NEIGHBOR_ENTRY *NeighborCache;
|
||||
LIST_ENTRY *Entry;
|
||||
IP6_NEIGHBOR_ENTRY *ArpQue;
|
||||
|
||||
IpSb = Interface->Service;
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
|
||||
//
|
||||
// Only when link local address is performing DAD, the interface could be used in unconfigured.
|
||||
//
|
||||
if (IpSb->LinkLocalOk) {
|
||||
ASSERT (Interface->Configured);
|
||||
}
|
||||
|
||||
Token = Ip6CreateLinkTxToken (Interface, IpInstance, Packet, CallBack, Context);
|
||||
|
||||
if (Token == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (IP6_IS_MULTICAST (NextHop)) {
|
||||
Status = Ip6GetMulticastMac (IpSb->Mnp, NextHop, &Token->DstMac);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
goto SendNow;
|
||||
}
|
||||
|
||||
//
|
||||
// If send to itself, directly send out
|
||||
//
|
||||
if (EFI_IP6_EQUAL (&Packet->Ip.Ip6->DestinationAddress, &Packet->Ip.Ip6->SourceAddress)) {
|
||||
IP6_COPY_LINK_ADDRESS (&Token->DstMac, &IpSb->SnpMode.CurrentAddress);
|
||||
goto SendNow;
|
||||
}
|
||||
|
||||
//
|
||||
// If unicast, check the neighbor state.
|
||||
//
|
||||
|
||||
NeighborCache = Ip6FindNeighborEntry (IpSb, NextHop);
|
||||
ASSERT (NeighborCache != NULL);
|
||||
|
||||
if (NeighborCache->Interface == NULL) {
|
||||
NeighborCache->Interface = Interface;
|
||||
}
|
||||
|
||||
switch (NeighborCache->State) {
|
||||
case EfiNeighborStale:
|
||||
NeighborCache->State = EfiNeighborDelay;
|
||||
NeighborCache->Ticks = (UINT32) IP6_GET_TICKS (IP6_DELAY_FIRST_PROBE_TIME);
|
||||
//
|
||||
// Fall through
|
||||
//
|
||||
case EfiNeighborReachable:
|
||||
case EfiNeighborDelay:
|
||||
case EfiNeighborProbe:
|
||||
IP6_COPY_LINK_ADDRESS (&Token->DstMac, &NeighborCache->LinkAddress);
|
||||
goto SendNow;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Have to do asynchronous ARP resolution. First check whether there is
|
||||
// already a pending request.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &Interface->ArpQues) {
|
||||
ArpQue = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, ArpList);
|
||||
if (ArpQue == NeighborCache) {
|
||||
InsertTailList (&NeighborCache->Frames, &Token->Link);
|
||||
NeighborCache->ArpFree = TRUE;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// First frame requires ARP.
|
||||
//
|
||||
InsertTailList (&NeighborCache->Frames, &Token->Link);
|
||||
InsertTailList (&Interface->ArpQues, &NeighborCache->ArpList);
|
||||
|
||||
NeighborCache->ArpFree = TRUE;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
SendNow:
|
||||
//
|
||||
// Insert the tx token into the SentFrames list before calling Mnp->Transmit.
|
||||
// Remove it if the returned status is not EFI_SUCCESS.
|
||||
//
|
||||
InsertTailList (&Interface->SentFrames, &Token->Link);
|
||||
Status = IpSb->Mnp->Transmit (IpSb->Mnp, &Token->MnpToken);
|
||||
if (EFI_ERROR (Status)) {
|
||||
RemoveEntryList (&Token->Link);
|
||||
goto Error;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
Error:
|
||||
Ip6FreeLinkTxToken (Token);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
The heartbeat timer of IP6 service instance. It times out
|
||||
all of its IP6 children's received-but-not-delivered and
|
||||
transmitted-but-not-recycle packets.
|
||||
|
||||
@param[in] Event The IP6 service instance's heartbeat timer.
|
||||
@param[in] Context The IP6 service instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip6TimerTicking (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
IP6_SERVICE *IpSb;
|
||||
|
||||
IpSb = (IP6_SERVICE *) Context;
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
|
||||
Ip6PacketTimerTicking (IpSb);
|
||||
Ip6NdTimerTicking (IpSb);
|
||||
Ip6MldTimerTicking (IpSb);
|
||||
}
|
267
NetworkPkg/Ip6Dxe/Ip6If.h
Normal file
267
NetworkPkg/Ip6Dxe/Ip6If.h
Normal file
@@ -0,0 +1,267 @@
|
||||
/** @file
|
||||
Definition for IP6 pesudo interface structure.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP6_IF_H__
|
||||
#define __EFI_IP6_IF_H__
|
||||
|
||||
#define IP6_LINK_RX_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'R')
|
||||
#define IP6_LINK_TX_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'T')
|
||||
#define IP6_INTERFACE_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'I')
|
||||
#define IP6_ADDR_INFO_SIGNATURE SIGNATURE_32 ('I', 'P', 'A', 'I')
|
||||
|
||||
//
|
||||
// This prototype is used by both receive and transmission.
|
||||
// When receiving Netbuf is allocated by IP6_INTERFACE, and
|
||||
// released by IP6. Flag shows whether the frame is received
|
||||
// as unicast/multicast/anycast...
|
||||
//
|
||||
// When transmitting, the Netbuf is from IP6, and provided
|
||||
// to the callback as a reference. Flag isn't used.
|
||||
//
|
||||
// IpInstance can be NULL which means that it is the IP6 driver
|
||||
// itself sending the packets. IP6 driver may send packets that
|
||||
// don't belong to any instance, such as ICMP errors, ICMP
|
||||
// informational packets. IpInstance is used as a tag in
|
||||
// this module.
|
||||
//
|
||||
typedef
|
||||
VOID
|
||||
(*IP6_FRAME_CALLBACK) (
|
||||
NET_BUF *Packet,
|
||||
EFI_STATUS IoStatus,
|
||||
UINT32 LinkFlag,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
//
|
||||
// Each receive request is wrapped in an IP6_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;
|
||||
IP6_FRAME_CALLBACK CallBack;
|
||||
VOID *Context;
|
||||
EFI_MANAGED_NETWORK_COMPLETION_TOKEN MnpToken;
|
||||
} IP6_LINK_RX_TOKEN;
|
||||
|
||||
//
|
||||
// Each transmit request is wrapped in an IP6_LINK_TX_TOKEN.
|
||||
// Upon completion, the Callback will be called.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
IP6_PROTOCOL *IpInstance;
|
||||
IP6_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;
|
||||
} IP6_LINK_TX_TOKEN;
|
||||
|
||||
struct _IP6_ADDRESS_INFO {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY Link;
|
||||
EFI_IPv6_ADDRESS Address;
|
||||
BOOLEAN IsAnycast;
|
||||
UINT8 PrefixLength;
|
||||
UINT32 ValidLifetime;
|
||||
UINT32 PreferredLifetime;
|
||||
};
|
||||
|
||||
//
|
||||
// Callback to select which frame to cancel. Caller can cancel a
|
||||
// single frame, or all the frame from an IP instance.
|
||||
//
|
||||
typedef
|
||||
BOOLEAN
|
||||
(*IP6_FRAME_TO_CANCEL) (
|
||||
IP6_LINK_TX_TOKEN *Frame,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
struct _IP6_INTERFACE {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
|
||||
//
|
||||
// IP address and prefix length of the interface. The fileds
|
||||
// are invalid if (Configured == FALSE)
|
||||
//
|
||||
LIST_ENTRY AddressList;
|
||||
UINT32 AddressCount;
|
||||
BOOLEAN Configured;
|
||||
|
||||
IP6_SERVICE *Service;
|
||||
|
||||
EFI_HANDLE Controller;
|
||||
EFI_HANDLE Image;
|
||||
|
||||
|
||||
//
|
||||
// Queues to keep the frames sent and waiting ARP request.
|
||||
//
|
||||
LIST_ENTRY ArpQues;
|
||||
LIST_ENTRY SentFrames;
|
||||
|
||||
|
||||
//
|
||||
// The interface's configuration variables
|
||||
//
|
||||
UINT32 DupAddrDetect;
|
||||
LIST_ENTRY DupAddrDetectList;
|
||||
LIST_ENTRY DelayJoinList;
|
||||
|
||||
//
|
||||
// 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 IP6_INTERFACE.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
@param[in] LinkLocal If TRUE, the instance is created for link-local address.
|
||||
Otherwise, it is not for a link-local address.
|
||||
|
||||
@return Point to the created IP6_INTERFACE, otherwise NULL.
|
||||
|
||||
**/
|
||||
IP6_INTERFACE *
|
||||
Ip6CreateInterface (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN BOOLEAN LinkLocal
|
||||
);
|
||||
|
||||
/**
|
||||
Free the interface used by IpInstance. All the IP instance with
|
||||
the same Ip/prefix pair share the same interface. It is reference
|
||||
counted. All the frames that haven't been sent will be cancelled.
|
||||
Because the IpInstance is optional, the caller must remove
|
||||
IpInstance from the interface's instance list.
|
||||
|
||||
@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.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CleanInterface (
|
||||
IN IP6_INTERFACE *Interface,
|
||||
IN IP6_PROTOCOL *IpInstance OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Free the link layer transmit token. It will close the event
|
||||
then free the memory used.
|
||||
|
||||
@param[in] Token Token to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6FreeLinkTxToken (
|
||||
IN IP6_LINK_TX_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Request Ip6OnFrameReceivedDpc as a DPC at TPL_CALLBACK
|
||||
|
||||
@param Event The receive event delivered to MNP for receive.
|
||||
@param Context Context for the callback.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip6OnFrameReceived (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Request to receive the packet from the interface.
|
||||
|
||||
@param[in] CallBack Function to call when the receive finished.
|
||||
@param[in] IpSb Points to the IP6 service binding instance.
|
||||
|
||||
@retval EFI_ALREADY_STARTED There is already a pending receive request.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources to receive.
|
||||
@retval EFI_SUCCESS The recieve request has been started.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ReceiveFrame (
|
||||
IN IP6_FRAME_CALLBACK CallBack,
|
||||
IN IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Send a frame from the interface. If the next hop is multicast address,
|
||||
it is transmitted immediately. If the next hop is a unicast,
|
||||
and the NextHop's MAC is not known, it will perform address resolution.
|
||||
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 IP6 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.
|
||||
|
||||
@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 successfully transmitted.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SendFrame (
|
||||
IN IP6_INTERFACE *Interface,
|
||||
IN IP6_PROTOCOL *IpInstance OPTIONAL,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_IPv6_ADDRESS *NextHop,
|
||||
IN IP6_FRAME_CALLBACK CallBack,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
The heartbeat timer of IP6 service instance. It times out
|
||||
all of its IP6 children's received-but-not-delivered and
|
||||
transmitted-but-not-recycle packets.
|
||||
|
||||
@param[in] Event The IP6 service instance's heart beat timer.
|
||||
@param[in] Context The IP6 service instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip6TimerTicking (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
#endif
|
1857
NetworkPkg/Ip6Dxe/Ip6Impl.c
Normal file
1857
NetworkPkg/Ip6Dxe/Ip6Impl.c
Normal file
File diff suppressed because it is too large
Load Diff
751
NetworkPkg/Ip6Dxe/Ip6Impl.h
Normal file
751
NetworkPkg/Ip6Dxe/Ip6Impl.h
Normal file
@@ -0,0 +1,751 @@
|
||||
/** @file
|
||||
Implementation of EFI_IP6_PROTOCOL protocol interfaces and type definitions.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP6_IMPL_H__
|
||||
#define __EFI_IP6_IMPL_H__
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
#include <Protocol/ManagedNetwork.h>
|
||||
#include <Protocol/IpSec.h>
|
||||
#include <Protocol/Ip6.h>
|
||||
#include <Protocol/Ip6Config.h>
|
||||
#include <Protocol/Dhcp6.h>
|
||||
#include <Protocol/DevicePath.h>
|
||||
#include <Protocol/HiiConfigRouting.h>
|
||||
#include <Protocol/HiiConfigAccess.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.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/HiiLib.h>
|
||||
#include <Library/UefiHiiServicesLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
|
||||
#include <Guid/MdeModuleHii.h>
|
||||
|
||||
#include "Ip6Common.h"
|
||||
#include "Ip6Driver.h"
|
||||
#include "Ip6Icmp.h"
|
||||
#include "Ip6If.h"
|
||||
#include "Ip6Input.h"
|
||||
#include "Ip6Mld.h"
|
||||
#include "Ip6Nd.h"
|
||||
#include "Ip6Option.h"
|
||||
#include "Ip6Output.h"
|
||||
#include "Ip6Route.h"
|
||||
#include "Ip6ConfigNv.h"
|
||||
#include "Ip6ConfigImpl.h"
|
||||
|
||||
#define IP6_PROTOCOL_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'P')
|
||||
#define IP6_SERVICE_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'S')
|
||||
|
||||
//
|
||||
// The state of IP6 protocol. It starts from UNCONFIGED. if it is
|
||||
// successfully configured, it goes to CONFIGED. if configure NULL
|
||||
// is called, it becomes UNCONFIGED again. If (partly) destroyed, it
|
||||
// becomes DESTROY.
|
||||
//
|
||||
#define IP6_STATE_UNCONFIGED 0
|
||||
#define IP6_STATE_CONFIGED 1
|
||||
#define IP6_STATE_DESTROY 2
|
||||
|
||||
//
|
||||
// The state of IP6 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 IP6_SERVICE_UNSTARTED 0
|
||||
#define IP6_SERVICE_STARTED 1
|
||||
#define IP6_SERVICE_CONFIGED 2
|
||||
#define IP6_SERVICE_DESTROY 3
|
||||
|
||||
#define IP6_INSTANCE_FROM_PROTOCOL(Ip6) \
|
||||
CR ((Ip6), IP6_PROTOCOL, Ip6Proto, IP6_PROTOCOL_SIGNATURE)
|
||||
|
||||
#define IP6_SERVICE_FROM_PROTOCOL(Sb) \
|
||||
CR ((Sb), IP6_SERVICE, ServiceBinding, IP6_SERVICE_SIGNATURE)
|
||||
|
||||
#define IP6_NO_MAPPING(IpInstance) (!(IpInstance)->Interface->Configured)
|
||||
|
||||
extern EFI_IPSEC_PROTOCOL *mIpSec;
|
||||
|
||||
//
|
||||
// IP6_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 IP6_TXTOKEN_WRAP will be released, and
|
||||
// user's event signalled.
|
||||
//
|
||||
typedef struct {
|
||||
IP6_PROTOCOL *IpInstance;
|
||||
EFI_IP6_COMPLETION_TOKEN *Token;
|
||||
EFI_EVENT IpSecRecycleSignal;
|
||||
NET_BUF *Packet;
|
||||
BOOLEAN Sent;
|
||||
INTN Life;
|
||||
} IP6_TXTOKEN_WRAP;
|
||||
|
||||
typedef struct {
|
||||
EFI_EVENT IpSecRecycleSignal;
|
||||
NET_BUF *Packet;
|
||||
} IP6_IPSEC_WRAP;
|
||||
|
||||
//
|
||||
// IP6_RXDATA_WRAP wraps the data IP6 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
|
||||
// IP6_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;
|
||||
IP6_PROTOCOL *IpInstance;
|
||||
NET_BUF *Packet;
|
||||
EFI_IP6_RECEIVE_DATA RxData;
|
||||
} IP6_RXDATA_WRAP;
|
||||
|
||||
struct _IP6_PROTOCOL {
|
||||
UINT32 Signature;
|
||||
|
||||
EFI_IP6_PROTOCOL Ip6Proto;
|
||||
EFI_HANDLE Handle;
|
||||
INTN State;
|
||||
|
||||
IP6_SERVICE *Service;
|
||||
LIST_ENTRY Link; // Link to all the IP protocol from the service
|
||||
|
||||
UINT8 PrefixLength; // PrefixLength of the configured station address.
|
||||
//
|
||||
// User's transmit/receive tokens, and received/deliverd packets
|
||||
//
|
||||
NET_MAP RxTokens;
|
||||
NET_MAP TxTokens; // map between (User's Token, IP6_TXTOKE_WRAP)
|
||||
LIST_ENTRY Received; // Received but not delivered packet
|
||||
LIST_ENTRY Delivered; // Delivered and to be recycled packets
|
||||
EFI_LOCK RecycleLock;
|
||||
|
||||
IP6_INTERFACE *Interface;
|
||||
LIST_ENTRY AddrLink; // Ip instances with the same IP address.
|
||||
|
||||
EFI_IPv6_ADDRESS *GroupList; // stored in network order.
|
||||
UINT32 GroupCount;
|
||||
|
||||
EFI_IP6_CONFIG_DATA ConfigData;
|
||||
};
|
||||
|
||||
struct _IP6_SERVICE {
|
||||
UINT32 Signature;
|
||||
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
|
||||
INTN State;
|
||||
BOOLEAN InDestroy;
|
||||
|
||||
//
|
||||
// List of all the IP instances and interfaces, and default
|
||||
// interface and route table and caches.
|
||||
//
|
||||
UINTN NumChildren;
|
||||
LIST_ENTRY Children;
|
||||
|
||||
LIST_ENTRY Interfaces;
|
||||
|
||||
IP6_INTERFACE *DefaultInterface;
|
||||
IP6_ROUTE_TABLE *RouteTable;
|
||||
|
||||
IP6_LINK_RX_TOKEN RecvRequest;
|
||||
|
||||
//
|
||||
// Ip reassemble utilities and MLD data
|
||||
//
|
||||
IP6_ASSEMBLE_TABLE Assemble;
|
||||
IP6_MLD_SERVICE_DATA MldCtrl;
|
||||
|
||||
EFI_IPv6_ADDRESS LinkLocalAddr;
|
||||
BOOLEAN LinkLocalOk;
|
||||
BOOLEAN LinkLocalDadFail;
|
||||
BOOLEAN Dhcp6NeedStart;
|
||||
BOOLEAN Dhcp6NeedInfoRequest;
|
||||
|
||||
//
|
||||
// ND data
|
||||
//
|
||||
UINT8 CurHopLimit;
|
||||
UINT32 LinkMTU;
|
||||
UINT32 BaseReachableTime;
|
||||
UINT32 ReachableTime;
|
||||
UINT32 RetransTimer;
|
||||
LIST_ENTRY NeighborTable;
|
||||
|
||||
LIST_ENTRY OnlinkPrefix;
|
||||
LIST_ENTRY AutonomousPrefix;
|
||||
|
||||
LIST_ENTRY DefaultRouterList;
|
||||
UINT32 RoundRobin;
|
||||
|
||||
UINT8 InterfaceIdLen;
|
||||
UINT8 *InterfaceId;
|
||||
|
||||
BOOLEAN RouterAdvertiseReceived;
|
||||
UINT8 SolicitTimer;
|
||||
UINT32 Ticks;
|
||||
|
||||
//
|
||||
// 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 FasterTimer;
|
||||
|
||||
//
|
||||
// IPv6 Configuration Protocol instance
|
||||
//
|
||||
IP6_CONFIG_INSTANCE Ip6ConfigInstance;
|
||||
|
||||
//
|
||||
// The string representation of the current mac address of the
|
||||
// NIC this IP6_SERVICE works on.
|
||||
//
|
||||
CHAR16 *MacString;
|
||||
UINT32 MaxPacketSize;
|
||||
UINT32 OldMaxPacketSize;
|
||||
};
|
||||
|
||||
/**
|
||||
The callback function for the net buffer which wraps the user's
|
||||
transmit token. Although this function seems simple,
|
||||
there are some subtle aspects.
|
||||
When a user requests the IP to transmit a packet by passing it a
|
||||
token, the token is wrapped in an IP6_TXTOKEN_WRAP and the data
|
||||
is wrapped in a net buffer. The net buffer's Free function is
|
||||
set to Ip6FreeTxToken. The Token and token wrap are added to the
|
||||
IP child's TxToken map. Then the buffer is passed to Ip6Output for
|
||||
transmission. If an error occurs before that, the buffer
|
||||
is freed, which in turn frees the token wrap. The wrap may
|
||||
have been added to the TxToken map or not, and the user's event
|
||||
shouldn't be signaled because we are still in the EfiIp6Transmit. If
|
||||
the buffer has been sent by Ip6Output, it should be removed from
|
||||
the TxToken map and the user's event signaled. The token wrap and buffer
|
||||
are bound together. Refer to the comments in Ip6Output for information
|
||||
about IP fragmentation.
|
||||
|
||||
@param[in] Context The token's wrap.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip6FreeTxToken (
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
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 promiscuous 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
|
||||
whether that is changed or not.
|
||||
|
||||
@param[in] IpSb The IP6 service instance that is to be changed.
|
||||
@param[in] Force Force the configuration or not.
|
||||
|
||||
@retval EFI_SUCCESS The MNP successfully configured/reconfigured.
|
||||
@retval Others The configuration failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ServiceConfigMnp (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN BOOLEAN Force
|
||||
);
|
||||
|
||||
/**
|
||||
Cancel the user's receive/transmit request. It is the worker function of
|
||||
EfiIp6Cancel API.
|
||||
|
||||
@param[in] IpInstance The IP6 child.
|
||||
@param[in] Token The token to cancel. If NULL, all tokens will be
|
||||
cancelled.
|
||||
|
||||
@retval EFI_SUCCESS The token was cancelled.
|
||||
@retval EFI_NOT_FOUND The token isn't found on either the
|
||||
transmit or receive queue.
|
||||
@retval EFI_DEVICE_ERROR Not all tokens are cancelled when Token is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6Cancel (
|
||||
IN IP6_PROTOCOL *IpInstance,
|
||||
IN EFI_IP6_COMPLETION_TOKEN *Token OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize the IP6_PROTOCOL structure to the unconfigured states.
|
||||
|
||||
@param[in] IpSb The IP6 service instance.
|
||||
@param[in, out] IpInstance The IP6 child instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6InitProtocol (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN OUT IP6_PROTOCOL *IpInstance
|
||||
);
|
||||
|
||||
/**
|
||||
Clean up the IP6 child, release all the resources used by it.
|
||||
|
||||
@param[in, out] IpInstance The IP6 child to clean up.
|
||||
|
||||
@retval EFI_SUCCESS The IP6 child was cleaned up
|
||||
@retval EFI_DEVICE_ERROR Some resources failed to be released.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6CleanProtocol (
|
||||
IN OUT IP6_PROTOCOL *IpInstance
|
||||
);
|
||||
|
||||
//
|
||||
// EFI_IP6_PROTOCOL interface prototypes
|
||||
//
|
||||
|
||||
/**
|
||||
Gets the current operational settings for this instance of the EFI IPv6 Protocol driver.
|
||||
|
||||
The GetModeData() function returns the current operational mode data for this driver instance.
|
||||
The data fields in EFI_IP6_MODE_DATA are read only. This function is used optionally to
|
||||
retrieve the operational mode data of underlying networks or drivers.
|
||||
|
||||
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
|
||||
@param[out] Ip6ModeData The pointer to the EFI IPv6 Protocol mode data structure.
|
||||
@param[out] MnpConfigData The pointer to the managed network configuration data structure.
|
||||
@param[out] SnpModeData The pointer to the simple network mode data structure.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_INVALID_PARAMETER This is NULL.
|
||||
@retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiIp6GetModeData (
|
||||
IN EFI_IP6_PROTOCOL *This,
|
||||
OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL,
|
||||
OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
|
||||
OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Assigns an IPv6 address and subnet mask to this EFI IPv6 Protocol driver instance.
|
||||
|
||||
The Configure() function is used to set, change, or reset the operational parameters and filter
|
||||
settings for this EFI IPv6 Protocol instance. Until these parameters have been set, no network traffic
|
||||
can be sent or received by this instance. Once the parameters have been reset (by calling this
|
||||
function with Ip6ConfigData set to NULL), no more traffic can be sent or received until these
|
||||
parameters have been set again. Each EFI IPv6 Protocol instance can be started and stopped
|
||||
independently of each other by enabling or disabling their receive filter settings with the
|
||||
Configure() function.
|
||||
|
||||
If Ip6ConfigData.StationAddress is a valid non-zero IPv6 unicast address, it is required
|
||||
to be one of the currently configured IPv6 addresses list in the EFI IPv6 drivers, or else
|
||||
EFI_INVALID_PARAMETER will be returned. If Ip6ConfigData.StationAddress is
|
||||
unspecified, the IPv6 driver will bind a source address according to the source address selection
|
||||
algorithm. Clients could frequently call GetModeData() to check get a currently configured IPv6.
|
||||
If both Ip6ConfigData.StationAddress and Ip6ConfigData.Destination are unspecified, when
|
||||
transmitting the packet afterwards, the source address filled in each outgoing IPv6 packet
|
||||
is decided based on the destination of this packet.
|
||||
|
||||
If operational parameters are reset or changed, any pending transmit and receive requests will be
|
||||
cancelled. Their completion token status will be set to EFI_ABORTED, and their events will be
|
||||
signaled.
|
||||
|
||||
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
|
||||
@param[in] Ip6ConfigData The pointer to the EFI IPv6 Protocol configuration data structure.
|
||||
If NULL, reset the configuration data.
|
||||
|
||||
@retval EFI_SUCCESS The driver instance was successfully opened.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- This is NULL.
|
||||
- Ip6ConfigData.StationAddress is neither zero nor
|
||||
a unicast IPv6 address.
|
||||
- Ip6ConfigData.StationAddress is neither zero nor
|
||||
one of the configured IP addresses in the EFI IPv6 driver.
|
||||
- Ip6ConfigData.DefaultProtocol is illegal.
|
||||
@retval EFI_OUT_OF_RESOURCES The EFI IPv6 Protocol driver instance data could not be allocated.
|
||||
@retval EFI_NO_MAPPING The IPv6 driver was responsible for choosing a source address for
|
||||
this instance, but no source address was available for use.
|
||||
@retval EFI_ALREADY_STARTED The interface is already open and must be stopped before the IPv6
|
||||
address or prefix length can be changed.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI IPv6
|
||||
Protocol driver instance was not opened.
|
||||
@retval EFI_UNSUPPORTED Default protocol specified through
|
||||
Ip6ConfigData.DefaulProtocol isn't supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiIp6Configure (
|
||||
IN EFI_IP6_PROTOCOL *This,
|
||||
IN EFI_IP6_CONFIG_DATA *Ip6ConfigData OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Joins and leaves multicast groups.
|
||||
|
||||
The Groups() function is used to join and leave multicast group sessions. Joining a group will
|
||||
enable reception of matching multicast packets. Leaving a group will disable reception of matching
|
||||
multicast packets. Source-Specific Multicast isn't required to be supported.
|
||||
|
||||
If JoinFlag is FALSE and GroupAddress is NULL, all joined groups will be left.
|
||||
|
||||
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
|
||||
@param[in] JoinFlag Set to TRUE to join the multicast group session and FALSE to leave.
|
||||
@param[in] GroupAddress The pointer to the IPv6 multicast address.
|
||||
This is an optional parameter that may be NULL.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following is TRUE:
|
||||
- This is NULL.
|
||||
- JoinFlag is TRUE and GroupAddress is NULL.
|
||||
- GroupAddress is not NULL and *GroupAddress is
|
||||
not a multicast IPv6 address.
|
||||
- GroupAddress is not NULL and *GroupAddress is in the
|
||||
range of SSM destination address.
|
||||
@retval EFI_NOT_STARTED This instance has not been started.
|
||||
@retval EFI_OUT_OF_RESOURCES System resources could not be allocated.
|
||||
@retval EFI_UNSUPPORTED This EFI IPv6 Protocol implementation does not support multicast groups.
|
||||
@retval EFI_ALREADY_STARTED The group address is already in the group table (when
|
||||
JoinFlag is TRUE).
|
||||
@retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE).
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiIp6Groups (
|
||||
IN EFI_IP6_PROTOCOL *This,
|
||||
IN BOOLEAN JoinFlag,
|
||||
IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Adds and deletes routing table entries.
|
||||
|
||||
The Routes() function adds a route to or deletes a route from the routing table.
|
||||
|
||||
Routes are determined by comparing the leftmost PrefixLength bits of Destination with
|
||||
the destination IPv6 address arithmetically. The gateway address must be on the same subnet as the
|
||||
configured station address.
|
||||
|
||||
The default route is added with Destination and PrefixLegth both set to all zeros. The
|
||||
default route matches all destination IPv6 addresses that do not match any other routes.
|
||||
|
||||
All EFI IPv6 Protocol instances share a routing table.
|
||||
|
||||
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
|
||||
@param[in] DeleteRoute Set to TRUE to delete this route from the routing table. Set to
|
||||
FALSE to add this route to the routing table. Destination,
|
||||
PrefixLength and Gateway are used as the key to each
|
||||
route entry.
|
||||
@param[in] Destination The address prefix of the subnet that needs to be routed.
|
||||
This is an optional parameter that may be NULL.
|
||||
@param[in] PrefixLength The prefix length of Destination. Ignored if Destination
|
||||
is NULL.
|
||||
@param[in] GatewayAddress The unicast gateway IPv6 address for this route.
|
||||
This is an optional parameter that may be NULL.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_NOT_STARTED The driver instance has not been started.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- This is NULL.
|
||||
- When DeleteRoute is TRUE, both Destination and
|
||||
GatewayAddress are NULL.
|
||||
- When DeleteRoute is FALSE, either Destination or
|
||||
GatewayAddress is NULL.
|
||||
- *GatewayAddress is not a valid unicast IPv6 address.
|
||||
- *GatewayAddress is one of the local configured IPv6
|
||||
addresses.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
|
||||
@retval EFI_NOT_FOUND This route is not in the routing table (when DeleteRoute is TRUE).
|
||||
@retval EFI_ACCESS_DENIED The route is already defined in the routing table (when
|
||||
DeleteRoute is FALSE).
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiIp6Routes (
|
||||
IN EFI_IP6_PROTOCOL *This,
|
||||
IN BOOLEAN DeleteRoute,
|
||||
IN EFI_IPv6_ADDRESS *Destination OPTIONAL,
|
||||
IN UINT8 PrefixLength,
|
||||
IN EFI_IPv6_ADDRESS *GatewayAddress OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Add or delete Neighbor cache entries.
|
||||
|
||||
The Neighbors() function is used to add, update, or delete an entry from a neighbor cache.
|
||||
IPv6 neighbor cache entries are typically inserted and updated by the network protocol driver as
|
||||
network traffic is processed. Most neighbor cache entries will timeout and be deleted if the network
|
||||
traffic stops. Neighbor cache entries that were inserted by Neighbors() may be static (will not
|
||||
timeout) or dynamic (will timeout).
|
||||
|
||||
The implementation should follow the neighbor cache timeout mechanism defined in
|
||||
RFC4861. The default neighbor cache timeout value should be tuned for the expected network
|
||||
environment.
|
||||
|
||||
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
|
||||
@param[in] DeleteFlag Set to TRUE to delete the specified cache entry. Set to FALSE to
|
||||
add (or update, if it already exists and Override is TRUE) the
|
||||
specified cache entry. TargetIp6Address is used as the key
|
||||
to find the requested cache entry.
|
||||
@param[in] TargetIp6Address The pointer to the Target IPv6 address.
|
||||
@param[in] TargetLinkAddress The pointer to link-layer address of the target. Ignored if NULL.
|
||||
@param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor
|
||||
cache, it will be deleted after Timeout. A value of zero means that
|
||||
the entry is permanent. A non-zero value means that the entry is
|
||||
dynamic.
|
||||
@param[in] Override If TRUE, the cached link-layer address of the matching entry will
|
||||
be overridden and updated; if FALSE, EFI_ACCESS_DENIED
|
||||
will be returned if a corresponding cache entry already exists.
|
||||
|
||||
@retval EFI_SUCCESS The data has been queued for transmission.
|
||||
@retval EFI_NOT_STARTED This instance has not been started.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- This is NULL.
|
||||
- TargetIpAddress is NULL.
|
||||
- *TargetLinkAddress is invalid when not NULL.
|
||||
- *TargetIpAddress is not a valid unicast IPv6 address.
|
||||
- *TargetIpAddress is one of the local configured IPv6
|
||||
addresses.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not add the entry to the neighbor cache.
|
||||
@retval EFI_NOT_FOUND This entry is not in the neighbor cache (when DeleteFlag is
|
||||
TRUE or when DeleteFlag is FALSE while
|
||||
TargetLinkAddress is NULL.).
|
||||
@retval EFI_ACCESS_DENIED The to-be-added entry is already defined in the neighbor cache,
|
||||
and that entry is tagged as un-overridden (when Override
|
||||
is FALSE).
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiIp6Neighbors (
|
||||
IN EFI_IP6_PROTOCOL *This,
|
||||
IN BOOLEAN DeleteFlag,
|
||||
IN EFI_IPv6_ADDRESS *TargetIp6Address,
|
||||
IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
|
||||
IN UINT32 Timeout,
|
||||
IN BOOLEAN Override
|
||||
);
|
||||
|
||||
/**
|
||||
Places outgoing data packets into the transmit queue.
|
||||
|
||||
The Transmit() function places a sending request in the transmit queue of this
|
||||
EFI IPv6 Protocol instance. Whenever the packet in the token is sent out or some
|
||||
errors occur, the event in the token will be signaled and the status is updated.
|
||||
|
||||
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
|
||||
@param[in] Token The pointer to the transmit token.
|
||||
|
||||
@retval EFI_SUCCESS The data has been queued for transmission.
|
||||
@retval EFI_NOT_STARTED This instance has not been started.
|
||||
@retval EFI_NO_MAPPING The IPv6 driver was responsible for choosing
|
||||
a source address for this transmission,
|
||||
but no source address was available for use.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following is TRUE:
|
||||
- This is NULL.
|
||||
- Token is NULL.
|
||||
- Token.Event is NULL.
|
||||
- Token.Packet.TxData is NULL.
|
||||
- Token.Packet.ExtHdrsLength is not zero and
|
||||
Token.Packet.ExtHdrs is NULL.
|
||||
- Token.Packet.FragmentCount is zero.
|
||||
- One or more of the Token.Packet.TxData.
|
||||
FragmentTable[].FragmentLength fields is zero.
|
||||
- One or more of the Token.Packet.TxData.
|
||||
FragmentTable[].FragmentBuffer fields is NULL.
|
||||
- Token.Packet.TxData.DataLength is zero or not
|
||||
equal to the sum of fragment lengths.
|
||||
- Token.Packet.TxData.DestinationAddress is non-
|
||||
zero when DestinationAddress is configured as
|
||||
non-zero when doing Configure() for this
|
||||
EFI IPv6 protocol instance.
|
||||
- Token.Packet.TxData.DestinationAddress is
|
||||
unspecified when DestinationAddress is unspecified
|
||||
when doing Configure() for this EFI IPv6 protocol
|
||||
instance.
|
||||
@retval EFI_ACCESS_DENIED The transmit completion token with the same Token.
|
||||
The event was already in the transmit queue.
|
||||
@retval EFI_NOT_READY The completion token could not be queued because
|
||||
the transmit queue is full.
|
||||
@retval EFI_NOT_FOUND Not route is found to the destination address.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not queue the transmit data.
|
||||
@retval EFI_BUFFER_TOO_SMALL Token.Packet.TxData.TotalDataLength is too
|
||||
short to transmit.
|
||||
@retval EFI_BAD_BUFFER_SIZE If Token.Packet.TxData.DataLength is beyond the
|
||||
maximum that which can be described through the
|
||||
Fragment Offset field in Fragment header when
|
||||
performing fragmentation.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiIp6Transmit (
|
||||
IN EFI_IP6_PROTOCOL *This,
|
||||
IN EFI_IP6_COMPLETION_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Places a receiving request into the receiving queue.
|
||||
|
||||
The Receive() function places a completion token into the receive packet queue.
|
||||
This function is always asynchronous.
|
||||
|
||||
The Token.Event field in the completion token must be filled in by the caller
|
||||
and cannot be NULL. When the receive operation completes, the EFI IPv6 Protocol
|
||||
driver updates the Token.Status and Token.Packet.RxData fields and the Token.Event
|
||||
is signaled.
|
||||
|
||||
Current Udp implementation creates an IP child for each Udp child.
|
||||
It initates a asynchronous receive immediately whether or not
|
||||
there is no mapping. Therefore, disable the returning EFI_NO_MAPPING for now.
|
||||
To enable it, the following check must be performed:
|
||||
|
||||
if (NetIp6IsUnspecifiedAddr (&Config->StationAddress) && IP6_NO_MAPPING (IpInstance)) {
|
||||
Status = EFI_NO_MAPPING;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
|
||||
@param[in] Token The pointer to a token that is associated with the
|
||||
receive data descriptor.
|
||||
|
||||
@retval EFI_SUCCESS The receive completion token was cached.
|
||||
@retval EFI_NOT_STARTED This EFI IPv6 Protocol instance has not been started.
|
||||
@retval EFI_NO_MAPPING When IP6 driver responsible for binding source address to this instance,
|
||||
while no source address is available for use.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- This is NULL.
|
||||
- Token is NULL.
|
||||
- Token.Event is NULL.
|
||||
@retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system
|
||||
resources (usually memory).
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
The EFI IPv6 Protocol instance has been reset to startup defaults.
|
||||
@retval EFI_ACCESS_DENIED The receive completion token with the same Token.Event was already
|
||||
in the receive queue.
|
||||
@retval EFI_NOT_READY The receive request could not be queued because the receive queue is full.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiIp6Receive (
|
||||
IN EFI_IP6_PROTOCOL *This,
|
||||
IN EFI_IP6_COMPLETION_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Abort an asynchronous transmit or receive request.
|
||||
|
||||
The Cancel() function is used to abort a pending transmit or receive request.
|
||||
If the token is in the transmit or receive request queues, after calling this
|
||||
function, Token->Status will be set to EFI_ABORTED, and then Token->Event will
|
||||
be signaled. If the token is not in one of the queues, which usually means the
|
||||
asynchronous operation has completed, this function will not signal the token,
|
||||
and EFI_NOT_FOUND is returned.
|
||||
|
||||
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
|
||||
@param[in] Token The pointer to a token that has been issued by
|
||||
EFI_IP6_PROTOCOL.Transmit() or
|
||||
EFI_IP6_PROTOCOL.Receive(). If NULL, all pending
|
||||
tokens are aborted. Type EFI_IP6_COMPLETION_TOKEN is
|
||||
defined in EFI_IP6_PROTOCOL.Transmit().
|
||||
|
||||
@retval EFI_SUCCESS The asynchronous I/O request was aborted and
|
||||
Token->Event was signaled. When Token is NULL, all
|
||||
pending requests were aborted, and their events were signaled.
|
||||
@retval EFI_INVALID_PARAMETER This is NULL.
|
||||
@retval EFI_NOT_STARTED This instance has not been started.
|
||||
@retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was
|
||||
not found in the transmit or receive queue. It has either completed
|
||||
or was not issued by Transmit() and Receive().
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiIp6Cancel (
|
||||
IN EFI_IP6_PROTOCOL *This,
|
||||
IN EFI_IP6_COMPLETION_TOKEN *Token OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Polls for incoming data packets and processes outgoing data packets.
|
||||
|
||||
The Poll() function polls for incoming data packets and processes outgoing data
|
||||
packets. Network drivers and applications can call the EFI_IP6_PROTOCOL.Poll()
|
||||
function to increase the rate that data packets are moved between the communications
|
||||
device and the transmit and receive queues.
|
||||
|
||||
In some systems the periodic timer event may not poll the underlying communications
|
||||
device fast enough to transmit and/or receive all data packets without missing
|
||||
incoming packets or dropping outgoing packets. Drivers and applications that are
|
||||
experiencing packet loss should try calling the EFI_IP6_PROTOCOL.Poll() function
|
||||
more often.
|
||||
|
||||
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS Incoming or outgoing data was processed.
|
||||
@retval EFI_NOT_STARTED This EFI IPv6 Protocol instance has not been started.
|
||||
@retval EFI_INVALID_PARAMETER This is NULL.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
@retval EFI_NOT_READY No incoming or outgoing data was processed.
|
||||
@retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.
|
||||
Consider increasing the polling rate.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiIp6Poll (
|
||||
IN EFI_IP6_PROTOCOL *This
|
||||
);
|
||||
|
||||
#endif
|
1710
NetworkPkg/Ip6Dxe/Ip6Input.c
Normal file
1710
NetworkPkg/Ip6Dxe/Ip6Input.c
Normal file
File diff suppressed because it is too large
Load Diff
235
NetworkPkg/Ip6Dxe/Ip6Input.h
Normal file
235
NetworkPkg/Ip6Dxe/Ip6Input.h
Normal file
@@ -0,0 +1,235 @@
|
||||
/** @file
|
||||
IP6 internal functions and definitions to process the incoming packets.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP6_INPUT_H__
|
||||
#define __EFI_IP6_INPUT_H__
|
||||
|
||||
#define IP6_MIN_HEADLEN 40
|
||||
#define IP6_MAX_HEADLEN 120
|
||||
///
|
||||
/// 8(ESP header) + 16(max IV) + 16(max padding) + 2(ESP tail) + 12(max ICV) = 54
|
||||
///
|
||||
#define IP6_MAX_IPSEC_HEADLEN 54
|
||||
|
||||
|
||||
#define IP6_ASSEMLE_HASH_SIZE 127
|
||||
///
|
||||
/// Lift time in seconds.
|
||||
///
|
||||
#define IP6_FRAGMENT_LIFE 60
|
||||
#define IP6_MAX_PACKET_SIZE 65535
|
||||
|
||||
|
||||
#define IP6_GET_CLIP_INFO(Packet) ((IP6_CLIP_INFO *) ((Packet)->ProtoData))
|
||||
|
||||
#define IP6_ASSEMBLE_HASH(Dst, Src, Id) \
|
||||
((*((UINT32 *) (Dst)) + *((UINT32 *) (Src)) + (Id)) % IP6_ASSEMLE_HASH_SIZE)
|
||||
|
||||
#define IP6_RXDATA_WRAP_SIZE(NumFrag) \
|
||||
(sizeof (IP6_RXDATA_WRAP) + sizeof (EFI_IP6_FRAGMENT_DATA) * ((NumFrag) - 1))
|
||||
|
||||
//
|
||||
// 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 {
|
||||
UINT32 LinkFlag;
|
||||
INT32 CastType;
|
||||
INT32 Start;
|
||||
INT32 End;
|
||||
INT32 Length;
|
||||
UINT32 Life;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Id;
|
||||
UINT16 HeadLen;
|
||||
UINT8 NextHeader;
|
||||
UINT8 LastFrag;
|
||||
UINT32 FormerNextHeader;
|
||||
} IP6_CLIP_INFO;
|
||||
|
||||
//
|
||||
// Structure used to assemble IP packets.
|
||||
//
|
||||
typedef struct {
|
||||
LIST_ENTRY Link;
|
||||
LIST_ENTRY Fragments; // List of all the fragments of this packet
|
||||
|
||||
//
|
||||
// Identity of one IP6 packet. Each fragment of a packet has
|
||||
// the same (Dst, Src, Id).
|
||||
//
|
||||
EFI_IPv6_ADDRESS Dst;
|
||||
EFI_IPv6_ADDRESS Src;
|
||||
UINT32 Id;
|
||||
|
||||
UINT32 TotalLen;
|
||||
UINT32 CurLen;
|
||||
UINT32 Life; // Count down life for the packet.
|
||||
|
||||
EFI_IP6_HEADER *Head; // IP head of the first fragment
|
||||
IP6_CLIP_INFO *Info; // Per packet information of the first fragment
|
||||
NET_BUF *Packet; // The first fragment of the packet
|
||||
} IP6_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[IP6_ASSEMLE_HASH_SIZE];
|
||||
} IP6_ASSEMBLE_TABLE;
|
||||
|
||||
/**
|
||||
The IP6 input routine. It is called by the IP6_INTERFACE when an
|
||||
IP6 fragment is received from MNP.
|
||||
|
||||
@param[in] Packet The IP6 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 IP6 service instance that own the MNP.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6AcceptFrame (
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN UINT32 Flag,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
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
|
||||
Ip6InstanceDeliverPacket (
|
||||
IN IP6_PROTOCOL *IpInstance
|
||||
);
|
||||
|
||||
/**
|
||||
The work function to locate IPsec protocol to process the inbound or
|
||||
outbound IP packets. The process routine handls the packet with the following
|
||||
actions: bypass the packet, discard the packet, or protect the packet.
|
||||
|
||||
@param[in] IpSb The IP6 service instance.
|
||||
@param[in] Head The caller supplied IP6 header.
|
||||
@param[in, out] LastHead The next header field of last IP header.
|
||||
@param[in, out] Netbuf The IP6 packet to be processed by IPsec.
|
||||
@param[in] ExtHdrs The caller supplied options.
|
||||
@param[in] ExtHdrsLen 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 are not suffcient resources 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 building a fragment table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6IpSecProcessPacket (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN OUT UINT8 *LastHead,
|
||||
IN OUT NET_BUF **Netbuf,
|
||||
IN VOID *ExtHdrs,
|
||||
IN UINT32 ExtHdrsLen,
|
||||
IN EFI_IPSEC_TRAFFIC_DIR Direction,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize an already allocated assemble table. This is generally
|
||||
the assemble table embedded in the IP6 service instance.
|
||||
|
||||
@param[in, out] Table The assemble table to initialize.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CreateAssembleTable (
|
||||
IN OUT IP6_ASSEMBLE_TABLE *Table
|
||||
);
|
||||
|
||||
/**
|
||||
Clean up the assemble table: remove all the fragments
|
||||
and assemble entries.
|
||||
|
||||
@param[in, out] Table The assemble table to clean up.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CleanAssembleTable (
|
||||
IN OUT IP6_ASSEMBLE_TABLE *Table
|
||||
);
|
||||
|
||||
/**
|
||||
Demultiple the packet. the packet delivery is processed in two
|
||||
passes. The first pass will enque a shared copy of the packet
|
||||
to each IP6 child that accepts the packet. The second pass will
|
||||
deliver a non-shared copy of the packet to each IP6 child that
|
||||
has pending receive requests. Data is copied if more than one
|
||||
child wants to consume the packet bacause each IP child need
|
||||
its own copy of the packet to make changes.
|
||||
|
||||
@param[in] IpSb The IP6 service instance that received the packet.
|
||||
@param[in] Head The header of the received packet.
|
||||
@param[in] Packet The data of the received packet.
|
||||
|
||||
@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
|
||||
Ip6Demultiplex (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
Timeout the fragmented, enqueued, and transmitted packets.
|
||||
|
||||
@param[in] IpSb The IP6 service instance to timeout.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6PacketTimerTicking (
|
||||
IN IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
#endif
|
908
NetworkPkg/Ip6Dxe/Ip6Mld.c
Normal file
908
NetworkPkg/Ip6Dxe/Ip6Mld.c
Normal file
@@ -0,0 +1,908 @@
|
||||
/** @file
|
||||
Multicast Listener Discovery support routines.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip6Impl.h"
|
||||
|
||||
/**
|
||||
Create a IP6_MLD_GROUP list entry node and record to IP6 service binding data.
|
||||
|
||||
@param[in, out] IpSb Points to IP6 service binding instance.
|
||||
@param[in] MulticastAddr The IPv6 multicast address to be recorded.
|
||||
@param[in] DelayTimer The maximum allowed delay before sending a responding
|
||||
report, in units of milliseconds.
|
||||
@return The created IP6_ML_GROUP list entry or NULL.
|
||||
|
||||
**/
|
||||
IP6_MLD_GROUP *
|
||||
Ip6CreateMldEntry (
|
||||
IN OUT IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *MulticastAddr,
|
||||
IN UINT32 DelayTimer
|
||||
)
|
||||
{
|
||||
IP6_MLD_GROUP *Entry;
|
||||
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
|
||||
|
||||
Entry = AllocatePool (sizeof (IP6_MLD_GROUP));
|
||||
if (Entry != NULL) {
|
||||
Entry->RefCnt = 1;
|
||||
Entry->DelayTimer = DelayTimer;
|
||||
Entry->SendByUs = FALSE;
|
||||
IP6_COPY_ADDRESS (&Entry->Address, MulticastAddr);
|
||||
InsertTailList (&IpSb->MldCtrl.Groups, &Entry->Link);
|
||||
}
|
||||
|
||||
return Entry;
|
||||
}
|
||||
|
||||
/**
|
||||
Search a IP6_MLD_GROUP list entry node from a list array.
|
||||
|
||||
@param[in] IpSb Points to IP6 service binding instance.
|
||||
@param[in] MulticastAddr The IPv6 multicast address to be searched.
|
||||
|
||||
@return The found IP6_ML_GROUP list entry or NULL.
|
||||
|
||||
**/
|
||||
IP6_MLD_GROUP *
|
||||
Ip6FindMldEntry (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *MulticastAddr
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP6_MLD_GROUP *Group;
|
||||
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
|
||||
if (EFI_IP6_EQUAL (MulticastAddr, &Group->Address)) {
|
||||
return Group;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Count the number of IP6 multicast groups that are mapped to the
|
||||
same MAC address. Several IP6 multicast address may be mapped to
|
||||
the same MAC address.
|
||||
|
||||
@param[in] MldCtrl The MLD control block to search in.
|
||||
@param[in] Mac The MAC address to search.
|
||||
|
||||
@return The number of the IP6 multicast group that mapped to the same
|
||||
multicast group Mac.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip6FindMac (
|
||||
IN IP6_MLD_SERVICE_DATA *MldCtrl,
|
||||
IN EFI_MAC_ADDRESS *Mac
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP6_MLD_GROUP *Group;
|
||||
INTN Count;
|
||||
|
||||
Count = 0;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &MldCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
|
||||
|
||||
if (NET_MAC_EQUAL (&Group->Mac, Mac, sizeof (EFI_MAC_ADDRESS))) {
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
|
||||
return Count;
|
||||
}
|
||||
|
||||
/**
|
||||
Generate MLD report message and send it out to MulticastAddr.
|
||||
|
||||
@param[in] IpSb The IP service to send the packet.
|
||||
@param[in] Interface The IP interface to send the packet.
|
||||
If NULL, a system interface will be selected.
|
||||
@param[in] MulticastAddr The specific IPv6 multicast address to which
|
||||
the message sender is listening.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete the
|
||||
operation.
|
||||
@retval EFI_SUCCESS The MLD report message was successfully sent out.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SendMldReport (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN IP6_INTERFACE *Interface OPTIONAL,
|
||||
IN EFI_IPv6_ADDRESS *MulticastAddr
|
||||
)
|
||||
{
|
||||
IP6_MLD_HEAD *MldHead;
|
||||
NET_BUF *Packet;
|
||||
EFI_IP6_HEADER Head;
|
||||
UINT16 PayloadLen;
|
||||
UINTN OptionLen;
|
||||
UINT8 *Options;
|
||||
EFI_STATUS Status;
|
||||
UINT16 HeadChecksum;
|
||||
UINT16 PseudoChecksum;
|
||||
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
|
||||
|
||||
//
|
||||
// Generate the packet to be sent
|
||||
// IPv6 basic header + Hop by Hop option + MLD message
|
||||
//
|
||||
|
||||
OptionLen = 0;
|
||||
Status = Ip6FillHopByHop (NULL, &OptionLen, IP6_ICMP);
|
||||
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
|
||||
|
||||
PayloadLen = (UINT16) (OptionLen + sizeof (IP6_MLD_HEAD));
|
||||
Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32) PayloadLen);
|
||||
if (Packet == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the basic IPv6 header.
|
||||
// RFC3590: Use link-local address as source address if it is available,
|
||||
// otherwise use the unspecified address.
|
||||
//
|
||||
Head.FlowLabelL = 0;
|
||||
Head.FlowLabelH = 0;
|
||||
Head.PayloadLength = HTONS (PayloadLen);
|
||||
Head.NextHeader = IP6_HOP_BY_HOP;
|
||||
Head.HopLimit = 1;
|
||||
IP6_COPY_ADDRESS (&Head.DestinationAddress, MulticastAddr);
|
||||
|
||||
//
|
||||
// If Link-Local address is not ready, we use unspecified address.
|
||||
//
|
||||
IP6_COPY_ADDRESS (&Head.SourceAddress, &IpSb->LinkLocalAddr);
|
||||
|
||||
NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
|
||||
|
||||
//
|
||||
// Fill a IPv6 Router Alert option in a Hop-by-Hop Options Header
|
||||
//
|
||||
Options = NetbufAllocSpace (Packet, (UINT32) OptionLen, FALSE);
|
||||
ASSERT (Options != NULL);
|
||||
Status = Ip6FillHopByHop (Options, &OptionLen, IP6_ICMP);
|
||||
if (EFI_ERROR (Status)) {
|
||||
NetbufFree (Packet);
|
||||
Packet = NULL;
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill in MLD message - Report
|
||||
//
|
||||
MldHead = (IP6_MLD_HEAD *) NetbufAllocSpace (Packet, sizeof (IP6_MLD_HEAD), FALSE);
|
||||
ASSERT (MldHead != NULL);
|
||||
ZeroMem (MldHead, sizeof (IP6_MLD_HEAD));
|
||||
MldHead->Head.Type = ICMP_V6_LISTENER_REPORT;
|
||||
MldHead->Head.Code = 0;
|
||||
IP6_COPY_ADDRESS (&MldHead->Group, MulticastAddr);
|
||||
|
||||
HeadChecksum = NetblockChecksum ((UINT8 *) MldHead, sizeof (IP6_MLD_HEAD));
|
||||
PseudoChecksum = NetIp6PseudoHeadChecksum (
|
||||
&Head.SourceAddress,
|
||||
&Head.DestinationAddress,
|
||||
IP6_ICMP,
|
||||
sizeof (IP6_MLD_HEAD)
|
||||
);
|
||||
|
||||
MldHead->Head.Checksum = (UINT16) ~NetAddChecksum (HeadChecksum, PseudoChecksum);
|
||||
|
||||
//
|
||||
// Transmit the packet
|
||||
//
|
||||
return Ip6Output (IpSb, Interface, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
Generate MLD Done message and send it out to MulticastAddr.
|
||||
|
||||
@param[in] IpSb The IP service to send the packet.
|
||||
@param[in] MulticastAddr The specific IPv6 multicast address to which
|
||||
the message sender is ceasing to listen.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete the
|
||||
operation.
|
||||
@retval EFI_SUCCESS The MLD report message was successfully sent out.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SendMldDone (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *MulticastAddr
|
||||
)
|
||||
{
|
||||
IP6_MLD_HEAD *MldHead;
|
||||
NET_BUF *Packet;
|
||||
EFI_IP6_HEADER Head;
|
||||
UINT16 PayloadLen;
|
||||
UINTN OptionLen;
|
||||
UINT8 *Options;
|
||||
EFI_STATUS Status;
|
||||
EFI_IPv6_ADDRESS Destination;
|
||||
UINT16 HeadChecksum;
|
||||
UINT16 PseudoChecksum;
|
||||
|
||||
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
|
||||
ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
|
||||
|
||||
//
|
||||
// Generate the packet to be sent
|
||||
// IPv6 basic header + Hop by Hop option + MLD message
|
||||
//
|
||||
|
||||
OptionLen = 0;
|
||||
Status = Ip6FillHopByHop (NULL, &OptionLen, IP6_ICMP);
|
||||
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
|
||||
|
||||
PayloadLen = (UINT16) (OptionLen + sizeof (IP6_MLD_HEAD));
|
||||
Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32) PayloadLen);
|
||||
if (Packet == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the basic IPv6 header.
|
||||
//
|
||||
Head.FlowLabelL = 0;
|
||||
Head.FlowLabelH = 0;
|
||||
Head.PayloadLength = HTONS (PayloadLen);
|
||||
Head.NextHeader = IP6_HOP_BY_HOP;
|
||||
Head.HopLimit = 1;
|
||||
|
||||
//
|
||||
// If Link-Local address is not ready, we use unspecified address.
|
||||
//
|
||||
IP6_COPY_ADDRESS (&Head.SourceAddress, &IpSb->LinkLocalAddr);
|
||||
|
||||
Ip6SetToAllNodeMulticast (TRUE, IP6_LINK_LOCAL_SCOPE, &Destination);
|
||||
IP6_COPY_ADDRESS (&Head.DestinationAddress, &Destination);
|
||||
|
||||
NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
|
||||
|
||||
//
|
||||
// Fill a IPv6 Router Alert option in a Hop-by-Hop Options Header
|
||||
//
|
||||
Options = NetbufAllocSpace (Packet, (UINT32) OptionLen, FALSE);
|
||||
ASSERT (Options != NULL);
|
||||
Status = Ip6FillHopByHop (Options, &OptionLen, IP6_ICMP);
|
||||
if (EFI_ERROR (Status)) {
|
||||
NetbufFree (Packet);
|
||||
Packet = NULL;
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill in MLD message - Done
|
||||
//
|
||||
MldHead = (IP6_MLD_HEAD *) NetbufAllocSpace (Packet, sizeof (IP6_MLD_HEAD), FALSE);
|
||||
ASSERT (MldHead != NULL);
|
||||
ZeroMem (MldHead, sizeof (IP6_MLD_HEAD));
|
||||
MldHead->Head.Type = ICMP_V6_LISTENER_DONE;
|
||||
MldHead->Head.Code = 0;
|
||||
IP6_COPY_ADDRESS (&MldHead->Group, MulticastAddr);
|
||||
|
||||
HeadChecksum = NetblockChecksum ((UINT8 *) MldHead, sizeof (IP6_MLD_HEAD));
|
||||
PseudoChecksum = NetIp6PseudoHeadChecksum (
|
||||
&Head.SourceAddress,
|
||||
&Head.DestinationAddress,
|
||||
IP6_ICMP,
|
||||
sizeof (IP6_MLD_HEAD)
|
||||
);
|
||||
|
||||
MldHead->Head.Checksum = (UINT16) ~NetAddChecksum (HeadChecksum, PseudoChecksum);
|
||||
|
||||
//
|
||||
// Transmit the packet
|
||||
//
|
||||
return Ip6Output (IpSb, NULL, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
Init the MLD data of the IP6 service instance. Configure
|
||||
MNP to receive ALL SYSTEM multicast.
|
||||
|
||||
@param[in] IpSb The IP6 service whose MLD is to be initialized.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES There are not sufficient resourcet to complete the
|
||||
operation.
|
||||
@retval EFI_SUCCESS The MLD module successfully initialized.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6InitMld (
|
||||
IN IP6_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
EFI_IPv6_ADDRESS AllNodes;
|
||||
IP6_MLD_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Join the link-scope all-nodes multicast address (FF02::1).
|
||||
// This address is started in Idle Listener state and never transitions to
|
||||
// another state, and never sends a Report or Done for that address.
|
||||
//
|
||||
|
||||
Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
|
||||
|
||||
Group = Ip6CreateMldEntry (IpSb, &AllNodes, (UINT32) IP6_INFINIT_LIFETIME);
|
||||
if (Group == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = Ip6GetMulticastMac (IpSb->Mnp, &AllNodes, &Group->Mac);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure MNP to receive all-nodes multicast
|
||||
//
|
||||
Status = IpSb->Mnp->Groups (IpSb->Mnp, TRUE, &Group->Mac);
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ERROR:
|
||||
RemoveEntryList (&Group->Link);
|
||||
FreePool (Group);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Add a group address to the array of group addresses.
|
||||
The caller should make sure that no duplicated address
|
||||
existed in the array.
|
||||
|
||||
@param[in, out] IpInstance Points to an IP6_PROTOCOL instance.
|
||||
@param[in] Group The IP6 multicast address to add.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete
|
||||
the operation.
|
||||
@retval EFI_SUCESS The address is added to the group address array.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6CombineGroups (
|
||||
IN OUT IP6_PROTOCOL *IpInstance,
|
||||
IN EFI_IPv6_ADDRESS *Group
|
||||
)
|
||||
{
|
||||
EFI_IPv6_ADDRESS *GroupList;
|
||||
|
||||
NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
|
||||
ASSERT (Group != NULL && IP6_IS_MULTICAST (Group));
|
||||
|
||||
IpInstance->GroupCount++;
|
||||
|
||||
GroupList = AllocatePool (IpInstance->GroupCount * sizeof (EFI_IPv6_ADDRESS));
|
||||
if (GroupList == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (IpInstance->GroupCount > 1) {
|
||||
ASSERT (IpInstance->GroupList != NULL);
|
||||
|
||||
CopyMem (
|
||||
GroupList,
|
||||
IpInstance->GroupList,
|
||||
(IpInstance->GroupCount - 1) * sizeof (EFI_IPv6_ADDRESS)
|
||||
);
|
||||
|
||||
FreePool (IpInstance->GroupList);
|
||||
}
|
||||
|
||||
IP6_COPY_ADDRESS (GroupList + (IpInstance->GroupCount - 1), Group);
|
||||
|
||||
IpInstance->GroupList = GroupList;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove a group address from the array of group addresses.
|
||||
Although the function doesn't assume the byte order of Group,
|
||||
the network byte order is used by the caller.
|
||||
|
||||
@param[in, out] IpInstance Points to an IP6_PROTOCOL instance.
|
||||
@param[in] Group The IP6 multicast address to remove.
|
||||
|
||||
@retval EFI_NOT_FOUND Cannot find the to be removed group address.
|
||||
@retval EFI_SUCCESS The group address was successfully removed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6RemoveGroup (
|
||||
IN OUT IP6_PROTOCOL *IpInstance,
|
||||
IN EFI_IPv6_ADDRESS *Group
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
UINT32 Count;
|
||||
|
||||
Count = IpInstance->GroupCount;
|
||||
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
if (EFI_IP6_EQUAL (IpInstance->GroupList + Index, Group)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Index == Count) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
while (Index < Count - 1) {
|
||||
IP6_COPY_ADDRESS (IpInstance->GroupList + Index, IpInstance->GroupList + Index + 1);
|
||||
Index++;
|
||||
}
|
||||
|
||||
ASSERT (IpInstance->GroupCount > 0);
|
||||
IpInstance->GroupCount--;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Join the multicast group on behalf of this IP6 service binding instance.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
@param[in] Interface Points to an IP6_INTERFACE structure.
|
||||
@param[in] Address The group address 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
|
||||
Ip6JoinGroup (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN IP6_INTERFACE *Interface,
|
||||
IN EFI_IPv6_ADDRESS *Address
|
||||
)
|
||||
{
|
||||
IP6_MLD_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Group = Ip6FindMldEntry (IpSb, Address);
|
||||
if (Group != NULL) {
|
||||
Group->RefCnt++;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Repeat the report once or twcie after short delays [Unsolicited Report Interval] (default:10s)
|
||||
// Simulate this operation as a Multicast-Address-Specific Query was received for that addresss.
|
||||
//
|
||||
Group = Ip6CreateMldEntry (IpSb, Address, IP6_UNSOLICITED_REPORT_INTERVAL);
|
||||
if (Group == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Group->SendByUs = TRUE;
|
||||
|
||||
Status = Ip6GetMulticastMac (IpSb->Mnp, Address, &Group->Mac);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = IpSb->Mnp->Groups (IpSb->Mnp, TRUE, &Group->Mac);
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Send unsolicited report when a node starts listening to a multicast address
|
||||
//
|
||||
Status = Ip6SendMldReport (IpSb, Interface, Address);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ERROR:
|
||||
RemoveEntryList (&Group->Link);
|
||||
FreePool (Group);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Leave the IP6 multicast group.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
@param[in] Address The group address to leave.
|
||||
|
||||
@retval EFI_NOT_FOUND The IP6 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
|
||||
Ip6LeaveGroup (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Address
|
||||
)
|
||||
{
|
||||
IP6_MLD_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Group = Ip6FindMldEntry (IpSb, 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) && (--Group->RefCnt > 0)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// If multiple IP6 group addresses are mapped to the same
|
||||
// multicast MAC address, don't configure the MNP to leave
|
||||
// the MAC.
|
||||
//
|
||||
if (Ip6FindMac (&IpSb->MldCtrl, &Group->Mac) == 1) {
|
||||
Status = IpSb->Mnp->Groups (IpSb->Mnp, FALSE, &Group->Mac);
|
||||
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Send a leave report if we are the last node to report
|
||||
//
|
||||
if (Group->SendByUs) {
|
||||
Status = Ip6SendMldDone (IpSb, Address);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
RemoveEntryList (&Group->Link);
|
||||
FreePool (Group);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Worker function for EfiIp6Groups(). The caller
|
||||
should make sure that the parameters are valid.
|
||||
|
||||
@param[in] IpInstance The IP6 child to change the setting.
|
||||
@param[in] JoinFlag TRUE to join the group, otherwise leave it.
|
||||
@param[in] GroupAddress The target group address. If NULL, leave all
|
||||
the group addresses.
|
||||
|
||||
@retval EFI_ALREADY_STARTED Wants to join the group, but is already a member of it
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate sufficient 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
|
||||
Ip6Groups (
|
||||
IN IP6_PROTOCOL *IpInstance,
|
||||
IN BOOLEAN JoinFlag,
|
||||
IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IP6_SERVICE *IpSb;
|
||||
UINT32 Index;
|
||||
EFI_IPv6_ADDRESS *Group;
|
||||
|
||||
IpSb = IpInstance->Service;
|
||||
|
||||
if (JoinFlag) {
|
||||
ASSERT (GroupAddress != NULL);
|
||||
|
||||
for (Index = 0; Index < IpInstance->GroupCount; Index++) {
|
||||
if (EFI_IP6_EQUAL (IpInstance->GroupList + Index, GroupAddress)) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
}
|
||||
|
||||
Status = Ip6JoinGroup (IpSb, IpInstance->Interface, GroupAddress);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
return Ip6CombineGroups (IpInstance, GroupAddress);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Leave the group. Leave all the groups if GroupAddress is NULL.
|
||||
//
|
||||
for (Index = IpInstance->GroupCount; Index > 0; Index--) {
|
||||
Group = IpInstance->GroupList + (Index - 1);
|
||||
|
||||
if ((GroupAddress == NULL) || EFI_IP6_EQUAL (Group, GroupAddress)) {
|
||||
Status = Ip6LeaveGroup (IpInstance->Service, Group);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Ip6RemoveGroup (IpInstance, Group);
|
||||
|
||||
if (IpInstance->GroupCount == 0) {
|
||||
ASSERT (Index == 1);
|
||||
FreePool (IpInstance->GroupList);
|
||||
IpInstance->GroupList = NULL;
|
||||
}
|
||||
|
||||
if (GroupAddress != NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ((GroupAddress != NULL) ? EFI_NOT_FOUND : EFI_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
Set a random value of the delay timer for the multicast address from the range
|
||||
[0, Maximum Response Delay]. If a timer for any address is already
|
||||
running, it is reset to the new random value only if the requested
|
||||
Maximum Response Delay is less than the remaining value of the
|
||||
running timer. If the Query packet specifies a Maximum Response
|
||||
Delay of zero, each timer is effectively set to zero, and the action
|
||||
specified below for timer expiration is performed immediately.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
@param[in] MaxRespDelay The Maximum Response Delay, in milliseconds.
|
||||
@param[in] MulticastAddr The multicast address.
|
||||
@param[in, out] Group Points to a IP6_MLD_GROUP list entry node.
|
||||
|
||||
@retval EFI_SUCCESS The delay timer is successfully updated or
|
||||
timer expiration is performed immediately.
|
||||
@retval Others Failed to send out MLD report message.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6UpdateDelayTimer (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN UINT16 MaxRespDelay,
|
||||
IN EFI_IPv6_ADDRESS *MulticastAddr,
|
||||
IN OUT IP6_MLD_GROUP *Group
|
||||
)
|
||||
{
|
||||
UINT32 Delay;
|
||||
|
||||
//
|
||||
// If the Query packet specifies a Maximum Response Delay of zero, perform timer
|
||||
// expiration immediately.
|
||||
//
|
||||
if (MaxRespDelay == 0) {
|
||||
Group->DelayTimer = 0;
|
||||
return Ip6SendMldReport (IpSb, NULL, MulticastAddr);
|
||||
}
|
||||
|
||||
Delay = (UINT32) (MaxRespDelay / 1000);
|
||||
|
||||
//
|
||||
// Sets a delay timer to a random value selected from the range [0, Maximum Response Delay]
|
||||
// If a timer is already running, resets it if the request Maximum Response Delay
|
||||
// is less than the remaining value of the running timer.
|
||||
//
|
||||
if (Group->DelayTimer == 0 || Delay < Group->DelayTimer) {
|
||||
Group->DelayTimer = Delay / 4294967295UL * NET_RANDOM (NetRandomInitSeed ());
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Process the Multicast Listener Query message.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the MLD query packet.
|
||||
@param[in] Packet The content of the MLD query packet with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_SUCCESS The MLD query packet processed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid.
|
||||
@retval Others Failed to process the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ProcessMldQuery (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
EFI_IPv6_ADDRESS AllNodes;
|
||||
IP6_MLD_GROUP *Group;
|
||||
IP6_MLD_HEAD MldPacket;
|
||||
LIST_ENTRY *Entry;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
|
||||
//
|
||||
// Check the validity of the packet, generic query or specific query
|
||||
//
|
||||
if (!NetIp6IsUnspecifiedAddr (&Head->SourceAddress) && !NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (Head->HopLimit != 1 || !IP6_IS_MULTICAST (&Head->DestinationAddress)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// The Packet points to MLD report raw data without Hop-By-Hop option.
|
||||
//
|
||||
NetbufCopy (Packet, 0, sizeof (IP6_MLD_HEAD), (UINT8 *) &MldPacket);
|
||||
MldPacket.MaxRespDelay = NTOHS (MldPacket.MaxRespDelay);
|
||||
|
||||
Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
|
||||
if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &AllNodes)) {
|
||||
//
|
||||
// Receives a Multicast-Address-Specific Query, check it firstly
|
||||
//
|
||||
if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &MldPacket.Group)) {
|
||||
goto Exit;
|
||||
}
|
||||
//
|
||||
// The node is not listening but it receives the specific query. Just return.
|
||||
//
|
||||
Group = Ip6FindMldEntry (IpSb, &MldPacket.Group);
|
||||
if (Group == NULL) {
|
||||
Status = EFI_SUCCESS;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = Ip6UpdateDelayTimer (
|
||||
IpSb,
|
||||
MldPacket.MaxRespDelay,
|
||||
&MldPacket.Group,
|
||||
Group
|
||||
);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Receives a General Query, sets a delay timer for each multicast address it is listening
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
|
||||
Status = Ip6UpdateDelayTimer (IpSb, MldPacket.MaxRespDelay, &Group->Address, Group);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
Exit:
|
||||
NetbufFree (Packet);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Process the Multicast Listener Report message.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the MLD report packet.
|
||||
@param[in] Packet The content of the MLD report packet with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_SUCCESS The MLD report packet processed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ProcessMldReport (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP6_MLD_HEAD MldPacket;
|
||||
IP6_MLD_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
|
||||
//
|
||||
// Validate the incoming message, if invalid, drop it.
|
||||
//
|
||||
if (!NetIp6IsUnspecifiedAddr (&Head->SourceAddress) && !NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (Head->HopLimit != 1 || !IP6_IS_MULTICAST (&Head->DestinationAddress)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// The Packet points to MLD report raw data without Hop-By-Hop option.
|
||||
//
|
||||
NetbufCopy (Packet, 0, sizeof (IP6_MLD_HEAD), (UINT8 *) &MldPacket);
|
||||
if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &MldPacket.Group)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Group = Ip6FindMldEntry (IpSb, &MldPacket.Group);
|
||||
if (Group == NULL) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// The report is sent by another node, stop its own timer relates to the multicast address and clear
|
||||
//
|
||||
|
||||
if (!Group->SendByUs) {
|
||||
Group->DelayTimer = 0;
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
Exit:
|
||||
NetbufFree (Packet);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
The heartbeat timer of MLD module. It sends out a solicited MLD report when
|
||||
DelayTimer expires.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6MldTimerTicking (
|
||||
IN IP6_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
IP6_MLD_GROUP *Group;
|
||||
LIST_ENTRY *Entry;
|
||||
|
||||
//
|
||||
// Send solicited report when timer expires
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
|
||||
if ((Group->DelayTimer > 0) && (--Group->DelayTimer == 0)) {
|
||||
Ip6SendMldReport (IpSb, NULL, &Group->Address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
198
NetworkPkg/Ip6Dxe/Ip6Mld.h
Normal file
198
NetworkPkg/Ip6Dxe/Ip6Mld.h
Normal file
@@ -0,0 +1,198 @@
|
||||
/** @file
|
||||
Multicast Listener Discovery support routines.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP6_MLD_H__
|
||||
#define __EFI_IP6_MLD_H__
|
||||
|
||||
#define IP6_UNSOLICITED_REPORT_INTERVAL 10
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IP6_ICMP_HEAD Head;
|
||||
UINT16 MaxRespDelay;
|
||||
UINT16 Reserved;
|
||||
EFI_IPv6_ADDRESS Group;
|
||||
} IP6_MLD_HEAD;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// The status of multicast group. It isn't necessary to maintain
|
||||
// explicit state of host state diagram. A group with finity
|
||||
// DelayTime (less than 0xffffffff) is in "delaying listener" state. otherwise, it is in
|
||||
// "idle listener" state.
|
||||
//
|
||||
typedef struct {
|
||||
LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
EFI_IPv6_ADDRESS Address;
|
||||
UINT32 DelayTimer;
|
||||
BOOLEAN SendByUs;
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
} IP6_MLD_GROUP;
|
||||
|
||||
//
|
||||
// The MLD status. Each IP6 service instance has a MLD_SERVICE_DATA
|
||||
// attached. The Mldv1QuerySeen remember whether the server on this
|
||||
// connected network is v1 or v2.
|
||||
//
|
||||
typedef struct {
|
||||
INTN Mldv1QuerySeen;
|
||||
LIST_ENTRY Groups;
|
||||
} IP6_MLD_SERVICE_DATA;
|
||||
|
||||
/**
|
||||
Search a IP6_MLD_GROUP list entry node from a list array.
|
||||
|
||||
@param[in] IpSb Points to an IP6 service binding instance.
|
||||
@param[in] MulticastAddr The IPv6 multicast address to be searched.
|
||||
|
||||
@return The found IP6_ML_GROUP list entry or NULL.
|
||||
|
||||
**/
|
||||
IP6_MLD_GROUP *
|
||||
Ip6FindMldEntry (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *MulticastAddr
|
||||
);
|
||||
|
||||
/**
|
||||
Init the MLD data of the IP6 service instance, configure
|
||||
MNP to receive ALL SYSTEM multicasts.
|
||||
|
||||
@param[in] IpSb The IP6 service whose MLD is to be initialized.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete the
|
||||
operation.
|
||||
@retval EFI_SUCCESS The MLD module successfully initialized.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6InitMld (
|
||||
IN IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Join the multicast group on behalf of this IP6 service binding instance.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
@param[in] Interface Points to an IP6_INTERFACE structure.
|
||||
@param[in] Address The group address to join.
|
||||
|
||||
@retval EFI_SUCCESS Successfully joined the multicast group.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
|
||||
@retval Others Failed to join the multicast group.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6JoinGroup (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN IP6_INTERFACE *Interface,
|
||||
IN EFI_IPv6_ADDRESS *Address
|
||||
);
|
||||
|
||||
/**
|
||||
Leave the IP6 multicast group.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
@param[in] Address The group address to leave.
|
||||
|
||||
@retval EFI_NOT_FOUND The IP6 service instance isn't in the group.
|
||||
@retval EFI_SUCCESS Successfully left the multicast group.
|
||||
@retval Others Failed to leave the multicast group.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6LeaveGroup (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Address
|
||||
);
|
||||
|
||||
/**
|
||||
Worker function for EfiIp6Groups(). The caller
|
||||
should verify that the parameters are valid.
|
||||
|
||||
@param[in] IpInstance The IP6 child to change the setting.
|
||||
@param[in] JoinFlag TRUE to join the group, otherwise leave it.
|
||||
@param[in] GroupAddress The target group address. If NULL, leave all
|
||||
the group addresses.
|
||||
|
||||
@retval EFI_ALREADY_STARTED Wants to join the group, but is 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 Tried to leave a group of whom it isn't a member.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6Groups (
|
||||
IN IP6_PROTOCOL *IpInstance,
|
||||
IN BOOLEAN JoinFlag,
|
||||
IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Process the Multicast Listener Query message.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the MLD query packet.
|
||||
@param[in] Packet The content of the MLD query packet with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_SUCCESS The MLD query packet processed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid.
|
||||
@retval Others Failed to process the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ProcessMldQuery (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
Process the Multicast Listener Report message.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the MLD report packet.
|
||||
@param[in] Packet The content of the MLD report packet with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_SUCCESS The MLD report packet processed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ProcessMldReport (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
The heartbeat timer of the MLD module. It sends out solicited MLD report when
|
||||
DelayTimer expires.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6MldTimerTicking (
|
||||
IN IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
#endif
|
||||
|
3141
NetworkPkg/Ip6Dxe/Ip6Nd.c
Normal file
3141
NetworkPkg/Ip6Dxe/Ip6Nd.c
Normal file
File diff suppressed because it is too large
Load Diff
750
NetworkPkg/Ip6Dxe/Ip6Nd.h
Normal file
750
NetworkPkg/Ip6Dxe/Ip6Nd.h
Normal file
@@ -0,0 +1,750 @@
|
||||
/** @file
|
||||
Definition of Neighbor Discovery support routines.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP6_ND_H__
|
||||
#define __EFI_IP6_ND_H__
|
||||
|
||||
#define IP6_GET_TICKS(Ms) (((Ms) + IP6_TIMER_INTERVAL_IN_MS - 1) / IP6_TIMER_INTERVAL_IN_MS)
|
||||
|
||||
enum {
|
||||
IP6_INF_ROUTER_LIFETIME = 0xFFFF,
|
||||
|
||||
IP6_MAX_RTR_SOLICITATION_DELAY = 1000, ///< 1000 milliseconds
|
||||
IP6_MAX_RTR_SOLICITATIONS = 3,
|
||||
IP6_RTR_SOLICITATION_INTERVAL = 4000,
|
||||
|
||||
IP6_MIN_RANDOM_FACTOR_SCALED = 1,
|
||||
IP6_MAX_RANDOM_FACTOR_SCALED = 3,
|
||||
IP6_RANDOM_FACTOR_SCALE = 2,
|
||||
|
||||
IP6_MAX_MULTICAST_SOLICIT = 3,
|
||||
IP6_MAX_UNICAST_SOLICIT = 3,
|
||||
IP6_MAX_ANYCAST_DELAY_TIME = 1,
|
||||
IP6_MAX_NEIGHBOR_ADV = 3,
|
||||
IP6_REACHABLE_TIME = 30000,
|
||||
IP6_RETRANS_TIMER = 1000,
|
||||
IP6_DELAY_FIRST_PROBE_TIME = 5000,
|
||||
|
||||
IP6_MIN_LINK_MTU = 1280,
|
||||
IP6_MAX_LINK_MTU = 1500,
|
||||
|
||||
IP6_IS_ROUTER_FLAG = 0x80,
|
||||
IP6_SOLICITED_FLAG = 0x40,
|
||||
IP6_OVERRIDE_FLAG = 0x20,
|
||||
|
||||
IP6_M_ADDR_CONFIG_FLAG = 0x80,
|
||||
IP6_O_CONFIG_FLAG = 0x40,
|
||||
|
||||
IP6_ON_LINK_FLAG = 0x80,
|
||||
IP6_AUTO_CONFIG_FLAG = 0x40,
|
||||
|
||||
IP6_ND_LENGTH = 24,
|
||||
IP6_RA_LENGTH = 16,
|
||||
IP6_REDITECT_LENGTH = 40,
|
||||
IP6_DAD_ENTRY_SIGNATURE = SIGNATURE_32 ('I', 'P', 'D', 'E')
|
||||
};
|
||||
|
||||
typedef
|
||||
VOID
|
||||
(*IP6_ARP_CALLBACK) (
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
typedef struct _IP6_ETHE_ADDR_OPTION {
|
||||
UINT8 Type;
|
||||
UINT8 Length;
|
||||
UINT8 EtherAddr[6];
|
||||
} IP6_ETHER_ADDR_OPTION;
|
||||
|
||||
typedef struct _IP6_MTU_OPTION {
|
||||
UINT8 Type;
|
||||
UINT8 Length;
|
||||
UINT16 Reserved;
|
||||
UINT32 Mtu;
|
||||
} IP6_MTU_OPTION;
|
||||
|
||||
typedef struct _IP6_PREFIX_INFO_OPTION {
|
||||
UINT8 Type;
|
||||
UINT8 Length;
|
||||
UINT8 PrefixLength;
|
||||
UINT8 Reserved1;
|
||||
UINT32 ValidLifetime;
|
||||
UINT32 PreferredLifetime;
|
||||
UINT32 Reserved2;
|
||||
EFI_IPv6_ADDRESS Prefix;
|
||||
} IP6_PREFIX_INFO_OPTION;
|
||||
|
||||
typedef
|
||||
VOID
|
||||
(*IP6_DAD_CALLBACK) (
|
||||
IN BOOLEAN IsDadPassed,
|
||||
IN EFI_IPv6_ADDRESS *TargetAddress,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
typedef struct _IP6_DAD_ENTRY {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY Link;
|
||||
UINT32 MaxTransmit;
|
||||
UINT32 Transmit;
|
||||
UINT32 Receive;
|
||||
UINT32 RetransTick;
|
||||
IP6_ADDRESS_INFO *AddressInfo;
|
||||
EFI_IPv6_ADDRESS Destination;
|
||||
IP6_DAD_CALLBACK Callback;
|
||||
VOID *Context;
|
||||
} IP6_DAD_ENTRY;
|
||||
|
||||
typedef struct _IP6_DELAY_JOIN_LIST {
|
||||
LIST_ENTRY Link;
|
||||
UINT32 DelayTime; ///< in tick per 50 milliseconds
|
||||
IP6_INTERFACE *Interface;
|
||||
IP6_ADDRESS_INFO *AddressInfo;
|
||||
IP6_DAD_CALLBACK DadCallback;
|
||||
VOID *Context;
|
||||
} IP6_DELAY_JOIN_LIST;
|
||||
|
||||
typedef struct _IP6_NEIGHBOR_ENTRY {
|
||||
LIST_ENTRY Link;
|
||||
LIST_ENTRY ArpList;
|
||||
INTN RefCnt;
|
||||
BOOLEAN IsRouter;
|
||||
BOOLEAN ArpFree;
|
||||
BOOLEAN Dynamic;
|
||||
EFI_IPv6_ADDRESS Neighbor;
|
||||
EFI_MAC_ADDRESS LinkAddress;
|
||||
EFI_IP6_NEIGHBOR_STATE State;
|
||||
UINT32 Transmit;
|
||||
UINT32 Ticks;
|
||||
|
||||
LIST_ENTRY Frames;
|
||||
IP6_INTERFACE *Interface;
|
||||
IP6_ARP_CALLBACK CallBack;
|
||||
} IP6_NEIGHBOR_ENTRY;
|
||||
|
||||
typedef struct _IP6_DEFAULT_ROUTER {
|
||||
LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
UINT16 Lifetime;
|
||||
EFI_IPv6_ADDRESS Router;
|
||||
IP6_NEIGHBOR_ENTRY *NeighborCache;
|
||||
} IP6_DEFAULT_ROUTER;
|
||||
|
||||
typedef struct _IP6_PREFIX_LIST_ENTRY {
|
||||
LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
UINT32 ValidLifetime;
|
||||
UINT32 PreferredLifetime;
|
||||
UINT8 PrefixLength;
|
||||
EFI_IPv6_ADDRESS Prefix;
|
||||
} IP6_PREFIX_LIST_ENTRY;
|
||||
|
||||
/**
|
||||
Build a array of EFI_IP6_NEIGHBOR_CACHE to be returned to the caller. The number
|
||||
of EFI_IP6_NEIGHBOR_CACHE is also returned.
|
||||
|
||||
@param[in] IpInstance The pointer to IP6_PROTOCOL instance.
|
||||
@param[out] NeighborCount The number of returned neighbor cache entries.
|
||||
@param[out] NeighborCache The pointer to the array of EFI_IP6_NEIGHBOR_CACHE.
|
||||
|
||||
@retval EFI_SUCCESS The EFI_IP6_NEIGHBOR_CACHE successfully built.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the route table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6BuildEfiNeighborCache (
|
||||
IN IP6_PROTOCOL *IpInstance,
|
||||
OUT UINT32 *NeighborCount,
|
||||
OUT EFI_IP6_NEIGHBOR_CACHE **NeighborCache
|
||||
);
|
||||
|
||||
/**
|
||||
Build a array of EFI_IP6_ADDRESS_INFO to be returned to the caller. The number
|
||||
of prefix entries is also returned.
|
||||
|
||||
@param[in] IpInstance The pointer to IP6_PROTOCOL instance.
|
||||
@param[out] PrefixCount The number of returned prefix entries.
|
||||
@param[out] PrefixTable The pointer to the array of PrefixTable.
|
||||
|
||||
@retval EFI_SUCCESS The prefix table successfully built.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the prefix table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6BuildPrefixTable (
|
||||
IN IP6_PROTOCOL *IpInstance,
|
||||
OUT UINT32 *PrefixCount,
|
||||
OUT EFI_IP6_ADDRESS_INFO **PrefixTable
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate and initialize an IP6 default router entry.
|
||||
|
||||
@param[in] IpSb The pointer to the IP6_SERVICE instance.
|
||||
@param[in] Ip6Address The IPv6 address of the default router.
|
||||
@param[in] RouterLifetime The lifetime associated with the default
|
||||
router, in units of seconds.
|
||||
|
||||
@return NULL if it failed to allocate memory for the default router node.
|
||||
Otherwise, point to the created default router node.
|
||||
|
||||
**/
|
||||
IP6_DEFAULT_ROUTER *
|
||||
Ip6CreateDefaultRouter (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Ip6Address,
|
||||
IN UINT16 RouterLifetime
|
||||
);
|
||||
|
||||
/**
|
||||
Destroy an IP6 default router entry.
|
||||
|
||||
@param[in] IpSb The pointer to the IP6_SERVICE instance.
|
||||
@param[in] DefaultRouter The to be destroyed IP6_DEFAULT_ROUTER.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6DestroyDefaultRouter (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN IP6_DEFAULT_ROUTER *DefaultRouter
|
||||
);
|
||||
|
||||
/**
|
||||
Clean an IP6 default router list.
|
||||
|
||||
@param[in] IpSb The pointer to the IP6_SERVICE instance.
|
||||
@param[in] DefaultRouter The to be destroyed IP6_DEFAULT_ROUTER.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CleanDefaultRouterList (
|
||||
IN IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Search a default router node from an IP6 default router list.
|
||||
|
||||
@param[in] IpSb The pointer to the IP6_SERVICE instance.
|
||||
@param[in] Ip6Address The IPv6 address of the to be searched default router node.
|
||||
|
||||
@return NULL if it failed to find the matching default router node.
|
||||
Otherwise, point to the found default router node.
|
||||
|
||||
**/
|
||||
IP6_DEFAULT_ROUTER *
|
||||
Ip6FindDefaultRouter (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Ip6Address
|
||||
);
|
||||
|
||||
/**
|
||||
The function to be called after DAD (Duplicate Address Detection) is performed.
|
||||
|
||||
@param[in] IsDadPassed If TRUE, the DAD operation succeed. Otherwise, the DAD operation failed.
|
||||
@param[in] IpIf Points to the IP6_INTERFACE.
|
||||
@param[in] DadEntry The DAD entry which already performed DAD.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6OnDADFinished (
|
||||
IN BOOLEAN IsDadPassed,
|
||||
IN IP6_INTERFACE *IpIf,
|
||||
IN IP6_DAD_ENTRY *DadEntry
|
||||
);
|
||||
|
||||
/**
|
||||
Create a DAD (Duplicate Address Detection) entry and queue it to be performed.
|
||||
|
||||
@param[in] IpIf Points to the IP6_INTERFACE.
|
||||
@param[in] AddressInfo The address information which needs DAD performed.
|
||||
@param[in] Callback The callback routine that will be called after DAD
|
||||
is performed. This is an optional parameter that
|
||||
may be NULL.
|
||||
@param[in] Context The opaque parameter for a DAD callback routine.
|
||||
This is an optional parameter that may be NULL.
|
||||
|
||||
@retval EFI_SUCCESS The DAD entry was created and queued.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory to complete the
|
||||
operation.
|
||||
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6InitDADProcess (
|
||||
IN IP6_INTERFACE *IpIf,
|
||||
IN IP6_ADDRESS_INFO *AddressInfo,
|
||||
IN IP6_DAD_CALLBACK Callback OPTIONAL,
|
||||
IN VOID *Context OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Search IP6_DAD_ENTRY from the Duplicate Address Detection List.
|
||||
|
||||
@param[in] IpSb The pointer to the IP6_SERVICE instance.
|
||||
@param[in] Target The address information which needs DAD performed .
|
||||
@param[out] Interface If not NULL, output the IP6 interface that configures
|
||||
the tentative address.
|
||||
|
||||
@return NULL if failed to find the matching DAD entry.
|
||||
Otherwise, point to the found DAD entry.
|
||||
|
||||
**/
|
||||
IP6_DAD_ENTRY *
|
||||
Ip6FindDADEntry (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Target,
|
||||
OUT IP6_INTERFACE **Interface OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate and initialize a IP6 prefix list entry.
|
||||
|
||||
@param[in] IpSb The pointer to IP6_SERVICE instance.
|
||||
@param[in] OnLinkOrAuto If TRUE, the entry is created for the on link prefix list.
|
||||
Otherwise, it is created for the autoconfiguration prefix list.
|
||||
@param[in] ValidLifetime The length of time in seconds that the prefix
|
||||
is valid for the purpose of on-link determination.
|
||||
@param[in] PreferredLifetime The length of time in seconds that addresses
|
||||
generated from the prefix via stateless address
|
||||
autoconfiguration remain preferred.
|
||||
@param[in] PrefixLength The prefix length of the Prefix.
|
||||
@param[in] Prefix The prefix address.
|
||||
|
||||
@return NULL if it failed to allocate memory for the prefix node. Otherwise, point
|
||||
to the created or existing prefix list entry.
|
||||
|
||||
**/
|
||||
IP6_PREFIX_LIST_ENTRY *
|
||||
Ip6CreatePrefixListEntry (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN BOOLEAN OnLinkOrAuto,
|
||||
IN UINT32 ValidLifetime,
|
||||
IN UINT32 PreferredLifetime,
|
||||
IN UINT8 PrefixLength,
|
||||
IN EFI_IPv6_ADDRESS *Prefix
|
||||
);
|
||||
|
||||
/**
|
||||
Destory a IP6 prefix list entry.
|
||||
|
||||
@param[in] IpSb The pointer to IP6_SERVICE instance.
|
||||
@param[in] PrefixEntry The to be destroyed prefix list entry.
|
||||
@param[in] OnLinkOrAuto If TRUE, the entry is removed from on link prefix list.
|
||||
Otherwise remove from autoconfiguration prefix list.
|
||||
@param[in] ImmediateDelete If TRUE, remove the entry directly.
|
||||
Otherwise, check the reference count to see whether
|
||||
it should be removed.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6DestroyPrefixListEntry (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN IP6_PREFIX_LIST_ENTRY *PrefixEntry,
|
||||
IN BOOLEAN OnLinkOrAuto,
|
||||
IN BOOLEAN ImmediateDelete
|
||||
);
|
||||
|
||||
/**
|
||||
Search the list array to find an IP6 prefix list entry.
|
||||
|
||||
@param[in] IpSb The pointer to IP6_SERVICE instance.
|
||||
@param[in] OnLinkOrAuto If TRUE, the search the link prefix list,
|
||||
Otherwise search the autoconfiguration prefix list.
|
||||
@param[in] PrefixLength The prefix length of the Prefix
|
||||
@param[in] Prefix The prefix address.
|
||||
|
||||
@return NULL if cannot find the IP6 prefix list entry. Otherwise, return the
|
||||
pointer to the IP6 prefix list entry.
|
||||
|
||||
**/
|
||||
IP6_PREFIX_LIST_ENTRY *
|
||||
Ip6FindPrefixListEntry (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN BOOLEAN OnLinkOrAuto,
|
||||
IN UINT8 PrefixLength,
|
||||
IN EFI_IPv6_ADDRESS *Prefix
|
||||
);
|
||||
|
||||
/**
|
||||
Release the resource in prefix list table, and destroy the list entry and
|
||||
corresponding addresses or route entries.
|
||||
|
||||
@param[in] IpSb The pointer to the IP6_SERVICE instance.
|
||||
@param[in] ListHead The list entry head of the prefix list table.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CleanPrefixListTable (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN LIST_ENTRY *ListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate and initialize an IP6 neighbor cache entry.
|
||||
|
||||
@param[in] IpSb The pointer to the IP6_SERVICE instance.
|
||||
@param[in] CallBack The callback function to be called when
|
||||
address resolution is finished.
|
||||
@param[in] Ip6Address Points to the IPv6 address of the neighbor.
|
||||
@param[in] LinkAddress Points to the MAC address of the neighbor.
|
||||
Ignored if NULL.
|
||||
|
||||
@return NULL if failed to allocate memory for the neighbor cache entry.
|
||||
Otherwise, point to the created neighbor cache entry.
|
||||
|
||||
**/
|
||||
IP6_NEIGHBOR_ENTRY *
|
||||
Ip6CreateNeighborEntry (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN IP6_ARP_CALLBACK CallBack,
|
||||
IN EFI_IPv6_ADDRESS *Ip6Address,
|
||||
IN EFI_MAC_ADDRESS *LinkAddress OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Search a IP6 neighbor cache entry.
|
||||
|
||||
@param[in] IpSb The pointer to the IP6_SERVICE instance.
|
||||
@param[in] Ip6Address Points to the IPv6 address of the neighbor.
|
||||
|
||||
@return NULL if it failed to find the matching neighbor cache entry.
|
||||
Otherwise, point to the found neighbor cache entry.
|
||||
|
||||
**/
|
||||
IP6_NEIGHBOR_ENTRY *
|
||||
Ip6FindNeighborEntry (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Ip6Address
|
||||
);
|
||||
|
||||
/**
|
||||
Free a IP6 neighbor cache entry and remove all the frames on the address
|
||||
resolution queue that pass the FrameToCancel. That is, either FrameToCancel
|
||||
is NULL, or it returns true for the frame.
|
||||
|
||||
@param[in] IpSb The pointer to the IP6_SERVICE instance.
|
||||
@param[in] NeighborCache The to be free neighbor cache entry.
|
||||
@param[in] SendIcmpError If TRUE, send out ICMP error.
|
||||
@param[in] FullFree If TRUE, remove the neighbor cache entry.
|
||||
Otherwise remove the pending frames.
|
||||
@param[in] IoStatus The status returned to the cancelled frames'
|
||||
callback function.
|
||||
@param[in] FrameToCancel Function to select which frame to cancel.
|
||||
This is an optional parameter that may be NULL.
|
||||
@param[in] Context Opaque parameter to the FrameToCancel.
|
||||
Ignored if FrameToCancel is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The input parameter is invalid.
|
||||
@retval EFI_SUCCESS The operation finished successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6FreeNeighborEntry (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN IP6_NEIGHBOR_ENTRY *NeighborCache,
|
||||
IN BOOLEAN SendIcmpError,
|
||||
IN BOOLEAN FullFree,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
|
||||
IN VOID *Context OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Add Neighbor cache entries. It is a work function for EfiIp6Neighbors().
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
@param[in] TargetIp6Address Pointer to Target IPv6 address.
|
||||
@param[in] TargetLinkAddress Pointer to link-layer address of the target. Ignored if NULL.
|
||||
@param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor
|
||||
cache. It will be deleted after Timeout. A value of zero means that
|
||||
the entry is permanent. A non-zero value means that the entry is
|
||||
dynamic.
|
||||
@param[in] Override If TRUE, the cached link-layer address of the matching entry will
|
||||
be overridden and updated; if FALSE, and if a
|
||||
corresponding cache entry already existed, EFI_ACCESS_DENIED
|
||||
will be returned.
|
||||
|
||||
@retval EFI_SUCCESS The neighbor cache entry has been added.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not add the entry to the neighbor cache
|
||||
due to insufficient resources.
|
||||
@retval EFI_NOT_FOUND TargetLinkAddress is NULL.
|
||||
@retval EFI_ACCESS_DENIED The to-be-added entry is already defined in the neighbor cache,
|
||||
and that entry is tagged as un-overridden (when DeleteFlag
|
||||
is FALSE).
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6AddNeighbor (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *TargetIp6Address,
|
||||
IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
|
||||
IN UINT32 Timeout,
|
||||
IN BOOLEAN Override
|
||||
);
|
||||
|
||||
/**
|
||||
Delete or update Neighbor cache entries. It is a work function for EfiIp6Neighbors().
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
@param[in] TargetIp6Address Pointer to Target IPv6 address.
|
||||
@param[in] TargetLinkAddress Pointer to link-layer address of the target. Ignored if NULL.
|
||||
@param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor
|
||||
cache. It will be deleted after Timeout. A value of zero means that
|
||||
the entry is permanent. A non-zero value means that the entry is
|
||||
dynamic.
|
||||
@param[in] Override If TRUE, the cached link-layer address of the matching entry will
|
||||
be overridden and updated; if FALSE, and if a
|
||||
corresponding cache entry already existed, EFI_ACCESS_DENIED
|
||||
will be returned.
|
||||
|
||||
@retval EFI_SUCCESS The neighbor cache entry has been updated or deleted.
|
||||
@retval EFI_NOT_FOUND This entry is not in the neighbor cache.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6DelNeighbor (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *TargetIp6Address,
|
||||
IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
|
||||
IN UINT32 Timeout,
|
||||
IN BOOLEAN Override
|
||||
);
|
||||
|
||||
/**
|
||||
Process the Neighbor Solicitation message. The message may be sent for Duplicate
|
||||
Address Detection or Address Resolution.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the message.
|
||||
@param[in] Packet The content of the message with IP head removed.
|
||||
|
||||
@retval EFI_SUCCESS The packet processed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid.
|
||||
@retval EFI_ICMP_ERROR The packet indicates that DAD is failed.
|
||||
@retval Others Failed to process the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ProcessNeighborSolicit (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
Process the Neighbor Advertisement message.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the message.
|
||||
@param[in] Packet The content of the message with IP head removed.
|
||||
|
||||
@retval EFI_SUCCESS The packet processed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid.
|
||||
@retval EFI_ICMP_ERROR The packet indicates that DAD is failed.
|
||||
@retval Others Failed to process the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ProcessNeighborAdvertise (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
Process the Router Advertisement message according to RFC4861.
|
||||
|
||||
@param[in] IpSb The IP service that received the packet.
|
||||
@param[in] Head The IP head of the message.
|
||||
@param[in] Packet The content of the message with the IP head removed.
|
||||
|
||||
@retval EFI_SUCCESS The packet processed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the operation.
|
||||
@retval Others Failed to process the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ProcessRouterAdvertise (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
Process the ICMPv6 redirect message. Find the instance, then update
|
||||
its route cache.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance that received
|
||||
the packet.
|
||||
@param[in] Head The IP head of the received ICMPv6 packet.
|
||||
@param[in] Packet The content of the ICMPv6 redirect packet with
|
||||
the IP head removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Insuffcient resources to complete the
|
||||
operation.
|
||||
@retval EFI_SUCCESS Successfully updated the route caches.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6ProcessRedirect (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
Generate router solicit message and send it out to Destination Address or
|
||||
All Router Link Local scope multicast address.
|
||||
|
||||
@param[in] IpSb The IP service to send the packet.
|
||||
@param[in] Interface If not NULL, points to the IP6 interface to send
|
||||
the packet.
|
||||
@param[in] SourceAddress If not NULL, the source address of the message.
|
||||
@param[in] DestinationAddress If not NULL, the destination address of the message.
|
||||
@param[in] SourceLinkAddress If not NULL, the MAC address of the source.
|
||||
A source link-layer address option will be appended
|
||||
to the message.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the operation.
|
||||
@retval EFI_SUCCESS The router solicit message was successfully sent.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SendRouterSolicit (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN IP6_INTERFACE *Interface OPTIONAL,
|
||||
IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
|
||||
IN EFI_IPv6_ADDRESS *DestinationAddress OPTIONAL,
|
||||
IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Generate the Neighbor Solicitation message and send it to the Destination Address.
|
||||
|
||||
@param[in] IpSb The IP service to send the packet
|
||||
@param[in] SourceAddress The source address of the message.
|
||||
@param[in] DestinationAddress The destination address of the message.
|
||||
@param[in] TargetIp6Address The IP address of the target of the solicitation.
|
||||
It must not be a multicast address.
|
||||
@param[in] SourceLinkAddress The MAC address for the sender. If not NULL,
|
||||
a source link-layer address option will be appended
|
||||
to the message.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the
|
||||
operation.
|
||||
@retval EFI_SUCCESS The Neighbor Advertise message was successfully sent.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SendNeighborSolicit (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *SourceAddress,
|
||||
IN EFI_IPv6_ADDRESS *DestinationAddress,
|
||||
IN EFI_IPv6_ADDRESS *TargetIp6Address,
|
||||
IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Set the interface's address. This will trigger the DAD process for the
|
||||
address to set. To set an already set address, the lifetimes wil be
|
||||
updated to the new value passed in.
|
||||
|
||||
@param[in] Interface The interface to set the address.
|
||||
@param[in] Ip6Addr The interface's to be assigned IPv6 address.
|
||||
@param[in] IsAnycast If TRUE, the unicast IPv6 address is anycast.
|
||||
Otherwise, it is not anycast.
|
||||
@param[in] PrefixLength The prefix length of the Ip6Addr.
|
||||
@param[in] ValidLifetime The valid lifetime for this address.
|
||||
@param[in] PreferredLifetime The preferred lifetime for this address.
|
||||
@param[in] DadCallback The caller's callback to trigger when DAD finishes.
|
||||
This is an optional parameter that may be NULL.
|
||||
@param[in] Context The context that will be passed to DadCallback.
|
||||
This is an optional parameter that may be NULL.
|
||||
|
||||
@retval EFI_SUCCESS The interface is scheduled to be configured with
|
||||
the specified address.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to set the interface's address due to
|
||||
lack of resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SetAddress (
|
||||
IN IP6_INTERFACE *Interface,
|
||||
IN EFI_IPv6_ADDRESS *Ip6Addr,
|
||||
IN BOOLEAN IsAnycast,
|
||||
IN UINT8 PrefixLength,
|
||||
IN UINT32 ValidLifetime,
|
||||
IN UINT32 PreferredLifetime,
|
||||
IN IP6_DAD_CALLBACK DadCallback OPTIONAL,
|
||||
IN VOID *Context OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
The heartbeat timer of ND module in IP6_TIMER_INTERVAL_IN_MS milliseconds.
|
||||
This time routine handles DAD module and neighbor state transition.
|
||||
It is also responsible for sending out router solicitations.
|
||||
|
||||
@param[in] Event The IP6 service instance's heartbeat timer.
|
||||
@param[in] Context The IP6 service instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip6NdFasterTimerTicking (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
The heartbeat timer of ND module in 1 second. This time routine handles following
|
||||
things: 1) maitain default router list; 2) maintain prefix options;
|
||||
3) maintain route caches.
|
||||
|
||||
@param[in] IpSb The IP6 service binding instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6NdTimerTicking (
|
||||
IN IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
/**
|
||||
Callback function when address resolution is finished. It will cancel
|
||||
all the queued frames if the address resolution failed, or transmit them
|
||||
if the request succeeded.
|
||||
|
||||
@param[in] Context The context of the callback, a pointer to IP6_NEIGHBOR_ENTRY.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6OnArpResolved (
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Update the ReachableTime in IP6 service binding instance data, in milliseconds.
|
||||
|
||||
@param[in, out] IpSb Points to the IP6_SERVICE.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6UpdateReachableTime (
|
||||
IN OUT IP6_SERVICE *IpSb
|
||||
);
|
||||
|
||||
#endif
|
70
NetworkPkg/Ip6Dxe/Ip6NvData.h
Normal file
70
NetworkPkg/Ip6Dxe/Ip6NvData.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/** @file
|
||||
NVData structure used by the IP6 configuration component.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _IP6_NV_DATA_H_
|
||||
#define _IP6_NV_DATA_H_
|
||||
|
||||
#define IP6_CONFIG_NVDATA_GUID \
|
||||
{ \
|
||||
0x2eea107, 0x98db, 0x400e, { 0x98, 0x30, 0x46, 0xa, 0x15, 0x42, 0xd7, 0x99 } \
|
||||
}
|
||||
|
||||
#define FORMID_MAIN_FORM 1
|
||||
#define FORMID_MANUAL_CONFIG_FORM 2
|
||||
|
||||
#define IP6_POLICY_AUTO 0
|
||||
#define IP6_POLICY_MANUAL 1
|
||||
#define DAD_MAX_TRANSMIT_COUNT 10
|
||||
|
||||
#define KEY_INTERFACE_ID 0x101
|
||||
#define KEY_MANUAL_ADDRESS 0x102
|
||||
#define KEY_GATEWAY_ADDRESS 0x103
|
||||
#define KEY_DNS_ADDRESS 0x104
|
||||
#define KEY_SAVE_CHANGES 0x105
|
||||
#define KEY_SAVE_CONFIG_CHANGES 0x106
|
||||
#define KEY_IGNORE_CONFIG_CHANGES 0x107
|
||||
|
||||
#define HOST_ADDRESS_LABEL 0x9000
|
||||
#define ROUTE_TABLE_LABEL 0xa000
|
||||
#define GATEWAY_ADDRESS_LABEL 0xb000
|
||||
#define DNS_ADDRESS_LABEL 0xc000
|
||||
#define LABEL_END 0xffff
|
||||
|
||||
#define INTERFACE_ID_STR_MIN_SIZE 1
|
||||
#define INTERFACE_ID_STR_MAX_SIZE 23
|
||||
#define INTERFACE_ID_STR_STORAGE 24
|
||||
#define IP6_STR_MAX_SIZE 40
|
||||
#define ADDRESS_STR_MIN_SIZE 2
|
||||
#define ADDRESS_STR_MAX_SIZE 255
|
||||
|
||||
///
|
||||
/// IP6_CONFIG_IFR_NVDATA contains the IP6 configure
|
||||
/// parameters for that NIC.
|
||||
///
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UINT8 IfType; ///< interface type
|
||||
UINT8 Padding[3];
|
||||
UINT32 Policy; ///< manual or automatic
|
||||
UINT32 DadTransmitCount; ///< dad transmits count
|
||||
CHAR16 InterfaceId[INTERFACE_ID_STR_STORAGE]; ///< alternative interface id
|
||||
CHAR16 ManualAddress[ADDRESS_STR_MAX_SIZE]; ///< IP addresses
|
||||
CHAR16 GatewayAddress[ADDRESS_STR_MAX_SIZE]; ///< Gateway address
|
||||
CHAR16 DnsAddress[ADDRESS_STR_MAX_SIZE]; ///< DNS server address
|
||||
} IP6_CONFIG_IFR_NVDATA;
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
|
758
NetworkPkg/Ip6Dxe/Ip6Option.c
Normal file
758
NetworkPkg/Ip6Dxe/Ip6Option.c
Normal file
@@ -0,0 +1,758 @@
|
||||
/** @file
|
||||
IP6 option support functions and routines.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip6Impl.h"
|
||||
|
||||
/**
|
||||
Validate the IP6 option format for both the packets we received
|
||||
and that we will transmit. It will compute the ICMPv6 error message fields
|
||||
if the option is malformated.
|
||||
|
||||
@param[in] IpSb The IP6 service data.
|
||||
@param[in] Packet The to be validated packet.
|
||||
@param[in] Option The first byte of the option.
|
||||
@param[in] OptionLen The length of the whole option.
|
||||
@param[in] Pointer Identifies the octet offset within
|
||||
the invoking packet where the error was detected.
|
||||
|
||||
|
||||
@retval TRUE The option is properly formatted.
|
||||
@retval FALSE The option is malformated.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsOptionValid (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN NET_BUF *Packet,
|
||||
IN UINT8 *Option,
|
||||
IN UINT8 OptionLen,
|
||||
IN UINT32 Pointer
|
||||
)
|
||||
{
|
||||
UINT8 Offset;
|
||||
UINT8 OptionType;
|
||||
|
||||
Offset = 0;
|
||||
|
||||
while (Offset < OptionLen) {
|
||||
OptionType = *(Option + Offset);
|
||||
|
||||
switch (OptionType) {
|
||||
case Ip6OptionPad1:
|
||||
//
|
||||
// It is a Pad1 option
|
||||
//
|
||||
Offset++;
|
||||
break;
|
||||
case Ip6OptionPadN:
|
||||
//
|
||||
// It is a PadN option
|
||||
//
|
||||
Offset = (UINT8) (Offset + *(Option + Offset + 1) + 2);
|
||||
break;
|
||||
case Ip6OptionRouterAlert:
|
||||
//
|
||||
// It is a Router Alert Option
|
||||
//
|
||||
Offset += 4;
|
||||
break;
|
||||
default:
|
||||
//
|
||||
// The highest-order two bits specify the action must be taken if
|
||||
// the processing IPv6 node does not recognize the option type.
|
||||
//
|
||||
switch (OptionType & Ip6OptionMask) {
|
||||
case Ip6OptionSkip:
|
||||
Offset = (UINT8) (Offset + *(Option + Offset + 1));
|
||||
break;
|
||||
case Ip6OptionDiscard:
|
||||
return FALSE;
|
||||
case Ip6OptionParameterProblem:
|
||||
Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER);
|
||||
Ip6SendIcmpError (
|
||||
IpSb,
|
||||
Packet,
|
||||
NULL,
|
||||
&Packet->Ip.Ip6->SourceAddress,
|
||||
ICMP_V6_PARAMETER_PROBLEM,
|
||||
2,
|
||||
&Pointer
|
||||
);
|
||||
return FALSE;
|
||||
case Ip6OptionMask:
|
||||
if (!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
|
||||
Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER);
|
||||
Ip6SendIcmpError (
|
||||
IpSb,
|
||||
Packet,
|
||||
NULL,
|
||||
&Packet->Ip.Ip6->SourceAddress,
|
||||
ICMP_V6_PARAMETER_PROBLEM,
|
||||
2,
|
||||
&Pointer
|
||||
);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Validate the IP6 option format for both the packets we received
|
||||
and that we will transmit. It supports the defined options in Neighbor
|
||||
Discovery messages.
|
||||
|
||||
@param[in] Option The first byte of the option.
|
||||
@param[in] OptionLen The length of the whole option.
|
||||
|
||||
@retval TRUE The option is properly formatted.
|
||||
@retval FALSE The option is malformated.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsNDOptionValid (
|
||||
IN UINT8 *Option,
|
||||
IN UINT16 OptionLen
|
||||
)
|
||||
{
|
||||
UINT16 Offset;
|
||||
UINT8 OptionType;
|
||||
UINT16 Length;
|
||||
|
||||
Offset = 0;
|
||||
|
||||
while (Offset < OptionLen) {
|
||||
OptionType = *(Option + Offset);
|
||||
Length = (UINT16) (*(Option + Offset + 1) * 8);
|
||||
|
||||
switch (OptionType) {
|
||||
case Ip6OptionPrefixInfo:
|
||||
if (Length != 32) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Ip6OptionMtu:
|
||||
if (Length != 8) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
//
|
||||
// Check the length of Ip6OptionEtherSource, Ip6OptionEtherTarget, and
|
||||
// Ip6OptionRedirected here. For unrecognized options, silently ignore
|
||||
// and continue processsing the message.
|
||||
//
|
||||
if (Length == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Offset = (UINT16) (Offset + Length);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Validate whether the NextHeader is a known valid protocol or one of the user configured
|
||||
protocols from the upper layer.
|
||||
|
||||
@param[in] IpSb The IP6 service instance.
|
||||
@param[in] NextHeader The next header field.
|
||||
|
||||
@retval TRUE The NextHeader is a known valid protocol or user configured.
|
||||
@retval FALSE The NextHeader is not a known valid protocol.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsValidProtocol (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN UINT8 NextHeader
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP6_PROTOCOL *IpInstance;
|
||||
|
||||
if (NextHeader == EFI_IP_PROTO_TCP ||
|
||||
NextHeader == EFI_IP_PROTO_UDP ||
|
||||
NextHeader == IP6_ICMP ||
|
||||
NextHeader == IP6_ESP
|
||||
) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (IpSb == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (IpSb->Signature != IP6_SERVICE_SIGNATURE) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Children) {
|
||||
IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);
|
||||
if (IpInstance->State == IP6_STATE_CONFIGED) {
|
||||
if (IpInstance->ConfigData.DefaultProtocol == NextHeader) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Validate the IP6 extension header format for both the packets we received
|
||||
and that we will transmit. It will compute the ICMPv6 error message fields
|
||||
if the option is mal-formated.
|
||||
|
||||
@param[in] IpSb The IP6 service instance. This is an optional parameter.
|
||||
@param[in] Packet The data of the packet. Ignored if NULL.
|
||||
@param[in] NextHeader The next header field in IPv6 basic header.
|
||||
@param[in] ExtHdrs The first byte of the option.
|
||||
@param[in] ExtHdrsLen The length of the whole option.
|
||||
@param[in] Rcvd The option is from the packet we received if TRUE,
|
||||
otherwise, the option we want to transmit.
|
||||
@param[out] FormerHeader The offset of NextHeader which points to Fragment
|
||||
Header when we received, of the ExtHdrs.
|
||||
Ignored if we transmit.
|
||||
@param[out] LastHeader The pointer of NextHeader of the last extension
|
||||
header processed by IP6.
|
||||
@param[out] RealExtsLen The length of extension headers processed by IP6 layer.
|
||||
This is an optional parameter that may be NULL.
|
||||
@param[out] UnFragmentLen The length of unfragmented length of extension headers.
|
||||
This is an optional parameter that may be NULL.
|
||||
@param[out] Fragmented Indicate whether the packet is fragmented.
|
||||
This is an optional parameter that may be NULL.
|
||||
|
||||
@retval TRUE The option is properly formated.
|
||||
@retval FALSE The option is malformated.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsExtsValid (
|
||||
IN IP6_SERVICE *IpSb OPTIONAL,
|
||||
IN NET_BUF *Packet OPTIONAL,
|
||||
IN UINT8 *NextHeader,
|
||||
IN UINT8 *ExtHdrs,
|
||||
IN UINT32 ExtHdrsLen,
|
||||
IN BOOLEAN Rcvd,
|
||||
OUT UINT32 *FormerHeader OPTIONAL,
|
||||
OUT UINT8 **LastHeader,
|
||||
OUT UINT32 *RealExtsLen OPTIONAL,
|
||||
OUT UINT32 *UnFragmentLen OPTIONAL,
|
||||
OUT BOOLEAN *Fragmented OPTIONAL
|
||||
)
|
||||
{
|
||||
UINT32 Pointer;
|
||||
UINT32 Offset;
|
||||
UINT8 *Option;
|
||||
UINT8 OptionLen;
|
||||
BOOLEAN Flag;
|
||||
UINT8 CountD;
|
||||
UINT8 CountA;
|
||||
IP6_FRAGMENT_HEADER *FragmentHead;
|
||||
UINT16 FragmentOffset;
|
||||
IP6_ROUTING_HEADER *RoutingHead;
|
||||
|
||||
if (RealExtsLen != NULL) {
|
||||
*RealExtsLen = 0;
|
||||
}
|
||||
|
||||
if (UnFragmentLen != NULL) {
|
||||
*UnFragmentLen = 0;
|
||||
}
|
||||
|
||||
if (Fragmented != NULL) {
|
||||
*Fragmented = FALSE;
|
||||
}
|
||||
|
||||
*LastHeader = NextHeader;
|
||||
|
||||
if (ExtHdrs == NULL && ExtHdrsLen == 0) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((ExtHdrs == NULL && ExtHdrsLen != 0) || (ExtHdrs != NULL && ExtHdrsLen == 0)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Pointer = 0;
|
||||
Offset = 0;
|
||||
Flag = FALSE;
|
||||
CountD = 0;
|
||||
CountA = 0;
|
||||
|
||||
while (Offset <= ExtHdrsLen) {
|
||||
|
||||
switch (*NextHeader) {
|
||||
case IP6_HOP_BY_HOP:
|
||||
if (Offset != 0) {
|
||||
if (!Rcvd) {
|
||||
return FALSE;
|
||||
}
|
||||
//
|
||||
// Hop-by-Hop Options header is restricted to appear immediately after an IPv6 header only.
|
||||
// If not, generate a ICMP parameter problem message with code value of 1.
|
||||
//
|
||||
if (Pointer == 0) {
|
||||
Pointer = sizeof (EFI_IP6_HEADER);
|
||||
} else {
|
||||
Pointer = Offset + sizeof (EFI_IP6_HEADER);
|
||||
}
|
||||
|
||||
if ((IpSb != NULL) && (Packet != NULL) &&
|
||||
!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
|
||||
Ip6SendIcmpError (
|
||||
IpSb,
|
||||
Packet,
|
||||
NULL,
|
||||
&Packet->Ip.Ip6->SourceAddress,
|
||||
ICMP_V6_PARAMETER_PROBLEM,
|
||||
1,
|
||||
&Pointer
|
||||
);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Flag = TRUE;
|
||||
|
||||
//
|
||||
// Fall through
|
||||
//
|
||||
case IP6_DESTINATION:
|
||||
if (*NextHeader == IP6_DESTINATION) {
|
||||
CountD++;
|
||||
}
|
||||
|
||||
if (CountD > 2) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NextHeader = ExtHdrs + Offset;
|
||||
Pointer = Offset;
|
||||
|
||||
Offset++;
|
||||
Option = ExtHdrs + Offset;
|
||||
OptionLen = (UINT8) ((*Option + 1) * 8 - 2);
|
||||
Option++;
|
||||
Offset++;
|
||||
|
||||
if (IpSb != NULL && Packet != NULL && !Ip6IsOptionValid (IpSb, Packet, Option, OptionLen, Offset)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Offset = Offset + OptionLen;
|
||||
|
||||
if (Flag) {
|
||||
if (UnFragmentLen != NULL) {
|
||||
*UnFragmentLen = Offset;
|
||||
}
|
||||
|
||||
Flag = FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IP6_ROUTING:
|
||||
NextHeader = ExtHdrs + Offset;
|
||||
RoutingHead = (IP6_ROUTING_HEADER *) NextHeader;
|
||||
|
||||
//
|
||||
// Type 0 routing header is defined in RFC2460 and deprecated in RFC5095.
|
||||
// Thus all routing types are processed as unrecognized.
|
||||
//
|
||||
if (RoutingHead->SegmentsLeft == 0) {
|
||||
//
|
||||
// Ignore the routing header and proceed to process the next header.
|
||||
//
|
||||
Offset = Offset + (RoutingHead->HeaderLen + 1) * 8;
|
||||
|
||||
if (UnFragmentLen != NULL) {
|
||||
*UnFragmentLen = Offset;
|
||||
}
|
||||
|
||||
} else {
|
||||
//
|
||||
// Discard the packet and send an ICMP Parameter Problem, Code 0, message
|
||||
// to the packet's source address, pointing to the unrecognized routing
|
||||
// type.
|
||||
//
|
||||
Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER);
|
||||
if ((IpSb != NULL) && (Packet != NULL) &&
|
||||
!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
|
||||
Ip6SendIcmpError (
|
||||
IpSb,
|
||||
Packet,
|
||||
NULL,
|
||||
&Packet->Ip.Ip6->SourceAddress,
|
||||
ICMP_V6_PARAMETER_PROBLEM,
|
||||
0,
|
||||
&Pointer
|
||||
);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IP6_FRAGMENT:
|
||||
|
||||
//
|
||||
// RFC2402, AH header should after fragment header.
|
||||
//
|
||||
if (CountA > 1) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// RFC2460, ICMP Parameter Problem message with code 0 should be sent
|
||||
// if the length of a fragment is not a multiple of 8 octects and the M
|
||||
// flag of that fragment is 1, pointing to the Payload length field of the
|
||||
// fragment packet.
|
||||
//
|
||||
if (IpSb != NULL && Packet != NULL && (ExtHdrsLen % 8) != 0) {
|
||||
//
|
||||
// Check whether it is the last fragment.
|
||||
//
|
||||
FragmentHead = (IP6_FRAGMENT_HEADER *) (ExtHdrs + Offset);
|
||||
if (FragmentHead == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FragmentOffset = NTOHS (FragmentHead->FragmentOffset);
|
||||
|
||||
if (((FragmentOffset & 0x1) == 0x1) &&
|
||||
!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
|
||||
Pointer = sizeof (UINT32);
|
||||
Ip6SendIcmpError (
|
||||
IpSb,
|
||||
Packet,
|
||||
NULL,
|
||||
&Packet->Ip.Ip6->SourceAddress,
|
||||
ICMP_V6_PARAMETER_PROBLEM,
|
||||
0,
|
||||
&Pointer
|
||||
);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (Fragmented != NULL) {
|
||||
*Fragmented = TRUE;
|
||||
}
|
||||
|
||||
if (Rcvd && FormerHeader != NULL) {
|
||||
*FormerHeader = (UINT32) (NextHeader - ExtHdrs);
|
||||
}
|
||||
|
||||
NextHeader = ExtHdrs + Offset;
|
||||
Offset = Offset + 8;
|
||||
break;
|
||||
|
||||
case IP6_AH:
|
||||
if (++CountA > 1) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Option = ExtHdrs + Offset;
|
||||
NextHeader = Option;
|
||||
Option++;
|
||||
//
|
||||
// RFC2402, Payload length is specified in 32-bit words, minus "2".
|
||||
//
|
||||
OptionLen = (UINT8) ((*Option + 2) * 4);
|
||||
Offset = Offset + OptionLen;
|
||||
break;
|
||||
|
||||
case IP6_NO_NEXT_HEADER:
|
||||
*LastHeader = NextHeader;
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (Ip6IsValidProtocol (IpSb, *NextHeader)) {
|
||||
|
||||
*LastHeader = NextHeader;
|
||||
|
||||
if (RealExtsLen != NULL) {
|
||||
*RealExtsLen = Offset;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// The Next Header value is unrecognized by the node, discard the packet and
|
||||
// send an ICMP parameter problem message with code value of 1.
|
||||
//
|
||||
if (Offset == 0) {
|
||||
//
|
||||
// The Next Header directly follows IPv6 basic header.
|
||||
//
|
||||
Pointer = 6;
|
||||
} else {
|
||||
if (Pointer == 0) {
|
||||
Pointer = sizeof (EFI_IP6_HEADER);
|
||||
} else {
|
||||
Pointer = Offset + sizeof (EFI_IP6_HEADER);
|
||||
}
|
||||
}
|
||||
|
||||
if ((IpSb != NULL) && (Packet != NULL) &&
|
||||
!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
|
||||
Ip6SendIcmpError (
|
||||
IpSb,
|
||||
Packet,
|
||||
NULL,
|
||||
&Packet->Ip.Ip6->SourceAddress,
|
||||
ICMP_V6_PARAMETER_PROBLEM,
|
||||
1,
|
||||
&Pointer
|
||||
);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
*LastHeader = NextHeader;
|
||||
|
||||
if (RealExtsLen != NULL) {
|
||||
*RealExtsLen = Offset;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Generate an IPv6 router alert option in network order and output it through Buffer.
|
||||
|
||||
@param[out] Buffer Points to a buffer to record the generated option.
|
||||
@param[in, out] BufferLen The length of Buffer, in bytes.
|
||||
@param[in] NextHeader The 8-bit selector indicates the type of header
|
||||
immediately following the Hop-by-Hop Options header.
|
||||
|
||||
@retval EFI_BUFFER_TOO_SMALL The Buffer is too small to contain the generated
|
||||
option. BufferLen is updated for the required size.
|
||||
|
||||
@retval EFI_SUCCESS The option is generated and filled in to Buffer.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6FillHopByHop (
|
||||
OUT UINT8 *Buffer,
|
||||
IN OUT UINTN *BufferLen,
|
||||
IN UINT8 NextHeader
|
||||
)
|
||||
{
|
||||
UINT8 BufferArray[8];
|
||||
|
||||
if (*BufferLen < 8) {
|
||||
*BufferLen = 8;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
//
|
||||
// Form the Hop-By-Hop option in network order.
|
||||
// NextHeader (1 octet) + HdrExtLen (1 octet) + RouterAlertOption(4 octets) + PadN
|
||||
// The Hdr Ext Len is the length in 8-octet units, and does not including the first 8 octets.
|
||||
//
|
||||
ZeroMem (BufferArray, sizeof (BufferArray));
|
||||
BufferArray[0] = NextHeader;
|
||||
BufferArray[2] = 0x5;
|
||||
BufferArray[3] = 0x2;
|
||||
BufferArray[6] = 1;
|
||||
|
||||
CopyMem (Buffer, BufferArray, sizeof (BufferArray));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Insert a Fragment Header to the Extension headers and output it in UpdatedExtHdrs.
|
||||
|
||||
@param[in] IpSb The IP6 service instance to transmit the packet.
|
||||
@param[in] NextHeader The extension header type of first extension header.
|
||||
@param[in] LastHeader The extension header type of last extension header.
|
||||
@param[in] ExtHdrs The length of the original extension header.
|
||||
@param[in] ExtHdrsLen The length of the extension headers.
|
||||
@param[in] FragmentOffset The fragment offset of the data following the header.
|
||||
@param[out] UpdatedExtHdrs The updated ExtHdrs with Fragment header inserted.
|
||||
It's caller's responsiblity to free this buffer.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to finish the operation due to lake of
|
||||
resource.
|
||||
@retval EFI_UNSUPPORTED The extension header specified in ExtHdrs is not
|
||||
supported currently.
|
||||
@retval EFI_SUCCESS The operation performed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6FillFragmentHeader (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN UINT8 NextHeader,
|
||||
IN UINT8 LastHeader,
|
||||
IN UINT8 *ExtHdrs,
|
||||
IN UINT32 ExtHdrsLen,
|
||||
IN UINT16 FragmentOffset,
|
||||
OUT UINT8 **UpdatedExtHdrs
|
||||
)
|
||||
{
|
||||
UINT32 Length;
|
||||
UINT8 *Buffer;
|
||||
UINT32 FormerHeader;
|
||||
UINT32 Offset;
|
||||
UINT32 Part1Len;
|
||||
UINT32 HeaderLen;
|
||||
UINT8 Current;
|
||||
IP6_FRAGMENT_HEADER FragmentHead;
|
||||
|
||||
if (UpdatedExtHdrs == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Length = ExtHdrsLen + sizeof (IP6_FRAGMENT_HEADER);
|
||||
Buffer = AllocatePool (Length);
|
||||
if (Buffer == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Offset = 0;
|
||||
Part1Len = 0;
|
||||
FormerHeader = 0;
|
||||
Current = NextHeader;
|
||||
|
||||
while ((ExtHdrs != NULL) && (Offset <= ExtHdrsLen)) {
|
||||
switch (NextHeader) {
|
||||
case IP6_ROUTING:
|
||||
case IP6_HOP_BY_HOP:
|
||||
case IP6_DESTINATION:
|
||||
Current = NextHeader;
|
||||
NextHeader = *(ExtHdrs + Offset);
|
||||
|
||||
if ((Current == IP6_DESTINATION) && (NextHeader != IP6_ROUTING)) {
|
||||
//
|
||||
// Destination Options header should occur at most twice, once before
|
||||
// a Routing header and once before the upper-layer header. Here we
|
||||
// find the one before the upper-layer header. Insert the Fragment
|
||||
// Header before it.
|
||||
//
|
||||
CopyMem (Buffer, ExtHdrs, Part1Len);
|
||||
*(Buffer + FormerHeader) = IP6_FRAGMENT;
|
||||
//
|
||||
// Exit the loop.
|
||||
//
|
||||
Offset = ExtHdrsLen + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
FormerHeader = Offset;
|
||||
HeaderLen = (*(ExtHdrs + Offset + 1) + 1) * 8;
|
||||
Part1Len = Part1Len + HeaderLen;
|
||||
Offset = Offset + HeaderLen;
|
||||
break;
|
||||
|
||||
case IP6_FRAGMENT:
|
||||
Current = NextHeader;
|
||||
|
||||
if (Part1Len != 0) {
|
||||
CopyMem (Buffer, ExtHdrs, Part1Len);
|
||||
}
|
||||
|
||||
*(Buffer + FormerHeader) = IP6_FRAGMENT;
|
||||
|
||||
//
|
||||
// Exit the loop.
|
||||
//
|
||||
Offset = ExtHdrsLen + 1;
|
||||
break;
|
||||
|
||||
case IP6_AH:
|
||||
Current = NextHeader;
|
||||
NextHeader = *(ExtHdrs + Offset);
|
||||
//
|
||||
// RFC2402, Payload length is specified in 32-bit words, minus "2".
|
||||
//
|
||||
HeaderLen = (*(ExtHdrs + Offset + 1) + 2) * 4;
|
||||
Part1Len = Part1Len + HeaderLen;
|
||||
Offset = Offset + HeaderLen;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (Ip6IsValidProtocol (IpSb, NextHeader)) {
|
||||
Current = NextHeader;
|
||||
CopyMem (Buffer, ExtHdrs, Part1Len);
|
||||
*(Buffer + FormerHeader) = IP6_FRAGMENT;
|
||||
//
|
||||
// Exit the loop.
|
||||
//
|
||||
Offset = ExtHdrsLen + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
FreePool (Buffer);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Append the Fragment header. If the fragment offset indicates the fragment
|
||||
// is the first fragment.
|
||||
//
|
||||
if ((FragmentOffset & IP6_FRAGMENT_OFFSET_MASK) == 0) {
|
||||
FragmentHead.NextHeader = Current;
|
||||
} else {
|
||||
FragmentHead.NextHeader = LastHeader;
|
||||
}
|
||||
|
||||
FragmentHead.Reserved = 0;
|
||||
FragmentHead.FragmentOffset = HTONS (FragmentOffset);
|
||||
FragmentHead.Identification = mIp6Id;
|
||||
|
||||
CopyMem (Buffer + Part1Len, &FragmentHead, sizeof (IP6_FRAGMENT_HEADER));
|
||||
|
||||
if ((ExtHdrs != NULL) && (Part1Len < ExtHdrsLen)) {
|
||||
//
|
||||
// Append the part2 (fragmentable part) of Extension headers
|
||||
//
|
||||
CopyMem (
|
||||
Buffer + Part1Len + sizeof (IP6_FRAGMENT_HEADER),
|
||||
ExtHdrs + Part1Len,
|
||||
ExtHdrsLen - Part1Len
|
||||
);
|
||||
}
|
||||
|
||||
*UpdatedExtHdrs = Buffer;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
191
NetworkPkg/Ip6Dxe/Ip6Option.h
Normal file
191
NetworkPkg/Ip6Dxe/Ip6Option.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/** @file
|
||||
Definition of IP6 option process routines.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP6_OPTION_H__
|
||||
#define __EFI_IP6_OPTION_H__
|
||||
|
||||
#define IP6_FRAGMENT_OFFSET_MASK (~0x3)
|
||||
|
||||
typedef struct _IP6_FRAGMENT_HEADER {
|
||||
UINT8 NextHeader;
|
||||
UINT8 Reserved;
|
||||
UINT16 FragmentOffset;
|
||||
UINT32 Identification;
|
||||
} IP6_FRAGMENT_HEADER;
|
||||
|
||||
typedef struct _IP6_ROUTING_HEADER {
|
||||
UINT8 NextHeader;
|
||||
UINT8 HeaderLen;
|
||||
UINT8 RoutingType;
|
||||
UINT8 SegmentsLeft;
|
||||
} IP6_ROUTING_HEADER;
|
||||
|
||||
typedef enum {
|
||||
Ip6OptionPad1 = 0,
|
||||
Ip6OptionPadN = 1,
|
||||
Ip6OptionRouterAlert = 5,
|
||||
Ip6OptionSkip = 0,
|
||||
Ip6OptionDiscard = 0x40,
|
||||
Ip6OptionParameterProblem = 0x80,
|
||||
Ip6OptionMask = 0xc0,
|
||||
|
||||
Ip6OptionEtherSource = 1,
|
||||
Ip6OptionEtherTarget = 2,
|
||||
Ip6OptionPrefixInfo = 3,
|
||||
Ip6OptionRedirected = 4,
|
||||
Ip6OptionMtu = 5
|
||||
} IP6_OPTION_TYPE;
|
||||
|
||||
/**
|
||||
Validate the IP6 extension header format for both the packets we received
|
||||
and that we will transmit. It will compute the ICMPv6 error message fields
|
||||
if the option is mal-formated.
|
||||
|
||||
@param[in] IpSb The IP6 service instance. This is an optional parameter.
|
||||
@param[in] Packet The data of the packet. Ignored if NULL.
|
||||
@param[in] NextHeader The next header field in IPv6 basic header.
|
||||
@param[in] ExtHdrs The first byte of the option.
|
||||
@param[in] ExtHdrsLen The length of the whole option.
|
||||
@param[in] Rcvd The option is from the packet we received if TRUE,
|
||||
otherwise, the option we want to transmit.
|
||||
@param[out] FormerHeader The offset of NextHeader which points to Fragment
|
||||
Header when we received, of the ExtHdrs.
|
||||
Ignored if we transmit.
|
||||
@param[out] LastHeader The pointer of NextHeader of the last extension
|
||||
header processed by IP6.
|
||||
@param[out] RealExtsLen The length of extension headers processed by IP6 layer.
|
||||
This is an optional parameter that may be NULL.
|
||||
@param[out] UnFragmentLen The length of unfragmented length of extension headers.
|
||||
This is an optional parameter that may be NULL.
|
||||
@param[out] Fragmented Indicate whether the packet is fragmented.
|
||||
This is an optional parameter that may be NULL.
|
||||
|
||||
@retval TRUE The option is properly formated.
|
||||
@retval FALSE The option is malformated.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsExtsValid (
|
||||
IN IP6_SERVICE *IpSb OPTIONAL,
|
||||
IN NET_BUF *Packet OPTIONAL,
|
||||
IN UINT8 *NextHeader,
|
||||
IN UINT8 *ExtHdrs,
|
||||
IN UINT32 ExtHdrsLen,
|
||||
IN BOOLEAN Rcvd,
|
||||
OUT UINT32 *FormerHeader OPTIONAL,
|
||||
OUT UINT8 **LastHeader,
|
||||
OUT UINT32 *RealExtsLen OPTIONAL,
|
||||
OUT UINT32 *UnFragmentLen OPTIONAL,
|
||||
OUT BOOLEAN *Fragmented OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Generate an IPv6 router alert option in network order and output it through Buffer.
|
||||
|
||||
@param[out] Buffer Points to a buffer to record the generated option.
|
||||
@param[in, out] BufferLen The length of Buffer, in bytes.
|
||||
@param[in] NextHeader The 8-bit selector indicates the type of header
|
||||
immediately following the Hop-by-Hop Options header.
|
||||
|
||||
@retval EFI_BUFFER_TOO_SMALL The Buffer is too small to contain the generated
|
||||
option. BufferLen is updated for the required size.
|
||||
|
||||
@retval EFI_SUCCESS The option is generated and filled in to Buffer.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6FillHopByHop (
|
||||
OUT UINT8 *Buffer,
|
||||
IN OUT UINTN *BufferLen,
|
||||
IN UINT8 NextHeader
|
||||
);
|
||||
|
||||
/**
|
||||
Insert a Fragment Header to the Extension headers and output it in UpdatedExtHdrs.
|
||||
|
||||
@param[in] IpSb The IP6 service instance to transmit the packet.
|
||||
@param[in] NextHeader The extension header type of first extension header.
|
||||
@param[in] LastHeader The extension header type of last extension header.
|
||||
@param[in] ExtHdrs The length of the original extension header.
|
||||
@param[in] ExtHdrsLen The length of the extension headers.
|
||||
@param[in] FragmentOffset The fragment offset of the data following the header.
|
||||
@param[out] UpdatedExtHdrs The updated ExtHdrs with Fragment header inserted.
|
||||
It's caller's responsiblity to free this buffer.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to finish the operation due to lake of
|
||||
resource.
|
||||
@retval EFI_UNSUPPORTED The extension header specified in ExtHdrs is not
|
||||
supported currently.
|
||||
@retval EFI_SUCCESS The operation performed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6FillFragmentHeader (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN UINT8 NextHeader,
|
||||
IN UINT8 LastHeader,
|
||||
IN UINT8 *ExtHdrs,
|
||||
IN UINT32 ExtHdrsLen,
|
||||
IN UINT16 FragmentOffset,
|
||||
OUT UINT8 **UpdatedExtHdrs
|
||||
);
|
||||
|
||||
/**
|
||||
Copy the extension headers from the original to buffer. A Fragment header is
|
||||
appended to the end.
|
||||
|
||||
@param[in] NextHeader The 8-bit selector indicates the type of
|
||||
the fragment header's next header.
|
||||
@param[in] ExtHdrs The length of the original extension header.
|
||||
@param[in] LastHeader The pointer of next header of last extension header.
|
||||
@param[in] FragmentOffset The fragment offset of the data following the header.
|
||||
@param[in] UnFragmentHdrLen The length of unfragmented length of extension headers.
|
||||
@param[in, out] Buf The buffer to copy options to.
|
||||
@param[in, out] BufLen The length of the buffer.
|
||||
|
||||
@retval EFI_SUCCESS The options are copied over.
|
||||
@retval EFI_BUFFER_TOO_SMALL The buffer caller provided is too small.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6CopyExts (
|
||||
IN UINT8 NextHeader,
|
||||
IN UINT8 *ExtHdrs,
|
||||
IN UINT8 *LastHeader,
|
||||
IN UINT16 FragmentOffset,
|
||||
IN UINT32 UnFragmentHdrLen,
|
||||
IN OUT UINT8 *Buf,
|
||||
IN OUT UINT32 *BufLen
|
||||
);
|
||||
|
||||
/**
|
||||
Validate the IP6 option format for both the packets we received
|
||||
and that we will transmit. It supports the defined options in Neighbor
|
||||
Discovery messages.
|
||||
|
||||
@param[in] Option The first byte of the option.
|
||||
@param[in] OptionLen The length of the whole option.
|
||||
|
||||
@retval TRUE The option is properly formatted.
|
||||
@retval FALSE The option is malformated.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip6IsNDOptionValid (
|
||||
IN UINT8 *Option,
|
||||
IN UINT16 OptionLen
|
||||
);
|
||||
|
||||
#endif
|
1077
NetworkPkg/Ip6Dxe/Ip6Output.c
Normal file
1077
NetworkPkg/Ip6Dxe/Ip6Output.c
Normal file
File diff suppressed because it is too large
Load Diff
141
NetworkPkg/Ip6Dxe/Ip6Output.h
Normal file
141
NetworkPkg/Ip6Dxe/Ip6Output.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/** @file
|
||||
The internal functions and routines to transmit the IP6 packet.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP6_OUTPUT_H__
|
||||
#define __EFI_IP6_OUTPUT_H__
|
||||
|
||||
extern UINT32 mIp6Id;
|
||||
|
||||
/**
|
||||
Output all the available source addresses to the list entry head SourceList. The
|
||||
number of source addresses are also returned.
|
||||
|
||||
@param[in] IpSb Points to a IP6 service binding instance.
|
||||
@param[in] Destination The IPv6 destination address.
|
||||
@param[out] Source The selected IPv6 source address according to
|
||||
the Destination.
|
||||
|
||||
@retval EFI_SUCCESS The source addresses were copied to the list entry
|
||||
head SourceList.
|
||||
@retval EFI_NO_MAPPING The IPv6 stack is not auto configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6SelectSourceAddress (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Destination,
|
||||
OUT EFI_IPv6_ADDRESS *Source
|
||||
);
|
||||
|
||||
/**
|
||||
The default callback function for system generated packet.
|
||||
It will free the packet.
|
||||
|
||||
@param[in] Packet The packet that transmitted.
|
||||
@param[in] IoStatus The result of the transmission: succeeded or failed.
|
||||
@param[in] LinkFlag Not used when transmission. Check IP6_FRAME_CALLBACK
|
||||
for reference.
|
||||
@param[in] Context The context provided by us.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6SysPacketSent (
|
||||
NET_BUF *Packet,
|
||||
EFI_STATUS IoStatus,
|
||||
UINT32 LinkFlag,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Transmit an IP6 packet. The packet comes either from the IP6
|
||||
child's consumer (IpInstance != NULL) or the IP6 driver itself
|
||||
(IpInstance == NULL). It will route the packet, fragment it,
|
||||
then transmit all the fragments through an interface.
|
||||
|
||||
@param[in] IpSb The IP6 service instance to transmit the packet.
|
||||
@param[in] Interface The IP6 interface to transmit the packet. Ignored
|
||||
if NULL.
|
||||
@param[in] IpInstance The IP6 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: NextHeader, HopLimit,
|
||||
Src, Dest, FlowLabel, PayloadLength. This function
|
||||
will fill in the Ver, TrafficClass.
|
||||
@param[in] ExtHdrs The extension headers to append to the IPv6 basic
|
||||
header.
|
||||
@param[in] ExtHdrsLen The length of the extension headers.
|
||||
@param[in] Callback The callback function to issue when transmission
|
||||
completed.
|
||||
@param[in] Context The opaque context for the callback.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Any input parameter or the packet is invalid.
|
||||
@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 successfully transmitted.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to finish the operation due to lack of
|
||||
resources.
|
||||
@retval Others Failed to transmit the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6Output (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN IP6_INTERFACE *Interface OPTIONAL,
|
||||
IN IP6_PROTOCOL *IpInstance OPTIONAL,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_IP6_HEADER *Head,
|
||||
IN UINT8 *ExtHdrs,
|
||||
IN UINT32 ExtHdrsLen,
|
||||
IN IP6_FRAME_CALLBACK Callback,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
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. Ignored if
|
||||
FrameToCancel is NULL.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CancelFrames (
|
||||
IN IP6_INTERFACE *Interface,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
|
||||
IN VOID *Context OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Cancel the Packet and all its fragments.
|
||||
|
||||
@param[in] IpIf The interface from which the Packet is sent.
|
||||
@param[in] Packet The Packet to cancel.
|
||||
@param[in] IoStatus The status returns to the sender.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CancelPacket (
|
||||
IN IP6_INTERFACE *IpIf,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus
|
||||
);
|
||||
|
||||
#endif
|
635
NetworkPkg/Ip6Dxe/Ip6Route.c
Normal file
635
NetworkPkg/Ip6Dxe/Ip6Route.c
Normal file
@@ -0,0 +1,635 @@
|
||||
/** @file
|
||||
The functions and routines to handle the route caches and route table.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip6Impl.h"
|
||||
|
||||
/**
|
||||
This is the worker function for IP6_ROUTE_CACHE_HASH(). It calculates the value
|
||||
as the index of the route cache bucket according to the prefix of two IPv6 addresses.
|
||||
|
||||
@param[in] Ip1 The IPv6 address.
|
||||
@param[in] Ip2 The IPv6 address.
|
||||
|
||||
@return The hash value of the prefix of two IPv6 addresses.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
Ip6RouteCacheHash (
|
||||
IN EFI_IPv6_ADDRESS *Ip1,
|
||||
IN EFI_IPv6_ADDRESS *Ip2
|
||||
)
|
||||
{
|
||||
UINT32 Prefix1;
|
||||
UINT32 Prefix2;
|
||||
|
||||
Prefix1 = *((UINT32 *) ((UINTN *) (Ip1)));
|
||||
Prefix2 = *((UINT32 *) ((UINTN *) (Ip2)));
|
||||
|
||||
return ((UINT32) (Prefix1 ^ Prefix2) % IP6_ROUTE_CACHE_HASH_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
Allocate a route entry then initialize it with the Destination/PrefixLength
|
||||
and Gateway.
|
||||
|
||||
@param[in] Destination The IPv6 destination address. This is an optional
|
||||
parameter that may be NULL.
|
||||
@param[in] PrefixLength The destination network's prefix length.
|
||||
@param[in] GatewayAddress The next hop address. This is an optional parameter
|
||||
that may be NULL.
|
||||
|
||||
@return NULL if failed to allocate memeory; otherwise, the newly created route entry.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_ENTRY *
|
||||
Ip6CreateRouteEntry (
|
||||
IN EFI_IPv6_ADDRESS *Destination OPTIONAL,
|
||||
IN UINT8 PrefixLength,
|
||||
IN EFI_IPv6_ADDRESS *GatewayAddress OPTIONAL
|
||||
)
|
||||
{
|
||||
IP6_ROUTE_ENTRY *RtEntry;
|
||||
|
||||
RtEntry = AllocateZeroPool (sizeof (IP6_ROUTE_ENTRY));
|
||||
|
||||
if (RtEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RtEntry->RefCnt = 1;
|
||||
RtEntry->Flag = 0;
|
||||
RtEntry->PrefixLength = PrefixLength;
|
||||
|
||||
if (Destination != NULL) {
|
||||
IP6_COPY_ADDRESS (&RtEntry->Destination, Destination);
|
||||
}
|
||||
|
||||
if (GatewayAddress != NULL) {
|
||||
IP6_COPY_ADDRESS (&RtEntry->NextHop, GatewayAddress);
|
||||
}
|
||||
|
||||
return RtEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
Free the route table entry. It is reference counted.
|
||||
|
||||
@param[in, out] RtEntry The route entry to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6FreeRouteEntry (
|
||||
IN OUT IP6_ROUTE_ENTRY *RtEntry
|
||||
)
|
||||
{
|
||||
ASSERT ((RtEntry != NULL) && (RtEntry->RefCnt > 0));
|
||||
|
||||
if (--RtEntry->RefCnt == 0) {
|
||||
FreePool (RtEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Search the route table for a most specific match to the Dst. It searches
|
||||
from the longest route area (prefix length == 128) 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 per 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] Destination The destionation address to search. If NULL, search
|
||||
the route table by NextHop.
|
||||
@param[in] NextHop The next hop address. If NULL, search the route table
|
||||
by Destination.
|
||||
|
||||
@return NULL if no route matches the Dst. Otherwise, the point to the
|
||||
@return most specific route to the Dst.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_ENTRY *
|
||||
Ip6FindRouteEntry (
|
||||
IN IP6_ROUTE_TABLE *RtTable,
|
||||
IN EFI_IPv6_ADDRESS *Destination OPTIONAL,
|
||||
IN EFI_IPv6_ADDRESS *NextHop OPTIONAL
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP6_ROUTE_ENTRY *RtEntry;
|
||||
INTN Index;
|
||||
|
||||
ASSERT (Destination != NULL || NextHop != NULL);
|
||||
|
||||
RtEntry = NULL;
|
||||
|
||||
for (Index = IP6_PREFIX_NUM - 1; Index >= 0; Index--) {
|
||||
NET_LIST_FOR_EACH (Entry, &RtTable->RouteArea[Index]) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_ENTRY, Link);
|
||||
|
||||
if (Destination != NULL) {
|
||||
if (NetIp6IsNetEqual (Destination, &RtEntry->Destination, RtEntry->PrefixLength)) {
|
||||
NET_GET_REF (RtEntry);
|
||||
return RtEntry;
|
||||
}
|
||||
} else if (NextHop != NULL) {
|
||||
if (NetIp6IsNetEqual (NextHop, &RtEntry->NextHop, RtEntry->PrefixLength)) {
|
||||
NET_GET_REF (RtEntry);
|
||||
return RtEntry;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Allocate and initialize a IP6 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. Otherwise, point
|
||||
to the created route cache entry.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_CACHE_ENTRY *
|
||||
Ip6CreateRouteCacheEntry (
|
||||
IN EFI_IPv6_ADDRESS *Dst,
|
||||
IN EFI_IPv6_ADDRESS *Src,
|
||||
IN EFI_IPv6_ADDRESS *GateWay,
|
||||
IN UINTN Tag
|
||||
)
|
||||
{
|
||||
IP6_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
|
||||
RtCacheEntry = AllocatePool (sizeof (IP6_ROUTE_CACHE_ENTRY));
|
||||
|
||||
if (RtCacheEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RtCacheEntry->RefCnt = 1;
|
||||
RtCacheEntry->Tag = Tag;
|
||||
|
||||
IP6_COPY_ADDRESS (&RtCacheEntry->Destination, Dst);
|
||||
IP6_COPY_ADDRESS (&RtCacheEntry->Source, Src);
|
||||
IP6_COPY_ADDRESS (&RtCacheEntry->NextHop, GateWay);
|
||||
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
Free the route cache entry. It is reference counted.
|
||||
|
||||
@param[in, out] RtCacheEntry The route cache entry to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6FreeRouteCacheEntry (
|
||||
IN OUT IP6_ROUTE_CACHE_ENTRY *RtCacheEntry
|
||||
)
|
||||
{
|
||||
ASSERT (RtCacheEntry->RefCnt > 0);
|
||||
|
||||
if (--RtCacheEntry->RefCnt == 0) {
|
||||
FreePool (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Find a route cache with the destination and source address. This is
|
||||
used by the ICMPv6 redirect messasge process.
|
||||
|
||||
@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 pointer
|
||||
to the correct route cache entry.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_CACHE_ENTRY *
|
||||
Ip6FindRouteCache (
|
||||
IN IP6_ROUTE_TABLE *RtTable,
|
||||
IN EFI_IPv6_ADDRESS *Dest,
|
||||
IN EFI_IPv6_ADDRESS *Src
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP6_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
UINT32 Index;
|
||||
|
||||
Index = IP6_ROUTE_CACHE_HASH (Dest, Src);
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &RtTable->Cache.CacheBucket[Index]) {
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
if (EFI_IP6_EQUAL (Dest, &RtCacheEntry->Destination)&& EFI_IP6_EQUAL (Src, &RtCacheEntry->Source)) {
|
||||
NET_GET_REF (RtCacheEntry);
|
||||
return RtCacheEntry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Build an array of EFI_IP6_ROUTE_TABLE to be returned to the caller. The number
|
||||
of EFI_IP6_ROUTE_TABLE is also returned.
|
||||
|
||||
@param[in] RouteTable The pointer of IP6_ROUTE_TABLE internal used.
|
||||
@param[out] EfiRouteCount The number of returned route entries.
|
||||
@param[out] EfiRouteTable The pointer to the array of EFI_IP6_ROUTE_TABLE.
|
||||
If NULL, only the route entry count is returned.
|
||||
|
||||
@retval EFI_SUCCESS The EFI_IP6_ROUTE_TABLE successfully built.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the route table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6BuildEfiRouteTable (
|
||||
IN IP6_ROUTE_TABLE *RouteTable,
|
||||
OUT UINT32 *EfiRouteCount,
|
||||
OUT EFI_IP6_ROUTE_TABLE **EfiRouteTable OPTIONAL
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
IP6_ROUTE_ENTRY *RtEntry;
|
||||
EFI_IP6_ROUTE_TABLE *EfiTable;
|
||||
UINT32 Count;
|
||||
INT32 Index;
|
||||
|
||||
ASSERT (EfiRouteCount != NULL);
|
||||
|
||||
Count = RouteTable->TotalNum;
|
||||
*EfiRouteCount = Count;
|
||||
|
||||
if ((EfiRouteTable == NULL) || (Count == 0)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (*EfiRouteTable == NULL) {
|
||||
*EfiRouteTable = AllocatePool (sizeof (EFI_IP6_ROUTE_TABLE) * Count);
|
||||
if (*EfiRouteTable == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
EfiTable = *EfiRouteTable;
|
||||
|
||||
//
|
||||
// Copy the route entry to EFI route table.
|
||||
//
|
||||
Count = 0;
|
||||
|
||||
for (Index = IP6_PREFIX_NUM - 1; Index >= 0; Index--) {
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &(RouteTable->RouteArea[Index])) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_ENTRY, Link);
|
||||
|
||||
Ip6CopyAddressByPrefix (
|
||||
&EfiTable[Count].Destination,
|
||||
&RtEntry->Destination,
|
||||
RtEntry->PrefixLength
|
||||
);
|
||||
|
||||
IP6_COPY_ADDRESS (&EfiTable[Count].Gateway, &RtEntry->NextHop);
|
||||
EfiTable[Count].PrefixLength = RtEntry->PrefixLength;
|
||||
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT (Count == RouteTable->TotalNum);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Create an empty route table. This includes its internal route cache.
|
||||
|
||||
@return NULL if failed to allocate memory for the route table. Otherwise,
|
||||
the point to newly created route table.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_TABLE *
|
||||
Ip6CreateRouteTable (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
IP6_ROUTE_TABLE *RtTable;
|
||||
UINT32 Index;
|
||||
|
||||
RtTable = AllocatePool (sizeof (IP6_ROUTE_TABLE));
|
||||
if (RtTable == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RtTable->RefCnt = 1;
|
||||
RtTable->TotalNum = 0;
|
||||
|
||||
for (Index = 0; Index < IP6_PREFIX_NUM; Index++) {
|
||||
InitializeListHead (&RtTable->RouteArea[Index]);
|
||||
}
|
||||
|
||||
for (Index = 0; Index < IP6_ROUTE_CACHE_HASH_SIZE; Index++) {
|
||||
InitializeListHead (&RtTable->Cache.CacheBucket[Index]);
|
||||
RtTable->Cache.CacheNum[Index] = 0;
|
||||
}
|
||||
|
||||
return RtTable;
|
||||
}
|
||||
|
||||
/**
|
||||
Free the route table and its associated route cache. Route
|
||||
table is reference counted.
|
||||
|
||||
@param[in, out] RtTable The route table to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CleanRouteTable (
|
||||
IN OUT IP6_ROUTE_TABLE *RtTable
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
IP6_ROUTE_ENTRY *RtEntry;
|
||||
IP6_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
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 < IP6_PREFIX_NUM; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &RtTable->RouteArea[Index]) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_ENTRY, Link);
|
||||
RemoveEntryList (Entry);
|
||||
Ip6FreeRouteEntry (RtEntry);
|
||||
}
|
||||
}
|
||||
|
||||
for (Index = 0; Index < IP6_ROUTE_CACHE_HASH_SIZE; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &RtTable->Cache.CacheBucket[Index]) {
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_CACHE_ENTRY, Link);
|
||||
RemoveEntryList (Entry);
|
||||
Ip6FreeRouteCacheEntry (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
|
||||
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[in] RtCache Route cache to remove the entries from.
|
||||
@param[in] Tag The Tag of the entries to remove.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6PurgeRouteCache (
|
||||
IN IP6_ROUTE_CACHE *RtCache,
|
||||
IN UINTN Tag
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
IP6_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < IP6_ROUTE_CACHE_HASH_SIZE; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &RtCache->CacheBucket[Index]) {
|
||||
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
if (RtCacheEntry->Tag == Tag) {
|
||||
RemoveEntryList (Entry);
|
||||
Ip6FreeRouteCacheEntry (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Add a route entry to the route table. It is the help function for EfiIp6Routes.
|
||||
|
||||
@param[in, out] RtTable Route table to add route to.
|
||||
@param[in] Destination The destination of the network.
|
||||
@param[in] PrefixLength The PrefixLength of the destination.
|
||||
@param[in] GatewayAddress 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 was added successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6AddRoute (
|
||||
IN OUT IP6_ROUTE_TABLE *RtTable,
|
||||
IN EFI_IPv6_ADDRESS *Destination,
|
||||
IN UINT8 PrefixLength,
|
||||
IN EFI_IPv6_ADDRESS *GatewayAddress
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *ListHead;
|
||||
LIST_ENTRY *Entry;
|
||||
IP6_ROUTE_ENTRY *Route;
|
||||
|
||||
ListHead = &RtTable->RouteArea[PrefixLength];
|
||||
|
||||
//
|
||||
// First check whether the route exists
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, ListHead) {
|
||||
Route = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_ENTRY, Link);
|
||||
|
||||
if (NetIp6IsNetEqual (Destination, &Route->Destination, PrefixLength) &&
|
||||
EFI_IP6_EQUAL (GatewayAddress, &Route->NextHop)) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create a route entry and insert it to the route area.
|
||||
//
|
||||
Route = Ip6CreateRouteEntry (Destination, PrefixLength, GatewayAddress);
|
||||
|
||||
if (Route == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (NetIp6IsUnspecifiedAddr (GatewayAddress)) {
|
||||
Route->Flag = IP6_DIRECT_ROUTE;
|
||||
}
|
||||
|
||||
InsertHeadList (ListHead, &Route->Link);
|
||||
RtTable->TotalNum++;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove a route entry and all the route caches spawn from it.
|
||||
It is the help function for EfiIp6Routes.
|
||||
|
||||
@param[in, out] RtTable The route table to remove the route from.
|
||||
@param[in] Destination The destination network.
|
||||
@param[in] PrefixLength The PrefixLength of the Destination.
|
||||
@param[in] GatewayAddress The next hop address.
|
||||
|
||||
@retval EFI_SUCCESS The route entry was successfully removed.
|
||||
@retval EFI_NOT_FOUND There is no route entry in the table with that
|
||||
property.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6DelRoute (
|
||||
IN OUT IP6_ROUTE_TABLE *RtTable,
|
||||
IN EFI_IPv6_ADDRESS *Destination,
|
||||
IN UINT8 PrefixLength,
|
||||
IN EFI_IPv6_ADDRESS *GatewayAddress
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *ListHead;
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
IP6_ROUTE_ENTRY *Route;
|
||||
UINT32 TotalNum;
|
||||
|
||||
ListHead = &RtTable->RouteArea[PrefixLength];
|
||||
TotalNum = RtTable->TotalNum;
|
||||
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, ListHead) {
|
||||
Route = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_ENTRY, Link);
|
||||
|
||||
if (Destination != NULL && !NetIp6IsNetEqual (Destination, &Route->Destination, PrefixLength)) {
|
||||
continue;
|
||||
}
|
||||
if (GatewayAddress != NULL && !EFI_IP6_EQUAL (GatewayAddress, &Route->NextHop)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Ip6PurgeRouteCache (&RtTable->Cache, (UINTN) Route);
|
||||
RemoveEntryList (Entry);
|
||||
Ip6FreeRouteEntry (Route);
|
||||
|
||||
ASSERT (RtTable->TotalNum > 0);
|
||||
RtTable->TotalNum--;
|
||||
}
|
||||
|
||||
return TotalNum == RtTable->TotalNum ? EFI_NOT_FOUND : EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Search the route table to route the packet. Return/create a route
|
||||
cache if there is a route to the destination.
|
||||
|
||||
@param[in] IpSb The IP6 service data.
|
||||
@param[in] Dest The destination address to search for.
|
||||
@param[in] Src The source address to search for.
|
||||
|
||||
@return NULL if it failed to route the packet. Otherwise, a route cache
|
||||
entry that can be used to route packets.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_CACHE_ENTRY *
|
||||
Ip6Route (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Dest,
|
||||
IN EFI_IPv6_ADDRESS *Src
|
||||
)
|
||||
{
|
||||
IP6_ROUTE_TABLE *RtTable;
|
||||
LIST_ENTRY *ListHead;
|
||||
IP6_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
IP6_ROUTE_ENTRY *RtEntry;
|
||||
EFI_IPv6_ADDRESS NextHop;
|
||||
UINT32 Index;
|
||||
|
||||
RtTable = IpSb->RouteTable;
|
||||
|
||||
ASSERT (RtTable != NULL);
|
||||
|
||||
//
|
||||
// Search the destination cache in IP6_ROUTE_TABLE.
|
||||
//
|
||||
Index = IP6_ROUTE_CACHE_HASH (Dest, Src);
|
||||
ListHead = &RtTable->Cache.CacheBucket[Index];
|
||||
|
||||
RtCacheEntry = Ip6FindRouteCache (RtTable, Dest, Src);
|
||||
|
||||
//
|
||||
// If found, promote the cache entry to the head of the hash bucket.
|
||||
//
|
||||
if (RtCacheEntry != NULL) {
|
||||
RemoveEntryList (&RtCacheEntry->Link);
|
||||
InsertHeadList (ListHead, &RtCacheEntry->Link);
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
||||
//
|
||||
// Search the route table for the most specific route
|
||||
//
|
||||
RtEntry = Ip6FindRouteEntry (RtTable, Dest, NULL);
|
||||
if (RtEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Found a route to the Dest, if it is a direct route, the packet
|
||||
// will be send directly to the destination, such as for connected
|
||||
// network. Otherwise, it is an indirect route, the packet will be
|
||||
// send the next hop router.
|
||||
//
|
||||
if ((RtEntry->Flag & IP6_DIRECT_ROUTE) == IP6_DIRECT_ROUTE) {
|
||||
IP6_COPY_ADDRESS (&NextHop, Dest);
|
||||
} else {
|
||||
IP6_COPY_ADDRESS (&NextHop, &RtEntry->NextHop);
|
||||
}
|
||||
|
||||
Ip6FreeRouteEntry (RtEntry);
|
||||
|
||||
//
|
||||
// Create a route cache entry, and tag it as spawned from this route entry
|
||||
//
|
||||
RtCacheEntry = Ip6CreateRouteCacheEntry (Dest, Src, &NextHop, (UINTN) RtEntry);
|
||||
|
||||
if (RtCacheEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
InsertHeadList (ListHead, &RtCacheEntry->Link);
|
||||
NET_GET_REF (RtCacheEntry);
|
||||
RtTable->Cache.CacheNum[Index]++;
|
||||
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
299
NetworkPkg/Ip6Dxe/Ip6Route.h
Normal file
299
NetworkPkg/Ip6Dxe/Ip6Route.h
Normal file
@@ -0,0 +1,299 @@
|
||||
/** @file
|
||||
EFI IP6 route table and route cache table defintions.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP6_ROUTE_H__
|
||||
#define __EFI_IP6_ROUTE_H__
|
||||
|
||||
#define IP6_DIRECT_ROUTE 0x00000001
|
||||
#define IP6_PACKET_TOO_BIG 0x00000010
|
||||
|
||||
#define IP6_ROUTE_CACHE_HASH_SIZE 31
|
||||
///
|
||||
/// Max NO. of cache entry per hash bucket
|
||||
///
|
||||
#define IP6_ROUTE_CACHE_MAX 32
|
||||
|
||||
#define IP6_ROUTE_CACHE_HASH(Ip1, Ip2) Ip6RouteCacheHash ((Ip1), (Ip2))
|
||||
|
||||
typedef struct {
|
||||
LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
UINT32 Flag;
|
||||
UINT8 PrefixLength;
|
||||
EFI_IPv6_ADDRESS Destination;
|
||||
EFI_IPv6_ADDRESS NextHop;
|
||||
} IP6_ROUTE_ENTRY;
|
||||
|
||||
typedef struct {
|
||||
LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
UINTN Tag;
|
||||
EFI_IPv6_ADDRESS Destination;
|
||||
EFI_IPv6_ADDRESS Source;
|
||||
EFI_IPv6_ADDRESS NextHop;
|
||||
} IP6_ROUTE_CACHE_ENTRY;
|
||||
|
||||
typedef struct {
|
||||
LIST_ENTRY CacheBucket[IP6_ROUTE_CACHE_HASH_SIZE];
|
||||
UINT8 CacheNum[IP6_ROUTE_CACHE_HASH_SIZE];
|
||||
} IP6_ROUTE_CACHE;
|
||||
|
||||
//
|
||||
// Each IP6 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 prefix length 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 _IP6_ROUTE_TABLE {
|
||||
INTN RefCnt;
|
||||
UINT32 TotalNum;
|
||||
LIST_ENTRY RouteArea[IP6_PREFIX_NUM];
|
||||
IP6_ROUTE_CACHE Cache;
|
||||
} IP6_ROUTE_TABLE;
|
||||
|
||||
/**
|
||||
This is the worker function for IP6_ROUTE_CACHE_HASH(). It calculates the value
|
||||
as the index of the route cache bucket according to the prefix of two IPv6 addresses.
|
||||
|
||||
@param[in] Ip1 The IPv6 address.
|
||||
@param[in] Ip2 The IPv6 address.
|
||||
|
||||
@return The hash value of the prefix of two IPv6 addresses.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
Ip6RouteCacheHash (
|
||||
IN EFI_IPv6_ADDRESS *Ip1,
|
||||
IN EFI_IPv6_ADDRESS *Ip2
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate and initialize an IP6 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 it failed to allocate memory for the cache. Otherwise, point
|
||||
to the created route cache entry.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_CACHE_ENTRY *
|
||||
Ip6CreateRouteCacheEntry (
|
||||
IN EFI_IPv6_ADDRESS *Dst,
|
||||
IN EFI_IPv6_ADDRESS *Src,
|
||||
IN EFI_IPv6_ADDRESS *GateWay,
|
||||
IN UINTN Tag
|
||||
);
|
||||
|
||||
/**
|
||||
Free the route cache entry. It is reference counted.
|
||||
|
||||
@param[in, out] RtCacheEntry The route cache entry to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6FreeRouteCacheEntry (
|
||||
IN OUT IP6_ROUTE_CACHE_ENTRY *RtCacheEntry
|
||||
);
|
||||
|
||||
/**
|
||||
Find a route cache with the destination and source address. This is
|
||||
used by the ICMPv6 redirect messasge process.
|
||||
|
||||
@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, point
|
||||
to the correct route cache entry.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_CACHE_ENTRY *
|
||||
Ip6FindRouteCache (
|
||||
IN IP6_ROUTE_TABLE *RtTable,
|
||||
IN EFI_IPv6_ADDRESS *Dest,
|
||||
IN EFI_IPv6_ADDRESS *Src
|
||||
);
|
||||
|
||||
/**
|
||||
Build a array of EFI_IP6_ROUTE_TABLE to be returned to the caller. The number
|
||||
of EFI_IP6_ROUTE_TABLE is also returned.
|
||||
|
||||
@param[in] RouteTable The pointer of IP6_ROUTE_TABLE internal used.
|
||||
@param[out] EfiRouteCount The number of returned route entries.
|
||||
@param[out] EfiRouteTable The pointer to the array of EFI_IP6_ROUTE_TABLE.
|
||||
If NULL, only the route entry count is returned.
|
||||
|
||||
@retval EFI_SUCCESS The EFI_IP6_ROUTE_TABLE successfully built.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the route table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6BuildEfiRouteTable (
|
||||
IN IP6_ROUTE_TABLE *RouteTable,
|
||||
OUT UINT32 *EfiRouteCount,
|
||||
OUT EFI_IP6_ROUTE_TABLE **EfiRouteTable OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
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.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_TABLE *
|
||||
Ip6CreateRouteTable (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Free the route table and its associated route cache. Route
|
||||
table is reference counted.
|
||||
|
||||
@param[in, out] RtTable The route table to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6CleanRouteTable (
|
||||
IN OUT IP6_ROUTE_TABLE *RtTable
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate a route entry then initialize it with the Destination/PrefixLength
|
||||
and Gateway.
|
||||
|
||||
@param[in] Destination The IPv6 destination address. This is an optional
|
||||
parameter that may be NULL.
|
||||
@param[in] PrefixLength The destination network's prefix length.
|
||||
@param[in] GatewayAddress The next hop address. This is optional parameter
|
||||
that may be NULL.
|
||||
|
||||
@return NULL if it failed to allocate memeory. Otherwise, the newly created route entry.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_ENTRY *
|
||||
Ip6CreateRouteEntry (
|
||||
IN EFI_IPv6_ADDRESS *Destination OPTIONAL,
|
||||
IN UINT8 PrefixLength,
|
||||
IN EFI_IPv6_ADDRESS *GatewayAddress OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Search the route table for a most specific match to the Dst. It searches
|
||||
from the longest route area (prefix length == 128) 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 per 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] Destination The destionation address to search. If NULL, search
|
||||
the route table by NextHop.
|
||||
@param[in] NextHop The next hop address. If NULL, search the route table
|
||||
by Destination.
|
||||
|
||||
@return NULL if no route matches the Dst. Otherwise the point to the
|
||||
most specific route to the Dst.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_ENTRY *
|
||||
Ip6FindRouteEntry (
|
||||
IN IP6_ROUTE_TABLE *RtTable,
|
||||
IN EFI_IPv6_ADDRESS *Destination OPTIONAL,
|
||||
IN EFI_IPv6_ADDRESS *NextHop OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Free the route table entry. It is reference counted.
|
||||
|
||||
@param[in, out] RtEntry The route entry to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip6FreeRouteEntry (
|
||||
IN OUT IP6_ROUTE_ENTRY *RtEntry
|
||||
);
|
||||
|
||||
/**
|
||||
Add a route entry to the route table. It is the help function for EfiIp6Routes.
|
||||
|
||||
@param[in, out] RtTable Route table to add route to.
|
||||
@param[in] Destination The destination of the network.
|
||||
@param[in] PrefixLength The PrefixLength of the destination.
|
||||
@param[in] GatewayAddress 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 was added successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6AddRoute (
|
||||
IN OUT IP6_ROUTE_TABLE *RtTable,
|
||||
IN EFI_IPv6_ADDRESS *Destination,
|
||||
IN UINT8 PrefixLength,
|
||||
IN EFI_IPv6_ADDRESS *GatewayAddress
|
||||
);
|
||||
|
||||
/**
|
||||
Remove a route entry and all the route caches spawn from it.
|
||||
It is the help function for EfiIp6Routes.
|
||||
|
||||
@param[in, out] RtTable The route table to remove the route from.
|
||||
@param[in] Destination The destination network.
|
||||
@param[in] PrefixLength The PrefixLength of the Destination.
|
||||
@param[in] GatewayAddress The next hop address.
|
||||
|
||||
@retval EFI_SUCCESS Successfully removed the route entry.
|
||||
@retval EFI_NOT_FOUND There is no route entry in the table with that
|
||||
properity.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip6DelRoute (
|
||||
IN OUT IP6_ROUTE_TABLE *RtTable,
|
||||
IN EFI_IPv6_ADDRESS *Destination,
|
||||
IN UINT8 PrefixLength,
|
||||
IN EFI_IPv6_ADDRESS *GatewayAddress
|
||||
);
|
||||
|
||||
/**
|
||||
Search the route table to route the packet. Return/create a route
|
||||
cache if there is a route to the destination.
|
||||
|
||||
@param[in] IpSb The IP6 service data.
|
||||
@param[in] Dest The destination address to search for.
|
||||
@param[in] Src The source address to search for.
|
||||
|
||||
@return NULL if failed to route packet. Otherwise, a route cache
|
||||
entry that can be used to route packet.
|
||||
|
||||
**/
|
||||
IP6_ROUTE_CACHE_ENTRY *
|
||||
Ip6Route (
|
||||
IN IP6_SERVICE *IpSb,
|
||||
IN EFI_IPv6_ADDRESS *Dest,
|
||||
IN EFI_IPv6_ADDRESS *Src
|
||||
);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user