Import ArpDxe, Dhcp4Dxe, Ip4Dxe, Mtftp4Dxe, PxeBcDxe and PxeDhcp4Dxe.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3492 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
166
MdeModulePkg/Universal/Network/Ip4Dxe/ComponentName.c
Normal file
166
MdeModulePkg/Universal/Network/Ip4Dxe/ComponentName.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2007, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
ComponentName.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Functions
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
);
|
||||
|
||||
//
|
||||
// EFI Component Name Protocol
|
||||
//
|
||||
EFI_COMPONENT_NAME_PROTOCOL gIp4ComponentName = {
|
||||
Ip4ComponentNameGetDriverName,
|
||||
Ip4ComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
static EFI_UNICODE_STRING_TABLE mIp4DriverNameTable[] = {
|
||||
{
|
||||
"eng",
|
||||
L"IP4 Network Service Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Retrieves a Unicode string that is the user readable
|
||||
name of the EFI Driver.
|
||||
|
||||
Arguments:
|
||||
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
Language - A pointer to a three character ISO 639-2 language
|
||||
identifier. This is the language of the driver name
|
||||
that 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.
|
||||
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.
|
||||
|
||||
Returns:
|
||||
EFI_SUCCES - The Unicode string for the Driver specified by This
|
||||
and the language specified by Language was returned
|
||||
in DriverName.
|
||||
EFI_INVALID_PARAMETER - Language is NULL.
|
||||
EFI_INVALID_PARAMETER - DriverName is NULL.
|
||||
EFI_UNSUPPORTED - The driver specified by This does not support the
|
||||
language specified by Language.
|
||||
|
||||
--*/
|
||||
{
|
||||
return LookupUnicodeString (
|
||||
Language,
|
||||
gIp4ComponentName.SupportedLanguages,
|
||||
mIp4DriverNameTable,
|
||||
DriverName
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Retrieves a Unicode string that is the user readable name of
|
||||
the controller that is being managed by an EFI Driver.
|
||||
|
||||
Arguments:
|
||||
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
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.
|
||||
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.
|
||||
Language - A pointer to a three character ISO 639-2 language
|
||||
identifier. This is the language of the controller name
|
||||
that 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.
|
||||
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.
|
||||
|
||||
Returns:
|
||||
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.
|
||||
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
|
||||
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not
|
||||
a valid EFI_HANDLE.
|
||||
EFI_INVALID_PARAMETER - Language is NULL.
|
||||
EFI_INVALID_PARAMETER - ControllerName is NULL.
|
||||
EFI_UNSUPPORTED - The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
EFI_UNSUPPORTED - The driver specified by This does not support the
|
||||
language specified by Language.
|
||||
|
||||
--*/
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
421
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.c
Normal file
421
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.c
Normal file
@@ -0,0 +1,421 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Common.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Return the cast type (Unicast/Boradcast) specific to a
|
||||
interface. All the addresses are host byte ordered.
|
||||
|
||||
@param IpAddr The IP address to classify in host byte order
|
||||
@param IpIf The interface that IpAddr received from
|
||||
|
||||
@return The cast type of this IP address specific to the interface.
|
||||
@retval IP4_LOCAL_HOST The IpAddr equals to the interface's address
|
||||
@retval IP4_SUBNET_BROADCAST The IpAddr is a directed subnet boradcast to the
|
||||
interface
|
||||
@retval IP4_NET_BROADCAST The IpAddr is a network broadcast to the interface
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4GetNetCast (
|
||||
IN IP4_ADDR IpAddr,
|
||||
IN IP4_INTERFACE *IpIf
|
||||
)
|
||||
{
|
||||
if (IpAddr == IpIf->Ip) {
|
||||
return IP4_LOCAL_HOST;
|
||||
|
||||
} else if (IpAddr == IpIf->SubnetBrdcast) {
|
||||
return IP4_SUBNET_BROADCAST;
|
||||
|
||||
} else if (IpAddr == IpIf->NetBrdcast) {
|
||||
return IP4_NET_BROADCAST;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find the cast type of the packet related to the local host.
|
||||
This isn't the same as link layer cast type. For example, DHCP
|
||||
server may send local broadcast to the local unicast MAC.
|
||||
|
||||
@param IpSb The IP4 service binding instance that received the
|
||||
packet
|
||||
@param Dst The destination address in the packet (host byte
|
||||
order)
|
||||
@param Src The source address in the packet (host byte order)
|
||||
|
||||
@return The cast type for the Dst, it will return on the first non-promiscuous
|
||||
@return cast type to a configured interface. If the packet doesn't match any of
|
||||
@return the interface, multicast address and local broadcast address are checked.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4GetHostCast (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
INTN Type;
|
||||
INTN Class;
|
||||
|
||||
Type = 0;
|
||||
|
||||
if (IpSb->MnpConfigData.EnablePromiscuousReceive) {
|
||||
Type = IP4_PROMISCUOUS;
|
||||
}
|
||||
|
||||
//
|
||||
// Go through the interface list of the IP service, most likely.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
//
|
||||
// Skip the unconfigured interface and invalid source address:
|
||||
// source address can't be broadcast.
|
||||
//
|
||||
if (!IpIf->Configured || IP4_IS_BROADCAST (Ip4GetNetCast (Src, IpIf))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((Class = Ip4GetNetCast (Dst, IpIf)) > Type) {
|
||||
return Class;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If it is local broadcast address. The source address must
|
||||
// be a unicast address on one of the direct connected network.
|
||||
// If it is a multicast address, accept it only if we are in
|
||||
// the group.
|
||||
//
|
||||
if (Dst == IP4_ALLONE_ADDRESS) {
|
||||
IpIf = Ip4FindNet (IpSb, Src);
|
||||
|
||||
if (IpIf && !IP4_IS_BROADCAST (Ip4GetNetCast (Src, IpIf))) {
|
||||
return IP4_LOCAL_BROADCAST;
|
||||
}
|
||||
|
||||
} else if (IP4_IS_MULTICAST (Dst) && Ip4FindGroup (&IpSb->IgmpCtrl, Dst)) {
|
||||
return IP4_MULTICAST;
|
||||
}
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find an interface whose configured IP address is Ip
|
||||
|
||||
@param IpSb The IP4 service binding instance
|
||||
@param Ip The Ip address (host byte order) to find
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindInterface (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && (IpIf->Ip == Ip)) {
|
||||
return IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find an interface that Ip is on that connected network.
|
||||
|
||||
@param IpSb The IP4 service binding instance
|
||||
@param Ip The Ip address (host byte order) to find
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindNet (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && IP4_NET_EQUAL (Ip, IpIf->Ip, IpIf->SubnetMask)) {
|
||||
return IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find an interface of the service with the same Ip/Netmask pair.
|
||||
|
||||
@param IpSb Ip4 service binding instance
|
||||
@param Ip The Ip adress to find (host byte order)
|
||||
@param Netmask The network to find (host byte order)
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindStationAddress (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip,
|
||||
IN IP4_ADDR Netmask
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && (IpIf->Ip == Ip) && (IpIf->SubnetMask == Netmask)) {
|
||||
return IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the MAC address for a multicast IP address. Call
|
||||
Mnp's McastIpToMac to find the MAC address in stead of
|
||||
hard code the NIC to be Ethernet.
|
||||
|
||||
@param Mnp The Mnp instance to get the MAC address.
|
||||
@param Multicast The multicast IP address to translate.
|
||||
@param Mac The buffer to hold the translated address.
|
||||
|
||||
@return Returns EFI_SUCCESS if the multicast IP is successfully
|
||||
@return translated to a multicast MAC address. Otherwise some error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4GetMulticastMac (
|
||||
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
|
||||
IN IP4_ADDR Multicast,
|
||||
OUT EFI_MAC_ADDRESS *Mac
|
||||
)
|
||||
{
|
||||
EFI_IP_ADDRESS EfiIp;
|
||||
|
||||
EFI_IP4 (EfiIp.v4) = HTONL (Multicast);
|
||||
return Mnp->McastIpToMac (Mnp, FALSE, &EfiIp, Mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Convert the multibyte field in IP header's byter order.
|
||||
In spite of its name, it can also be used to convert from
|
||||
host to network byte order.
|
||||
|
||||
@param Head The IP head to convert
|
||||
|
||||
@return Point to the converted IP head
|
||||
|
||||
**/
|
||||
IP4_HEAD *
|
||||
Ip4NtohHead (
|
||||
IN IP4_HEAD *Head
|
||||
)
|
||||
{
|
||||
Head->TotalLen = NTOHS (Head->TotalLen);
|
||||
Head->Id = NTOHS (Head->Id);
|
||||
Head->Fragment = NTOHS (Head->Fragment);
|
||||
Head->Src = NTOHL (Head->Src);
|
||||
Head->Dst = NTOHL (Head->Dst);
|
||||
|
||||
return Head;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Set the Ip4 variable data.
|
||||
|
||||
@param IpSb Ip4 service binding instance
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.
|
||||
@retval other Set variable failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4SetVariableData (
|
||||
IN IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
UINT32 NumConfiguredInstance;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
UINTN VariableDataSize;
|
||||
EFI_IP4_VARIABLE_DATA *Ip4VariableData;
|
||||
EFI_IP4_ADDRESS_PAIR *Ip4AddressPair;
|
||||
IP4_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, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE);
|
||||
|
||||
if (IpInstance->State == IP4_STATE_CONFIGED) {
|
||||
NumConfiguredInstance++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the size of the Ip4VariableData. 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_IP4_VARIABLE_DATA);
|
||||
|
||||
if (NumConfiguredInstance > 1) {
|
||||
VariableDataSize += sizeof (EFI_IP4_ADDRESS_PAIR) * (NumConfiguredInstance - 1);
|
||||
}
|
||||
|
||||
Ip4VariableData = NetAllocatePool (VariableDataSize);
|
||||
if (Ip4VariableData == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Ip4VariableData->DriverHandle = IpSb->Image;
|
||||
Ip4VariableData->AddressCount = NumConfiguredInstance;
|
||||
|
||||
Ip4AddressPair = &Ip4VariableData->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, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE);
|
||||
|
||||
if (IpInstance->State == IP4_STATE_CONFIGED) {
|
||||
Ip4AddressPair->InstanceHandle = IpInstance->Handle;
|
||||
EFI_IP4 (Ip4AddressPair->Ip4Address) = NTOHL (IpInstance->Interface->Ip);
|
||||
EFI_IP4 (Ip4AddressPair->SubnetMask) = NTOHL (IpInstance->Interface->SubnetMask);
|
||||
|
||||
Ip4AddressPair++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get the mac string.
|
||||
//
|
||||
Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &NewMacString);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
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,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
NetFreePool (IpSb->MacString);
|
||||
}
|
||||
|
||||
IpSb->MacString = NewMacString;
|
||||
|
||||
Status = gRT->SetVariable (
|
||||
IpSb->MacString,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
VariableDataSize,
|
||||
(VOID *) Ip4VariableData
|
||||
);
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
NetFreePool (Ip4VariableData);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Clear the variable and free the resource.
|
||||
|
||||
@param IpSb Ip4 service binding instance
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4ClearVariableData (
|
||||
IN IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
ASSERT (IpSb->MacString != NULL);
|
||||
|
||||
gRT->SetVariable (
|
||||
IpSb->MacString,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
NetFreePool (IpSb->MacString);
|
||||
IpSb->MacString = NULL;
|
||||
}
|
143
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.h
Normal file
143
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Common.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Common definition for IP4.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_COMMON_H__
|
||||
#define __EFI_IP4_COMMON_H__
|
||||
|
||||
typedef struct _IP4_INTERFACE IP4_INTERFACE;
|
||||
typedef struct _IP4_PROTOCOL IP4_PROTOCOL;
|
||||
typedef struct _IP4_SERVICE IP4_SERVICE;
|
||||
|
||||
|
||||
enum {
|
||||
IP4_ETHER_PROTO = 0x0800,
|
||||
|
||||
IP4_PROTO_ICMP = 0x01,
|
||||
IP4_PROTO_IGMP = 0x02,
|
||||
|
||||
//
|
||||
// The packet is received as link level broadcast/multicast/promiscuous.
|
||||
//
|
||||
IP4_LINK_BROADCAST = 0x00000001,
|
||||
IP4_LINK_MULTICAST = 0x00000002,
|
||||
IP4_LINK_PROMISC = 0x00000004,
|
||||
|
||||
//
|
||||
// IP4 address cast type classfication. Keep it true that any
|
||||
// type bigger than or equal to LOCAL_BROADCAST is broadcast.
|
||||
//
|
||||
IP4_PROMISCUOUS = 1,
|
||||
IP4_LOCAL_HOST,
|
||||
IP4_MULTICAST,
|
||||
IP4_LOCAL_BROADCAST, // Destination is 255.255.255.255
|
||||
IP4_SUBNET_BROADCAST,
|
||||
IP4_NET_BROADCAST,
|
||||
|
||||
//
|
||||
// IP4 header flags
|
||||
//
|
||||
IP4_HEAD_DF_MASK = 0x4000,
|
||||
IP4_HEAD_MF_MASK = 0x2000,
|
||||
IP4_HEAD_OFFSET_MASK = 0x1fff,
|
||||
};
|
||||
|
||||
#define IP4_ALLZERO_ADDRESS 0x00000000u
|
||||
#define IP4_ALLONE_ADDRESS 0xFFFFFFFFu
|
||||
#define IP4_ALLSYSTEM_ADDRESS 0xE0000001u
|
||||
#define IP4_ALLROUTER_ADDRESS 0xE0000002u
|
||||
|
||||
//
|
||||
// Compose the fragment field to be used in the IP4 header.
|
||||
//
|
||||
#define IP4_HEAD_FRAGMENT_FIELD(Df, Mf, Offset) \
|
||||
((UINT16)(((Df) ? 0x4000 : 0) | ((Mf) ? 0x2000 : 0) | (((Offset) >> 3) & 0x1fff)))
|
||||
|
||||
#define IP4_LAST_FRAGMENT(FragmentField) \
|
||||
(((FragmentField) & IP4_HEAD_MF_MASK) == 0)
|
||||
|
||||
#define IP4_FIRST_FRAGMENT(FragmentField) \
|
||||
((BOOLEAN)(((FragmentField) & IP4_HEAD_OFFSET_MASK) == 0))
|
||||
|
||||
#define IP4_IS_BROADCAST(CastType) ((CastType) >= IP4_LOCAL_BROADCAST)
|
||||
|
||||
//
|
||||
// Conver the Microsecond to second. IP transmit/receive time is
|
||||
// in the unit of microsecond. IP ticks once per second.
|
||||
//
|
||||
#define IP4_US_TO_SEC(Us) (((Us) + 999999) / 1000000)
|
||||
|
||||
INTN
|
||||
Ip4GetNetCast (
|
||||
IN IP4_ADDR IpAddr,
|
||||
IN IP4_INTERFACE *IpIf
|
||||
);
|
||||
|
||||
INTN
|
||||
Ip4GetHostCast (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src
|
||||
);
|
||||
|
||||
IP4_INTERFACE *
|
||||
Ip4FindInterface (
|
||||
IN IP4_SERVICE *IpService,
|
||||
IN IP4_ADDR Addr
|
||||
);
|
||||
|
||||
IP4_INTERFACE *
|
||||
Ip4FindNet (
|
||||
IN IP4_SERVICE *IpService,
|
||||
IN IP4_ADDR Addr
|
||||
);
|
||||
|
||||
IP4_INTERFACE *
|
||||
Ip4FindStationAddress (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip,
|
||||
IN IP4_ADDR Netmask
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4GetMulticastMac (
|
||||
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
|
||||
IN IP4_ADDR Multicast,
|
||||
OUT EFI_MAC_ADDRESS *Mac
|
||||
);
|
||||
|
||||
IP4_HEAD *
|
||||
Ip4NtohHead (
|
||||
IN IP4_HEAD *Head
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4SetVariableData (
|
||||
IN IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4ClearVariableData (
|
||||
IN IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
#endif
|
932
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
Normal file
932
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
Normal file
@@ -0,0 +1,932 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Driver.c
|
||||
|
||||
Abstract:
|
||||
|
||||
The driver binding and service binding protocol for IP4 driver.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding = {
|
||||
Ip4DriverBindingSupported,
|
||||
Ip4DriverBindingStart,
|
||||
Ip4DriverBindingStop,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
//@MT: EFI_DRIVER_ENTRY_POINT (Ip4DriverEntryPoint)
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The entry point for IP4 driver which install the driver
|
||||
binding and component name protocol on its image.
|
||||
|
||||
Arguments:
|
||||
|
||||
ImageHandle - The image handle of the driver
|
||||
SystemTable - The system table
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS if the driver binding and component name protocols
|
||||
are successfully installed, otherwise if failed.
|
||||
|
||||
--*/
|
||||
{
|
||||
return NetLibInstallAllDriverProtocols (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gIp4DriverBinding,
|
||||
ImageHandle,
|
||||
&gIp4ComponentName,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to test
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCES This driver supports this device
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on this device
|
||||
@retval other This driver does not support this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL * This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Test for the MNP service binding Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Test for the Arp service binding Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiArpServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Ip4CleanService (
|
||||
IN IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Create a new IP4 driver service binding protocol
|
||||
|
||||
@param Controller The controller that has MNP service binding
|
||||
installed
|
||||
@param ImageHandle The IP4 driver's image handle
|
||||
@param Service The variable to receive the newly created IP4
|
||||
service.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resource
|
||||
@retval EFI_SUCCESS A new IP4 service binding private is created.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Ip4CreateService (
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
OUT IP4_SERVICE **Service
|
||||
)
|
||||
{
|
||||
IP4_SERVICE *IpSb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
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, Ip4CleanService can be called to clean it up.
|
||||
//
|
||||
IpSb = NetAllocatePool (sizeof (IP4_SERVICE));
|
||||
|
||||
if (IpSb == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
IpSb->Signature = IP4_SERVICE_SIGNATURE;
|
||||
IpSb->ServiceBinding.CreateChild = Ip4ServiceBindingCreateChild;
|
||||
IpSb->ServiceBinding.DestroyChild = Ip4ServiceBindingDestroyChild;
|
||||
IpSb->State = IP4_SERVICE_UNSTARTED;
|
||||
IpSb->InDestory = FALSE;
|
||||
|
||||
IpSb->NumChildren = 0;
|
||||
NetListInit (&IpSb->Children);
|
||||
|
||||
NetListInit (&IpSb->Interfaces);
|
||||
IpSb->DefaultInterface = NULL;
|
||||
IpSb->DefaultRouteTable = NULL;
|
||||
|
||||
Ip4InitAssembleTable (&IpSb->Assemble);
|
||||
|
||||
IpSb->IgmpCtrl.Igmpv1QuerySeen = 0;
|
||||
NetListInit (&IpSb->IgmpCtrl.Groups);
|
||||
|
||||
IpSb->Image = ImageHandle;
|
||||
IpSb->Controller = Controller;
|
||||
|
||||
IpSb->MnpChildHandle = NULL;
|
||||
IpSb->Mnp = NULL;
|
||||
|
||||
IpSb->MnpConfigData.ReceivedQueueTimeoutValue = 0;
|
||||
IpSb->MnpConfigData.TransmitQueueTimeoutValue = 0;
|
||||
IpSb->MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO;
|
||||
IpSb->MnpConfigData.EnableUnicastReceive = TRUE;
|
||||
IpSb->MnpConfigData.EnableMulticastReceive = TRUE;
|
||||
IpSb->MnpConfigData.EnableBroadcastReceive = TRUE;
|
||||
IpSb->MnpConfigData.EnablePromiscuousReceive = FALSE;
|
||||
IpSb->MnpConfigData.FlushQueuesOnReset = TRUE;
|
||||
IpSb->MnpConfigData.EnableReceiveTimestamps = FALSE;
|
||||
IpSb->MnpConfigData.DisableBackgroundPolling = FALSE;
|
||||
|
||||
NetZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));
|
||||
|
||||
IpSb->Timer = NULL;
|
||||
IpSb->Ip4Config = NULL;
|
||||
IpSb->DoneEvent = NULL;
|
||||
IpSb->ReconfigEvent = NULL;
|
||||
|
||||
//
|
||||
// Create various resources. First create the route table, timer
|
||||
// event and MNP child. IGMP, interface's initialization depend
|
||||
// on the MNP child.
|
||||
//
|
||||
IpSb->DefaultRouteTable = Ip4CreateRouteTable ();
|
||||
|
||||
if (IpSb->DefaultRouteTable == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
||||
TPL_CALLBACK,
|
||||
Ip4TimerTicking,
|
||||
IpSb,
|
||||
&IpSb->Timer
|
||||
);
|
||||
|
||||
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 = Ip4ServiceConfigMnp (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;
|
||||
}
|
||||
|
||||
Status = Ip4InitIgmp (IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
IpSb->DefaultInterface = Ip4CreateInterface (IpSb->Mnp, Controller, ImageHandle);
|
||||
|
||||
if (IpSb->DefaultInterface == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
NetListInsertHead (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);
|
||||
|
||||
IpSb->MacString = NULL;
|
||||
|
||||
*Service = IpSb;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
Ip4CleanService (IpSb);
|
||||
NetFreePool (IpSb);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Clean up a IP4 service binding instance. It will release all
|
||||
the resource allocated by the instance. The instance may be
|
||||
partly initialized, or partly destoried. If a resource is
|
||||
destoried, it is marked as that in case the destory failed and
|
||||
being called again later.
|
||||
|
||||
@param IpSb The IP4 serviceing 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
|
||||
Ip4CleanService (
|
||||
IN IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (IpSb->DefaultInterface != NULL) {
|
||||
Status = Ip4FreeInterface (IpSb->DefaultInterface, NULL);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
IpSb->DefaultInterface = NULL;
|
||||
}
|
||||
|
||||
if (IpSb->DefaultRouteTable != NULL) {
|
||||
Ip4FreeRouteTable (IpSb->DefaultRouteTable);
|
||||
IpSb->DefaultRouteTable = NULL;
|
||||
}
|
||||
|
||||
Ip4CleanAssembleTable (&IpSb->Assemble);
|
||||
|
||||
if (IpSb->MnpChildHandle != NULL) {
|
||||
if (IpSb->Mnp) {
|
||||
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->Timer != NULL) {
|
||||
gBS->SetTimer (IpSb->Timer, TimerCancel, 0);
|
||||
gBS->CloseEvent (IpSb->Timer);
|
||||
|
||||
IpSb->Timer = NULL;
|
||||
}
|
||||
|
||||
if (IpSb->Ip4Config != NULL) {
|
||||
IpSb->Ip4Config->Stop (IpSb->Ip4Config);
|
||||
|
||||
gBS->CloseProtocol (
|
||||
IpSb->Controller,
|
||||
&gEfiIp4ConfigProtocolGuid,
|
||||
IpSb->Image,
|
||||
IpSb->Controller
|
||||
);
|
||||
|
||||
gBS->CloseEvent (IpSb->DoneEvent);
|
||||
gBS->CloseEvent (IpSb->ReconfigEvent);
|
||||
IpSb->Ip4Config = NULL;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to bind driver to
|
||||
@param RemainingDevicePath Optional parameter use 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
|
||||
Ip4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL * This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
IP4_SERVICE *IpSb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Test for the Ip4 service binding protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (Status == EFI_SUCCESS) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the Ip4ServiceBinding Protocol onto ControlerHandle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&ControllerHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
&IpSb->ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto FREE_SERVICE;
|
||||
}
|
||||
|
||||
//
|
||||
// ready to go: start the receiving and timer
|
||||
//
|
||||
Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto UNINSTALL_PROTOCOL;
|
||||
}
|
||||
|
||||
Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto UNINSTALL_PROTOCOL;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the IP4 ID
|
||||
//
|
||||
mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());
|
||||
|
||||
Ip4SetVariableData (IpSb);
|
||||
|
||||
return Status;
|
||||
|
||||
UNINSTALL_PROTOCOL:
|
||||
gBS->UninstallProtocolInterface (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
&IpSb->ServiceBinding
|
||||
);
|
||||
|
||||
FREE_SERVICE:
|
||||
Ip4CleanService (IpSb);
|
||||
NetFreePool (IpSb);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to stop driver on
|
||||
@param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
|
||||
of children is zero stop the entire bus driver.
|
||||
@param ChildHandleBuffer List of Child Handles to Stop.
|
||||
|
||||
@retval EFI_SUCCES This driver is removed ControllerHandle
|
||||
@retval other This driver was not removed from this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
IP4_SERVICE *IpSb;
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
EFI_HANDLE NicHandle;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
INTN State;
|
||||
|
||||
//
|
||||
// IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol
|
||||
// by driver. So the ControllerHandle may be the MNP child handle, ARP child
|
||||
// handle, or the NIC (UNDI) handle because IP4_CONFIG protocol is installed
|
||||
// in the NIC handle.
|
||||
//
|
||||
//
|
||||
// First, check whether it is the IP4_CONFIG protocol being uninstalled.
|
||||
// IP4_CONFIG protocol is installed on the NIC handle. It isn't necessary
|
||||
// to clean up the default configuration if IP4_CONFIG is being stopped.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ConfigProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (Status == EFI_SUCCESS) {
|
||||
//
|
||||
// Retrieve the IP4 service binding protocol. If failed, it is
|
||||
// likely that Ip4 ServiceBinding is uninstalled already. In this
|
||||
// case, return immediately.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
(VOID **) &ServiceBinding,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
if (IpSb->Ip4Config && (IpSb->State != IP4_SERVICE_DESTORY)) {
|
||||
|
||||
IpSb->Ip4Config->Stop (IpSb->Ip4Config);
|
||||
|
||||
Status = gBS->CloseProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ConfigProtocolGuid,
|
||||
IpSb->Image,
|
||||
ControllerHandle
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// If the auto configure hasn't complete, mark it as not started.
|
||||
//
|
||||
if (IpSb->State == IP4_SERVICE_STARTED) {
|
||||
IpSb->State = IP4_SERVICE_UNSTARTED;
|
||||
}
|
||||
|
||||
IpSb->Ip4Config = NULL;
|
||||
gBS->CloseEvent (IpSb->DoneEvent);
|
||||
gBS->CloseEvent (IpSb->ReconfigEvent);
|
||||
}
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Either MNP or ARP protocol is being uninstalled. The controller
|
||||
// handle is either the MNP child or ARP child. But, the IP4's
|
||||
// service binding is installed on the NIC handle. So, need to open
|
||||
// the protocol info to find the NIC handle.
|
||||
//
|
||||
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
|
||||
|
||||
if (NicHandle == NULL) {
|
||||
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
|
||||
}
|
||||
|
||||
if (NicHandle == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the IP4 service binding protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
NicHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
(VOID **) &ServiceBinding,
|
||||
This->DriverBindingHandle,
|
||||
NicHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
if (IpSb->InDestory) {
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
IpSb->InDestory = TRUE;
|
||||
|
||||
State = IpSb->State;
|
||||
IpSb->State = IP4_SERVICE_DESTORY;
|
||||
|
||||
//
|
||||
// Destory all the children first. If not all children are destoried,
|
||||
// the IP driver can operate correctly, so restore it state. Don't
|
||||
// use NET_LIST_FOR_EACH_SAFE here, because it will cache the next
|
||||
// pointer, which may point to the child that has already been destoried.
|
||||
// For example, if there are two child in the list, the first is UDP
|
||||
// listen child, the send is the MTFTP's child. When Udp child is
|
||||
// destoried, it will destory the MTFTP's child. Then Next point to
|
||||
// a invalid child.
|
||||
//
|
||||
while (!NetListIsEmpty (&IpSb->Children)) {
|
||||
IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);
|
||||
Ip4ServiceBindingDestroyChild (ServiceBinding, IpInstance->Handle);
|
||||
}
|
||||
|
||||
if (IpSb->NumChildren != 0) {
|
||||
IpSb->State = State;
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Clear the variable data.
|
||||
//
|
||||
Ip4ClearVariableData (IpSb);
|
||||
|
||||
//
|
||||
// OK, clean other resources then uninstall the service binding protocol.
|
||||
//
|
||||
Status = Ip4CleanService (IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
NicHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
ServiceBinding
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
NetFreePool (IpSb);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
IpSb->InDestory = FALSE;
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates a child handle with a set of I/O services.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param 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
|
||||
Ip4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
)
|
||||
{
|
||||
IP4_SERVICE *IpSb;
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
VOID *Mnp;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
IpSb = IP4_SERVICE_FROM_PROTOCOL (This);
|
||||
IpInstance = NetAllocatePool (sizeof (IP4_PROTOCOL));
|
||||
|
||||
if (IpInstance == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Ip4InitProtocol (IpSb, IpInstance);
|
||||
|
||||
//
|
||||
// Install Ip4 onto ChildHandle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
&IpInstance->Ip4Proto,
|
||||
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,
|
||||
gIp4DriverBinding.DriverBindingHandle,
|
||||
IpInstance->Handle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
&IpInstance->Ip4Proto,
|
||||
NULL
|
||||
);
|
||||
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert it into the service binding instance.
|
||||
//
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
NetListInsertTail (&IpSb->Children, &IpInstance->Link);
|
||||
IpSb->NumChildren++;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
Ip4CleanProtocol (IpInstance);
|
||||
|
||||
NetFreePool (IpInstance);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destroys a child handle with a set of I/O services.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param 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
|
||||
Ip4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IP4_SERVICE *IpSb;
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
EFI_IP4_PROTOCOL *Ip4;
|
||||
EFI_TPL OldTpl;
|
||||
INTN State;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the private context data structures
|
||||
//
|
||||
IpSb = IP4_SERVICE_FROM_PROTOCOL (This);
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
(VOID **) &Ip4,
|
||||
gIp4DriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
IpInstance = IP4_INSTANCE_FROM_PROTOCOL (Ip4);
|
||||
|
||||
if (IpInstance->Service != IpSb) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
//
|
||||
// A child can be destoried more than once. For example,
|
||||
// Ip4DriverBindingStop will destory all of its children.
|
||||
// when UDP driver is being stopped, it will destory all
|
||||
// the IP child it opens.
|
||||
//
|
||||
if (IpInstance->State == IP4_STATE_DESTORY) {
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
State = IpInstance->State;
|
||||
IpInstance->State = IP4_STATE_DESTORY;
|
||||
|
||||
//
|
||||
// Close the Managed Network protocol.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
IpSb->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
gIp4DriverBinding.DriverBindingHandle,
|
||||
ChildHandle
|
||||
);
|
||||
|
||||
//
|
||||
// Uninstall the IP4 protocol first. Many thing happens during
|
||||
// this:
|
||||
// 1. The consumer of the IP4 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_IP4_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,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
&IpInstance->Ip4Proto
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip4CleanProtocol (IpInstance);
|
||||
|
||||
Ip4SetVariableData (IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->InstallMultipleProtocolInterfaces (
|
||||
&ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
Ip4,
|
||||
NULL
|
||||
);
|
||||
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
NetListRemoveEntry (&IpInstance->Link);
|
||||
IpSb->NumChildren--;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
NetFreePool (IpInstance);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
IpInstance->State = State;
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
84
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.h
Normal file
84
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2007, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Driver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_DRIVER_H__
|
||||
#define __EFI_IP4_DRIVER_H__
|
||||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
|
||||
extern EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding;
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gIp4ComponentName;
|
||||
|
||||
//
|
||||
// Function prototype for the driver's entry point
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
//
|
||||
// Function prototypes for the Drivr Binding Protocol
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
//
|
||||
// Function ptototypes for the ServiceBinding Prococol
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
);
|
||||
#endif
|
81
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf
Normal file
81
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf
Normal file
@@ -0,0 +1,81 @@
|
||||
#/** @file
|
||||
# Component name for module Ip4
|
||||
#
|
||||
# Copyright (c) 2007, Intel Corporation
|
||||
#
|
||||
# All rights reserved. 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 = Ip4Dxe
|
||||
FILE_GUID = 9FB1A1F3-3B71-4324-B39A-745CBB015FFF
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
EDK_RELEASE_VERSION = 0x00020000
|
||||
EFI_SPECIFICATION_VERSION = 0x00020000
|
||||
|
||||
ENTRY_POINT = Ip4DriverEntryPoint
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
Ip4Driver.c
|
||||
Ip4Option.h
|
||||
Ip4Route.h
|
||||
Ip4If.c
|
||||
Ip4Igmp.h
|
||||
Ip4Output.c
|
||||
Ip4Icmp.c
|
||||
Ip4Igmp.c
|
||||
Ip4Impl.c
|
||||
Ip4Common.h
|
||||
Ip4Impl.h
|
||||
Ip4Driver.h
|
||||
Ip4Common.c
|
||||
Ip4If.h
|
||||
Ip4Option.c
|
||||
Ip4Output.h
|
||||
ComponentName.c
|
||||
Ip4Input.h
|
||||
Ip4Route.c
|
||||
Ip4Icmp.h
|
||||
Ip4Input.c
|
||||
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
UefiLib
|
||||
BaseLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
DebugLib
|
||||
NetLib
|
||||
|
||||
|
||||
[Protocols]
|
||||
gEfiIp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiManagedNetworkServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiIp4ConfigProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiArpServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiIp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiManagedNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiArpProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
|
101
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.msa
Normal file
101
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.msa
Normal file
@@ -0,0 +1,101 @@
|
||||
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<MsaHeader>
|
||||
<ModuleName>Ip4Dxe</ModuleName>
|
||||
<ModuleType>DXE_DRIVER</ModuleType>
|
||||
<GuidValue>9FB1A1F3-3B71-4324-B39A-745CBB015FFF</GuidValue>
|
||||
<Version>1.0</Version>
|
||||
<Abstract>Component name for module Ip4</Abstract>
|
||||
<Description>FIX ME!</Description>
|
||||
<Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>
|
||||
<License>All rights reserved. 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.</License>
|
||||
<Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
|
||||
</MsaHeader>
|
||||
<ModuleDefinitions>
|
||||
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
|
||||
<BinaryModule>false</BinaryModule>
|
||||
<OutputFileBasename>Ip4Dxe</OutputFileBasename>
|
||||
</ModuleDefinitions>
|
||||
<LibraryClassDefinitions>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>DebugLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiRuntimeServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiDriverEntryPoint</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiBootServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>BaseLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiLib</Keyword>
|
||||
</LibraryClass>
|
||||
</LibraryClassDefinitions>
|
||||
<SourceFiles>
|
||||
<Filename>Ip4Input.c</Filename>
|
||||
<Filename>Ip4Icmp.h</Filename>
|
||||
<Filename>Ip4Route.c</Filename>
|
||||
<Filename>Ip4Input.h</Filename>
|
||||
<Filename>ComponentName.c</Filename>
|
||||
<Filename>Ip4Output.h</Filename>
|
||||
<Filename>Ip4Option.c</Filename>
|
||||
<Filename>Ip4If.h</Filename>
|
||||
<Filename>Ip4Common.c</Filename>
|
||||
<Filename>Ip4Driver.h</Filename>
|
||||
<Filename>Ip4Impl.h</Filename>
|
||||
<Filename>Ip4Common.h</Filename>
|
||||
<Filename>Ip4Impl.c</Filename>
|
||||
<Filename>Ip4Igmp.c</Filename>
|
||||
<Filename>Ip4Icmp.c</Filename>
|
||||
<Filename>Ip4Output.c</Filename>
|
||||
<Filename>Ip4Igmp.h</Filename>
|
||||
<Filename>Ip4If.c</Filename>
|
||||
<Filename>Ip4Route.h</Filename>
|
||||
<Filename>Ip4Option.h</Filename>
|
||||
<Filename>Ip4Driver.c</Filename>
|
||||
</SourceFiles>
|
||||
<PackageDependencies>
|
||||
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
|
||||
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
|
||||
</PackageDependencies>
|
||||
<Protocols>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiArpProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiManagedNetworkProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiIp4ServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiArpServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiIp4ConfigProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiManagedNetworkServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiIp4ProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
</Protocols>
|
||||
<Externs>
|
||||
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
|
||||
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
|
||||
<Extern>
|
||||
<ModuleEntryPoint>Ip4DriverEntryPoint</ModuleEntryPoint>
|
||||
</Extern>
|
||||
</Externs>
|
||||
</ModuleSurfaceArea>
|
372
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Icmp.c
Normal file
372
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Icmp.c
Normal file
@@ -0,0 +1,372 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Icmp.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
IP4_ICMP_CLASS
|
||||
mIcmpClass[] = {
|
||||
{ICMP_ECHO_REPLY, ICMP_QUERY_MESSAGE },
|
||||
{1, ICMP_INVALID_MESSAGE},
|
||||
{2, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_SOURCE_QUENCH, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_REDIRECT, ICMP_ERROR_MESSAGE },
|
||||
{6, ICMP_INVALID_MESSAGE},
|
||||
{7, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_ECHO_REQUEST, ICMP_QUERY_MESSAGE },
|
||||
{9, ICMP_INVALID_MESSAGE},
|
||||
{10, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_TIME_EXCEEDED, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_PARAMETER_PROBLEM, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_TIMESTAMP , ICMP_QUERY_MESSAGE },
|
||||
{14, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_INFO_REQUEST , ICMP_QUERY_MESSAGE },
|
||||
{ICMP_INFO_REPLY , ICMP_QUERY_MESSAGE },
|
||||
};
|
||||
|
||||
EFI_IP4_ICMP_TYPE
|
||||
mIp4SupportedIcmp [23] = {
|
||||
{ICMP_ECHO_REPLY, ICMP_DEFAULT_CODE },
|
||||
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_PROTO_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_PORT_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_FRAGMENT_FAILED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_SOURCEROUTE_FAILED},
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNKNOWN },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNKNOWN },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_SOURCE_ISOLATED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_PROHIBITED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_PROHIBITED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACHABLE_TOS },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNREACHABLE_TOS},
|
||||
|
||||
{ICMP_SOURCE_QUENCH, ICMP_DEFAULT_CODE },
|
||||
|
||||
{ICMP_REDIRECT, ICMP_NET_REDIRECT },
|
||||
{ICMP_REDIRECT, ICMP_HOST_REDIRECT },
|
||||
{ICMP_REDIRECT, ICMP_NET_TOS_REDIRECT },
|
||||
{ICMP_REDIRECT, ICMP_HOST_TOS_REDIRECT },
|
||||
|
||||
{ICMP_ECHO_REQUEST, ICMP_DEFAULT_CODE },
|
||||
|
||||
{ICMP_TIME_EXCEEDED, ICMP_TIMEOUT_IN_TRANSIT},
|
||||
{ICMP_TIME_EXCEEDED, ICMp_TIMEOUT_REASSEMBLE},
|
||||
|
||||
{ICMP_PARAMETER_PROBLEM, ICMP_DEFAULT_CODE },
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Process the ICMP redirect. Find the instance then update
|
||||
its route cache.
|
||||
All kinds of redirect is treated as host redirect as
|
||||
specified by RFC1122 3.3.1.2:
|
||||
"Since the subnet mask appropriate to the destination
|
||||
address is generally not known, a Network Redirect
|
||||
message SHOULD be treated identically to a Host Redirect
|
||||
message;"
|
||||
|
||||
@param IpSb The IP4 service binding instance that received the
|
||||
packet
|
||||
@param Head The IP head of the received ICMPpacket.
|
||||
@param Packet The content of the ICMP redirect packet with IP
|
||||
head removed.
|
||||
@param Icmp The buffer to store the ICMP error message if
|
||||
something is wrong.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invalid
|
||||
@retval EFI_SUCCESS Successfully updated the route caches
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Ip4ProcessIcmpRedirect (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_ICMP_ERROR_HEAD *Icmp
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_PROTOCOL *Ip4Instance;
|
||||
IP4_ROUTE_CACHE_ENTRY *CacheEntry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
IP4_ADDR Gateway;
|
||||
|
||||
//
|
||||
// Find the interface whose IP address is the source of the
|
||||
// orgianl IP packet.
|
||||
//
|
||||
IpIf = Ip4FindInterface (IpSb, NTOHL (Icmp->IpHead.Src));
|
||||
Gateway = NTOHL (Icmp->Fourth);
|
||||
|
||||
//
|
||||
// discard the packet if the new gateway address it specifies
|
||||
// is not on the same connected net through which the Redirect
|
||||
// arrived. (RFC1122 3.2.2.2).
|
||||
//
|
||||
if ((IpIf == NULL) || !IP4_NET_EQUAL (Gateway, IpIf->Ip, IpIf->SubnetMask)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Update each IP child's route cache on the interface.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
|
||||
Ip4Instance = NET_LIST_USER_STRUCT (Entry, IP4_PROTOCOL, AddrLink);
|
||||
|
||||
if (Ip4Instance->RouteTable == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CacheEntry = Ip4FindRouteCache (
|
||||
Ip4Instance->RouteTable,
|
||||
NTOHL (Icmp->IpHead.Dst),
|
||||
NTOHL (Icmp->IpHead.Src)
|
||||
);
|
||||
|
||||
//
|
||||
// Only update the route cache's gateway if the source of the
|
||||
// Redirect is the current first-hop gateway
|
||||
//
|
||||
if ((CacheEntry != NULL) && (NTOHL (Head->Src) == CacheEntry->NextHop)) {
|
||||
CacheEntry->NextHop = Gateway;
|
||||
}
|
||||
}
|
||||
|
||||
NetbufFree (Packet);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Process the ICMP error packet. If it is an ICMP redirect packet,
|
||||
update call Ip4ProcessIcmpRedirect to update the IP instance's
|
||||
route cache, otherwise, deliver the packet to upper layer.
|
||||
|
||||
@param IpSb The IP service that received the packet.
|
||||
@param Head The IP head of the ICMP error packet
|
||||
@param Packet The content of the ICMP error with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid
|
||||
@retval Others Failed to process the packet.
|
||||
@retval EFI_SUCCESS The ICMP error is processed successfully.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Ip4ProcessIcmpError (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_ERROR_HEAD Icmp;
|
||||
|
||||
if (Packet->TotalSize < sizeof (Icmp)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
|
||||
//
|
||||
// If it is an ICMP redirect error, update the route cache
|
||||
// as RFC1122. Otherwise, demultiplex it to IP instances.
|
||||
//
|
||||
if (Icmp.Head.Type == ICMP_REDIRECT) {
|
||||
return Ip4ProcessIcmpRedirect (IpSb, Head, Packet, &Icmp);
|
||||
}
|
||||
|
||||
IP4_GET_CLIP_INFO (Packet)->Status = EFI_ICMP_ERROR;
|
||||
return Ip4Demultiplex (IpSb, Head, Packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Replay an ICMP echo request.
|
||||
|
||||
@param IpSb The IP service that receivd the packet
|
||||
@param Head The IP head of the ICMP error packet
|
||||
@param Packet The content of the ICMP error with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
|
||||
@retval EFI_SUCCESS The ICMP Echo request is successfully answered.
|
||||
@retval Others Failed to answer the ICMP echo request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IcmpReplyEcho (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_QUERY_HEAD *Icmp;
|
||||
NET_BUF *Data;
|
||||
EFI_STATUS Status;
|
||||
IP4_HEAD ReplyHead;
|
||||
|
||||
//
|
||||
// make a copy the packet, it is really a bad idea to
|
||||
// send the MNP's buffer back to MNP.
|
||||
//
|
||||
Data = NetbufDuplicate (Packet, NULL, IP4_MAX_HEADLEN);
|
||||
|
||||
if (Data == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Change the ICMP type to echo reply, exchange the source
|
||||
// and destination, then send it. The source is updated to
|
||||
// use specific destination. See RFC1122. SRR/RR option
|
||||
// update is omitted.
|
||||
//
|
||||
Icmp = (IP4_ICMP_QUERY_HEAD *) NetbufGetByte (Data, 0, NULL);
|
||||
Icmp->Head.Type = ICMP_ECHO_REPLY;
|
||||
Icmp->Head.Checksum = 0;
|
||||
Icmp->Head.Checksum = ~NetblockChecksum ((UINT8 *) Icmp, Data->TotalSize);
|
||||
|
||||
ReplyHead.Tos = 0;
|
||||
ReplyHead.Fragment = 0;
|
||||
ReplyHead.Ttl = 64;
|
||||
ReplyHead.Protocol = IP4_PROTO_ICMP;
|
||||
ReplyHead.Src = 0;
|
||||
|
||||
//
|
||||
// Ip4Output will select a source for us
|
||||
//
|
||||
ReplyHead.Dst = Head->Src;
|
||||
|
||||
Status = Ip4Output (
|
||||
IpSb,
|
||||
NULL,
|
||||
Data,
|
||||
&ReplyHead,
|
||||
NULL,
|
||||
0,
|
||||
IP4_ALLZERO_ADDRESS,
|
||||
Ip4SysPacketSent,
|
||||
NULL
|
||||
);
|
||||
|
||||
ON_EXIT:
|
||||
NetbufFree (Packet);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Process the ICMP query message. If it is an ICMP echo
|
||||
request, answer it. Otherwise deliver it to upper layer.
|
||||
|
||||
@param IpSb The IP service that receivd the packet
|
||||
@param Head The IP head of the ICMP query packet
|
||||
@param Packet The content of the ICMP query with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid
|
||||
@retval EFI_SUCCESS The ICMP query message is processed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4ProcessIcmpQuery (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_QUERY_HEAD Icmp;
|
||||
|
||||
if (Packet->TotalSize < sizeof (Icmp)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
|
||||
if (Icmp.Head.Type == ICMP_ECHO_REQUEST) {
|
||||
return Ip4IcmpReplyEcho (IpSb, Head, Packet);
|
||||
}
|
||||
|
||||
return Ip4Demultiplex (IpSb, Head, Packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Handle the ICMP packet. First validate the message format,
|
||||
then according to the message types, process it as query or
|
||||
error packet.
|
||||
|
||||
@param IpSb The IP service that receivd the packet
|
||||
@param Head The IP head of the ICMP query packet
|
||||
@param Packet The content of the ICMP query with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformated.
|
||||
@retval EFI_SUCCESS The ICMP message is successfully processed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IcmpHandle (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_HEAD Icmp;
|
||||
UINT16 Checksum;
|
||||
|
||||
if (Packet->TotalSize < sizeof (Icmp)) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
|
||||
if (Icmp.Type > ICMP_TYPE_MAX) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
Checksum = ~NetbufChecksum (Packet);
|
||||
if ((Icmp.Checksum != 0) && (Checksum != 0)) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_ERROR_MESSAGE) {
|
||||
return Ip4ProcessIcmpError (IpSb, Head, Packet);
|
||||
|
||||
} else if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_QUERY_MESSAGE) {
|
||||
return Ip4ProcessIcmpQuery (IpSb, Head, Packet);
|
||||
|
||||
}
|
||||
|
||||
DROP:
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
99
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Icmp.h
Normal file
99
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Icmp.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Icmp.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Header file for ICMP protocol.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_ICMP_H__
|
||||
#define __EFI_IP4_ICMP_H__
|
||||
|
||||
enum {
|
||||
//
|
||||
// ICMP type definations
|
||||
//
|
||||
ICMP_ECHO_REPLY = 0,
|
||||
ICMP_DEST_UNREACHABLE = 3,
|
||||
ICMP_SOURCE_QUENCH = 4,
|
||||
ICMP_REDIRECT = 5,
|
||||
ICMP_ECHO_REQUEST = 8,
|
||||
ICMP_TIME_EXCEEDED = 11,
|
||||
ICMP_PARAMETER_PROBLEM = 12,
|
||||
ICMP_TIMESTAMP = 13,
|
||||
ICMP_INFO_REQUEST = 15,
|
||||
ICMP_INFO_REPLY = 16,
|
||||
ICMP_TYPE_MAX = ICMP_INFO_REPLY,
|
||||
|
||||
ICMP_DEFAULT_CODE = 0,
|
||||
|
||||
//
|
||||
// ICMP code definations for ICMP_DEST_UNREACHABLE
|
||||
//
|
||||
ICMP_NET_UNREACHABLE = 0,
|
||||
ICMP_HOST_UNREACHABLE = 1,
|
||||
ICMP_PROTO_UNREACHABLE = 2, // Host may generate
|
||||
ICMP_PORT_UNREACHABLE = 3, // Host may generate
|
||||
ICMP_FRAGMENT_FAILED = 4,
|
||||
ICMP_SOURCEROUTE_FAILED = 5, // Host may generate
|
||||
ICMP_NET_UNKNOWN = 6,
|
||||
ICMP_HOST_UNKNOWN = 7,
|
||||
ICMP_SOURCE_ISOLATED = 8,
|
||||
ICMP_NET_PROHIBITED = 9,
|
||||
ICMP_HOST_PROHIBITED = 10,
|
||||
ICMP_NET_UNREACHABLE_TOS = 11,
|
||||
ICMP_HOST_UNREACHABLE_TOS = 12,
|
||||
|
||||
//
|
||||
// ICMP code definations for ICMP_TIME_EXCEEDED
|
||||
//
|
||||
ICMP_TIMEOUT_IN_TRANSIT = 0,
|
||||
ICMp_TIMEOUT_REASSEMBLE = 1, // Host may generate
|
||||
|
||||
//
|
||||
// ICMP code definations for ICMP_TIME_EXCEEDED
|
||||
//
|
||||
ICMP_NET_REDIRECT = 0,
|
||||
ICMP_HOST_REDIRECT = 1,
|
||||
ICMP_NET_TOS_REDIRECT = 2,
|
||||
ICMP_HOST_TOS_REDIRECT = 3,
|
||||
|
||||
//
|
||||
// ICMP message classes, each class of ICMP message shares
|
||||
// a common message format. INVALID_MESSAGE is only a flag.
|
||||
//
|
||||
ICMP_INVALID_MESSAGE = 0,
|
||||
ICMP_ERROR_MESSAGE = 1,
|
||||
ICMP_QUERY_MESSAGE = 2,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
UINT8 IcmpType;
|
||||
UINT8 IcmpClass;
|
||||
} IP4_ICMP_CLASS;
|
||||
|
||||
extern IP4_ICMP_CLASS mIcmpClass[];
|
||||
extern EFI_IP4_ICMP_TYPE mIp4SupportedIcmp[];
|
||||
|
||||
EFI_STATUS
|
||||
Ip4IcmpHandle (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Header,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
#endif
|
1146
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
Normal file
1146
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
Normal file
File diff suppressed because it is too large
Load Diff
238
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.h
Normal file
238
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.h
Normal file
@@ -0,0 +1,238 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4If.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Definition for IP4 pesudo interface structure.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_IF_H__
|
||||
#define __EFI_IP4_IF_H__
|
||||
|
||||
enum {
|
||||
IP4_FRAME_RX_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', 'F', 'R'),
|
||||
IP4_FRAME_TX_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', 'F', 'T'),
|
||||
IP4_FRAME_ARP_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', 'F', 'A'),
|
||||
IP4_INTERFACE_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', 'I', 'F'),
|
||||
};
|
||||
|
||||
//
|
||||
// This prototype is used by both receive and transmission.
|
||||
// When receiving Netbuf is allocated by IP4_INTERFACE, and
|
||||
// released by IP4. Flag shows whether the frame is received
|
||||
// as link broadcast/multicast...
|
||||
//
|
||||
// When transmitting, the Netbuf is from IP4, and provided
|
||||
// to the callback as a reference. Flag isn't used.
|
||||
//
|
||||
// IpInstance can be NULL which means that it is the IP4 driver
|
||||
// itself sending the packets. IP4 driver may send packets that
|
||||
// don't belong to any instance, such as ICMP errors, ICMP echo
|
||||
// responses, or IGMP packets. IpInstance is used as a tag in
|
||||
// this module.
|
||||
//
|
||||
typedef
|
||||
VOID
|
||||
(*IP4_FRAME_CALLBACK) (
|
||||
IP4_PROTOCOL *IpInstance, OPTIONAL
|
||||
NET_BUF *Packet,
|
||||
EFI_STATUS IoStatus,
|
||||
UINT32 LinkFlag,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
//
|
||||
// Each receive request is wrapped in an IP4_LINK_RX_TOKEN.
|
||||
// Upon completion, the Callback will be called. Only one
|
||||
// receive request is send to MNP. IpInstance is always NULL.
|
||||
// Reference MNP's spec for information.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
IP4_INTERFACE *Interface;
|
||||
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
IP4_FRAME_CALLBACK CallBack;
|
||||
VOID *Context;
|
||||
|
||||
EFI_MANAGED_NETWORK_COMPLETION_TOKEN MnpToken;
|
||||
} IP4_LINK_RX_TOKEN;
|
||||
|
||||
//
|
||||
// Each transmit request is wrapped in an IP4_LINK_TX_TOKEN.
|
||||
// Upon completion, the Callback will be called.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
NET_LIST_ENTRY Link;
|
||||
|
||||
IP4_INTERFACE *Interface;
|
||||
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
IP4_FRAME_CALLBACK CallBack;
|
||||
NET_BUF *Packet;
|
||||
VOID *Context;
|
||||
|
||||
EFI_MAC_ADDRESS DstMac;
|
||||
EFI_MAC_ADDRESS SrcMac;
|
||||
|
||||
EFI_MANAGED_NETWORK_COMPLETION_TOKEN MnpToken;
|
||||
EFI_MANAGED_NETWORK_TRANSMIT_DATA MnpTxData;
|
||||
} IP4_LINK_TX_TOKEN;
|
||||
|
||||
//
|
||||
// Only one ARP request is requested for all the frames in
|
||||
// a time. It is started for the first frames to the Ip. Any
|
||||
// subsequent transmission frame will be linked to Frames, and
|
||||
// be sent all at once the ARP requests succeed.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
NET_LIST_ENTRY Link;
|
||||
|
||||
NET_LIST_ENTRY Frames;
|
||||
IP4_INTERFACE *Interface;
|
||||
|
||||
//
|
||||
// ARP requesting staffs
|
||||
//
|
||||
EFI_EVENT OnResolved;
|
||||
IP4_ADDR Ip;
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
} IP4_ARP_QUE;
|
||||
|
||||
//
|
||||
// Callback to select which frame to cancel. Caller can cancel a
|
||||
// single frame, or all the frame from an IP instance.
|
||||
//
|
||||
typedef
|
||||
BOOLEAN
|
||||
(*IP4_FRAME_TO_CANCEL) (
|
||||
IP4_LINK_TX_TOKEN *Frame,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
//
|
||||
// Each IP4 instance has its own station address. All the instances
|
||||
// with the same station address share a single interface structure.
|
||||
// Each interface has its own ARP child, and shares one MNP child.
|
||||
// Notice the special cases that DHCP can configure the interface
|
||||
// with 0.0.0.0/0.0.0.0.
|
||||
//
|
||||
typedef struct _IP4_INTERFACE {
|
||||
UINT32 Signature;
|
||||
NET_LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
|
||||
//
|
||||
// IP address and subnet mask of the interface. It also contains
|
||||
// the subnet/net broadcast address for quick access. The fileds
|
||||
// are invalid if (Configured == FALSE)
|
||||
//
|
||||
IP4_ADDR Ip;
|
||||
IP4_ADDR SubnetMask;
|
||||
IP4_ADDR SubnetBrdcast;
|
||||
IP4_ADDR NetBrdcast;
|
||||
BOOLEAN Configured;
|
||||
|
||||
//
|
||||
// Handle used to create/destory ARP child. All the IP children
|
||||
// share one MNP which is owned by IP service binding.
|
||||
//
|
||||
EFI_HANDLE Controller;
|
||||
EFI_HANDLE Image;
|
||||
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
EFI_ARP_PROTOCOL *Arp;
|
||||
EFI_HANDLE ArpHandle;
|
||||
|
||||
//
|
||||
// Queues to keep the frames sent and waiting ARP request.
|
||||
//
|
||||
NET_LIST_ENTRY ArpQues;
|
||||
NET_LIST_ENTRY SentFrames;
|
||||
IP4_LINK_RX_TOKEN *RecvRequest;
|
||||
|
||||
//
|
||||
// The interface's MAC and broadcast MAC address.
|
||||
//
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
EFI_MAC_ADDRESS BroadcastMac;
|
||||
UINT32 HwaddrLen;
|
||||
|
||||
//
|
||||
// All the IP instances that have the same IP/SubnetMask are linked
|
||||
// together through IpInstances. If any of the instance enables
|
||||
// promiscuous receive, PromiscRecv is true.
|
||||
//
|
||||
NET_LIST_ENTRY IpInstances;
|
||||
BOOLEAN PromiscRecv;
|
||||
} IP4_INTERFACE;
|
||||
|
||||
IP4_INTERFACE *
|
||||
Ip4CreateInterface (
|
||||
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE ImageHandle
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4SetAddress (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN IP4_ADDR IpAddr,
|
||||
IN IP4_ADDR SubnetMask
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4FreeInterface (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN IP4_PROTOCOL *IpInstance OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4SendFrame (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN IP4_PROTOCOL *IpInstance, OPTIONAL
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_ADDR NextHop,
|
||||
IN IP4_FRAME_CALLBACK CallBack,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4CancelFrames (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN IP4_FRAME_TO_CANCEL FrameToCancel, OPTIONAL
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4CancelReceive (
|
||||
IN IP4_INTERFACE *Interface
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4ReceiveFrame (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN IP4_PROTOCOL *IpInstance, OPTIONAL
|
||||
IN IP4_FRAME_CALLBACK CallBack,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
#endif
|
629
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Igmp.c
Normal file
629
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Igmp.c
Normal file
@@ -0,0 +1,629 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Igmp.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This file implements the RFC2236: IGMP v2
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
//
|
||||
// Route Alert option in IGMP report to direct routers to
|
||||
// examine the packet more closely.
|
||||
//
|
||||
UINT32 mRouteAlertOption = 0x00000494;
|
||||
|
||||
|
||||
/**
|
||||
Init the IGMP control data of the IP4 service instance, configure
|
||||
MNP to receive ALL SYSTEM multicast.
|
||||
|
||||
@param IpSb The IP4 service whose IGMP is to be initialized.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to initialize IGMP.
|
||||
@retval Others Failed to initialize the IGMP of IpSb.
|
||||
@retval EFI_SUCCESS IGMP of the IpSb is successfully initialized.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4InitIgmp (
|
||||
IN IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
IGMP_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
|
||||
//
|
||||
// Configure MNP to receive ALL_SYSTEM multicast
|
||||
//
|
||||
Group = NetAllocatePool (sizeof (IGMP_GROUP));
|
||||
|
||||
if (Group == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Mnp = IpSb->Mnp;
|
||||
|
||||
Group->Address = IP4_ALLSYSTEM_ADDRESS;
|
||||
Group->RefCnt = 1;
|
||||
Group->DelayTime = 0;
|
||||
Group->ReportByUs = FALSE;
|
||||
|
||||
Status = Ip4GetMulticastMac (Mnp, IP4_ALLSYSTEM_ADDRESS, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Mnp->Groups (Mnp, TRUE, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
NetListInsertHead (&IgmpCtrl->Groups, &Group->Link);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
NetFreePool (Group);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find the IGMP_GROUP structure which contains the status of multicast
|
||||
group Address in this IGMP control block
|
||||
|
||||
@param IgmpCtrl The IGMP control block to search from
|
||||
@param Address The multicast address to search
|
||||
|
||||
@return NULL if the multicast address isn't in the IGMP control block. Otherwise
|
||||
@return the point to the IGMP_GROUP which contains the status of multicast group
|
||||
@return for Address.
|
||||
|
||||
**/
|
||||
IGMP_GROUP *
|
||||
Ip4FindGroup (
|
||||
IN IGMP_SERVICE_DATA *IgmpCtrl,
|
||||
IN IP4_ADDR Address
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IGMP_GROUP *Group;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
|
||||
if (Group->Address == Address) {
|
||||
return Group;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Count the number of IP4 multicast groups that are mapped to the
|
||||
same MAC address. Several IP4 multicast address may be mapped to
|
||||
the same MAC address.
|
||||
|
||||
@param IgmpCtrl The IGMP control block to search in
|
||||
@param Mac The MAC address to search
|
||||
|
||||
@return The number of the IP4 multicast group that mapped to the same
|
||||
@return multicast group Mac.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4FindMac (
|
||||
IN IGMP_SERVICE_DATA *IgmpCtrl,
|
||||
IN EFI_MAC_ADDRESS *Mac
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IGMP_GROUP *Group;
|
||||
INTN Count;
|
||||
|
||||
Count = 0;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
|
||||
if (NET_MAC_EQUAL (&Group->Mac, Mac, sizeof (EFI_MAC_ADDRESS))) {
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
|
||||
return Count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send an IGMP protocol message to the Dst, such as IGMP v1 membership report.
|
||||
|
||||
@param IpSb The IP4 service instance that requests the
|
||||
transmission
|
||||
@param Dst The destinaton to send to
|
||||
@param Type The IGMP message type, such as IGMP v2 membership
|
||||
report
|
||||
@param Group The group address in the IGMP message head.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to build the message
|
||||
@retval EFI_SUCCESS The IGMP message is successfully send
|
||||
@retval Others Failed to send the IGMP message.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4SendIgmpMessage (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN UINT8 Type,
|
||||
IN IP4_ADDR Group
|
||||
)
|
||||
{
|
||||
IP4_HEAD Head;
|
||||
NET_BUF *Packet;
|
||||
IGMP_HEAD *Igmp;
|
||||
|
||||
//
|
||||
// Allocate a net buffer to hold the message
|
||||
//
|
||||
Packet = NetbufAlloc (IP4_MAX_HEADLEN + sizeof (IGMP_HEAD));
|
||||
|
||||
if (Packet == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill in the IGMP and IP header, then transmit the message
|
||||
//
|
||||
NetbufReserve (Packet, IP4_MAX_HEADLEN);
|
||||
|
||||
Igmp = (IGMP_HEAD *) NetbufAllocSpace (Packet, sizeof (IGMP_HEAD), FALSE);
|
||||
|
||||
Igmp->Type = Type;
|
||||
Igmp->MaxRespTime = 0;
|
||||
Igmp->Checksum = 0;
|
||||
Igmp->Group = HTONL (Group);
|
||||
Igmp->Checksum = ~NetblockChecksum ((UINT8 *) Igmp, sizeof (IGMP_HEAD));
|
||||
|
||||
Head.Tos = 0;
|
||||
Head.Protocol = IP4_PROTO_IGMP;
|
||||
Head.Ttl = 1;
|
||||
Head.Fragment = 0;
|
||||
Head.Dst = Dst;
|
||||
Head.Src = IP4_ALLZERO_ADDRESS;
|
||||
|
||||
return Ip4Output (
|
||||
IpSb,
|
||||
NULL,
|
||||
Packet,
|
||||
&Head,
|
||||
(UINT8 *) &mRouteAlertOption,
|
||||
sizeof (UINT32),
|
||||
IP4_ALLZERO_ADDRESS,
|
||||
Ip4SysPacketSent,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send an IGMP membership report. Depends on whether the server is
|
||||
v1 or v2, it will send either a V1 or V2 membership report.
|
||||
|
||||
@param IpSb The IP4 service instance that requests the
|
||||
transmission.
|
||||
@param Group The group address to report
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to build the message
|
||||
@retval EFI_SUCCESS The IGMP report message is successfully send
|
||||
@retval Others Failed to send the report.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4SendIgmpReport (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Group
|
||||
)
|
||||
{
|
||||
if (IpSb->IgmpCtrl.Igmpv1QuerySeen != 0) {
|
||||
return Ip4SendIgmpMessage (IpSb, Group, IGMP_V1_MEMBERSHIP_REPORT, Group);
|
||||
} else {
|
||||
return Ip4SendIgmpMessage (IpSb, Group, IGMP_V2_MEMBERSHIP_REPORT, Group);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Join the multicast group on behavior of this IP4 child
|
||||
|
||||
@param IpInstance The IP4 child that wants to join the group
|
||||
@param Address The group to join
|
||||
|
||||
@retval EFI_SUCCESS Successfully join the multicast group
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources
|
||||
@retval Others Failed to join the multicast group.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4JoinGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
)
|
||||
{
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
IP4_SERVICE *IpSb;
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
IGMP_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
IpSb = IpInstance->Service;
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
Mnp = IpSb->Mnp;
|
||||
|
||||
//
|
||||
// If the IP service already is a member in the group, just
|
||||
// increase the refernce count and return.
|
||||
//
|
||||
Group = Ip4FindGroup (IgmpCtrl, Address);
|
||||
|
||||
if (Group != NULL) {
|
||||
Group->RefCnt++;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Otherwise, create a new IGMP_GROUP, Get the multicast's MAC address,
|
||||
// send a report, then direct MNP to receive the multicast.
|
||||
//
|
||||
Group = NetAllocatePool (sizeof (IGMP_GROUP));
|
||||
|
||||
if (Group == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Group->Address = Address;
|
||||
Group->RefCnt = 1;
|
||||
Group->DelayTime = IGMP_UNSOLICIATED_REPORT;
|
||||
Group->ReportByUs = TRUE;
|
||||
|
||||
Status = Ip4GetMulticastMac (Mnp, Address, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip4SendIgmpReport (IpSb, Address);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Mnp->Groups (Mnp, TRUE, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
NetListInsertHead (&IgmpCtrl->Groups, &Group->Link);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
NetFreePool (Group);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Leave the IP4 multicast group on behavior of IpInstance.
|
||||
|
||||
@param IpInstance The IP4 child that wants to leave the group
|
||||
address
|
||||
@param Address The group address to leave
|
||||
|
||||
@retval EFI_NOT_FOUND The IP4 service instance isn't in the group
|
||||
@retval EFI_SUCCESS Successfully leave the multicast group.
|
||||
@retval Others Failed to leave the multicast group.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4LeaveGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
)
|
||||
{
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
IP4_SERVICE *IpSb;
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
IGMP_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
IpSb = IpInstance->Service;
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
Mnp = IpSb->Mnp;
|
||||
|
||||
Group = Ip4FindGroup (IgmpCtrl, Address);
|
||||
|
||||
if (Group == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// If more than one instance is in the group, decrease
|
||||
// the RefCnt then return.
|
||||
//
|
||||
if (--Group->RefCnt > 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// If multiple IP4 group addresses are mapped to the same
|
||||
// multicast MAC address, don't configure the MNP to leave
|
||||
// the MAC.
|
||||
//
|
||||
if (Ip4FindMac (IgmpCtrl, &Group->Mac) == 1) {
|
||||
Status = Mnp->Groups (Mnp, FALSE, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Send a leave report if the membership is reported by us
|
||||
// and we are talking IGMPv2.
|
||||
//
|
||||
if (Group->ReportByUs && !IgmpCtrl->Igmpv1QuerySeen) {
|
||||
Ip4SendIgmpMessage (IpSb, IP4_ALLROUTER_ADDRESS, IGMP_LEAVE_GROUP, Group->Address);
|
||||
}
|
||||
|
||||
NetListRemoveEntry (&Group->Link);
|
||||
NetFreePool (Group);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Handle the received IGMP message for the IP4 service instance.
|
||||
|
||||
@param IpSb The IP4 service instance that received the message
|
||||
@param Head The IP4 header of the received message
|
||||
@param Packet The IGMP message, without IP4 header
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The IGMP message is malformated.
|
||||
@retval EFI_SUCCESS The IGMP message is successfully processed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IgmpHandle (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
IGMP_HEAD Igmp;
|
||||
IGMP_GROUP *Group;
|
||||
IP4_ADDR Address;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
|
||||
//
|
||||
// Must checksum over the whole packet, later IGMP version
|
||||
// may employ message longer than 8 bytes. IP's header has
|
||||
// already been trimmed off.
|
||||
//
|
||||
if ((Packet->TotalSize < sizeof (Igmp)) || (NetbufChecksum (Packet) != 0)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the packet in case it is fragmented
|
||||
//
|
||||
NetbufCopy (Packet, 0, sizeof (IGMP_HEAD), (UINT8 *)&Igmp);
|
||||
|
||||
switch (Igmp.Type) {
|
||||
case IGMP_MEMBERSHIP_QUERY:
|
||||
//
|
||||
// If MaxRespTIme is zero, it is most likely that we are
|
||||
// talking to a V1 router
|
||||
//
|
||||
if (Igmp.MaxRespTime == 0) {
|
||||
IgmpCtrl->Igmpv1QuerySeen = IGMP_V1ROUTER_PRESENT;
|
||||
Igmp.MaxRespTime = 100;
|
||||
}
|
||||
|
||||
//
|
||||
// Igmp is ticking once per second but MaxRespTime is in
|
||||
// the unit of 100ms.
|
||||
//
|
||||
Igmp.MaxRespTime /= 10;
|
||||
Address = NTOHL (Igmp.Group);
|
||||
|
||||
if (Address == IP4_ALLSYSTEM_ADDRESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
|
||||
//
|
||||
// If address is all zero, all the memberships will be reported.
|
||||
// otherwise only one is reported.
|
||||
//
|
||||
if ((Address == IP4_ALLZERO_ADDRESS) || (Address == Group->Address)) {
|
||||
//
|
||||
// If the timer is pending, only update it if the time left
|
||||
// is longer than the MaxRespTime. TODO: randomize the DelayTime.
|
||||
//
|
||||
if ((Group->DelayTime == 0) || (Group->DelayTime > Igmp.MaxRespTime)) {
|
||||
Group->DelayTime = NET_MAX (1, Igmp.MaxRespTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IGMP_V1_MEMBERSHIP_REPORT:
|
||||
case IGMP_V2_MEMBERSHIP_REPORT:
|
||||
Address = NTOHL (Igmp.Group);
|
||||
Group = Ip4FindGroup (IgmpCtrl, Address);
|
||||
|
||||
if ((Group != NULL) && (Group->DelayTime > 0)) {
|
||||
Group->DelayTime = 0;
|
||||
Group->ReportByUs = FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
NetbufFree (Packet);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The periodical timer function for IGMP. It does the following
|
||||
things:
|
||||
1. Decrease the Igmpv1QuerySeen to make it possible to refresh
|
||||
the IGMP server type.
|
||||
2. Decrease the report timer for each IGMP group in "delaying
|
||||
member" state.
|
||||
|
||||
@param IpSb The IP4 service instance that is ticking
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4IgmpTicking (
|
||||
IN IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IGMP_GROUP *Group;
|
||||
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
|
||||
if (IgmpCtrl->Igmpv1QuerySeen > 0) {
|
||||
IgmpCtrl->Igmpv1QuerySeen--;
|
||||
}
|
||||
|
||||
//
|
||||
// Decrease the report timer for each IGMP group in "delaying member"
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
ASSERT (Group->DelayTime >= 0);
|
||||
|
||||
if (Group->DelayTime > 0) {
|
||||
Group->DelayTime--;
|
||||
|
||||
if (Group->DelayTime == 0) {
|
||||
Ip4SendIgmpReport (IpSb, Group->Address);
|
||||
Group->ReportByUs = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add a group address to the array of group addresses.
|
||||
The caller should make sure that no duplicated address
|
||||
existed in the array. Although the function doesn't
|
||||
assume the byte order of the both Source and Addr, the
|
||||
network byte order is used by the caller.
|
||||
|
||||
@param Source The array of group addresses to add to
|
||||
@param Count The number of group addresses in the Source
|
||||
@param Addr The IP4 multicast address to add
|
||||
|
||||
@return NULL if failed to allocate memory for the new groups,
|
||||
@return otherwise the new combined group addresses.
|
||||
|
||||
**/
|
||||
IP4_ADDR *
|
||||
Ip4CombineGroups (
|
||||
IN IP4_ADDR *Source,
|
||||
IN UINT32 Count,
|
||||
IN IP4_ADDR Addr
|
||||
)
|
||||
{
|
||||
IP4_ADDR *Groups;
|
||||
|
||||
Groups = NetAllocatePool (sizeof (IP4_ADDR) * (Count + 1));
|
||||
|
||||
if (Groups == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetCopyMem (Groups, Source, Count * sizeof (IP4_ADDR));
|
||||
Groups[Count] = Addr;
|
||||
|
||||
return Groups;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove a group address frome the array of group addresses.
|
||||
Although the function doesn't assume the byte order of the
|
||||
both Groups and Addr, the network byte order is used by
|
||||
the caller.
|
||||
|
||||
@param Groups The array of group addresses to remove from
|
||||
@param Count The number of group addresses in the Groups
|
||||
@param Addr The IP4 multicast address to remove
|
||||
|
||||
@return The nubmer of group addresses in the Groups after remove.
|
||||
@return It is Count if the Addr isn't in the Groups.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4RemoveGroupAddr (
|
||||
IN IP4_ADDR *Groups,
|
||||
IN UINT32 Count,
|
||||
IN IP4_ADDR Addr
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
if (Groups[Index] == Addr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (Index < Count - 1) {
|
||||
Groups[Index] = Groups[Index + 1];
|
||||
Index++;
|
||||
}
|
||||
|
||||
return Index;
|
||||
}
|
120
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Igmp.h
Normal file
120
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Igmp.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Igmp.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_IGMP_H__
|
||||
#define __EFI_IP4_IGMP_H__
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UINT8 Type;
|
||||
UINT8 MaxRespTime;
|
||||
UINT16 Checksum;
|
||||
IP4_ADDR Group;
|
||||
} IGMP_HEAD;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// The status of multicast group. It isn't necessary to maintain
|
||||
// explicit state of host state diagram. A group with non-zero
|
||||
// DelayTime is in "delaying member" state. otherwise, it is in
|
||||
// "idle member" state.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
IP4_ADDR Address;
|
||||
INTN DelayTime;
|
||||
BOOLEAN ReportByUs;
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
} IGMP_GROUP;
|
||||
|
||||
//
|
||||
// The IGMP status. Each IP4 service instance has a IGMP_SERVICE_DATA
|
||||
// attached. The Igmpv1QuerySeen remember whether the server on this
|
||||
// connected network is v1 or v2.
|
||||
//
|
||||
typedef struct {
|
||||
INTN Igmpv1QuerySeen;
|
||||
NET_LIST_ENTRY Groups;
|
||||
} IGMP_SERVICE_DATA;
|
||||
|
||||
enum {
|
||||
//
|
||||
// IGMP message type
|
||||
//
|
||||
IGMP_MEMBERSHIP_QUERY = 0x11,
|
||||
IGMP_V1_MEMBERSHIP_REPORT = 0x12,
|
||||
IGMP_V2_MEMBERSHIP_REPORT = 0x16,
|
||||
IGMP_LEAVE_GROUP = 0x17,
|
||||
|
||||
IGMP_V1ROUTER_PRESENT = 400,
|
||||
IGMP_UNSOLICIATED_REPORT = 10,
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
Ip4InitIgmp (
|
||||
IN IP4_SERVICE *IpService
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4JoinGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4LeaveGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4IgmpHandle (
|
||||
IN IP4_SERVICE *IpService,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4IgmpTicking (
|
||||
IN IP4_SERVICE *IpService
|
||||
);
|
||||
|
||||
IP4_ADDR *
|
||||
Ip4CombineGroups (
|
||||
IN IP4_ADDR *SourceGroups,
|
||||
IN UINT32 Count,
|
||||
IN IP4_ADDR Addr
|
||||
);
|
||||
|
||||
INTN
|
||||
Ip4RemoveGroupAddr (
|
||||
IN IP4_ADDR *Group,
|
||||
IN UINT32 GroupCnt,
|
||||
IN IP4_ADDR Addr
|
||||
);
|
||||
|
||||
IGMP_GROUP *
|
||||
Ip4FindGroup (
|
||||
IN IGMP_SERVICE_DATA *IgmpCtrl,
|
||||
IN IP4_ADDR Address
|
||||
);
|
||||
#endif
|
2022
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
Normal file
2022
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
Normal file
File diff suppressed because it is too large
Load Diff
258
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h
Normal file
258
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h
Normal file
@@ -0,0 +1,258 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Impl.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Ip4 internal functions and type defintions.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_IMPL_H__
|
||||
#define __EFI_IP4_IMPL_H__
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/IP4.h>
|
||||
#include <Protocol/IP4Config.h>
|
||||
#include <Protocol/Arp.h>
|
||||
#include <Protocol/ManagedNetwork.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/NetLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
#include "IP4Common.h"
|
||||
#include "IP4Driver.h"
|
||||
#include "IP4If.h"
|
||||
#include "Ip4Icmp.h"
|
||||
#include "IP4Option.h"
|
||||
#include "Ip4Igmp.h"
|
||||
#include "IP4Route.h"
|
||||
#include "IP4Input.h"
|
||||
#include "IP4Output.h"
|
||||
|
||||
enum {
|
||||
IP4_PROTOCOL_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', '4', 'P'),
|
||||
IP4_SERVICE_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', '4', 'S'),
|
||||
|
||||
//
|
||||
// The state of IP4 protocol. It starts from UNCONFIGED. if it is
|
||||
// successfully configured, it goes to CONFIGED. if configure NULL
|
||||
// is called, it becomes UNCONFIGED again. If (partly) destoried, it
|
||||
// becomes DESTORY.
|
||||
//
|
||||
IP4_STATE_UNCONFIGED = 0,
|
||||
IP4_STATE_CONFIGED,
|
||||
IP4_STATE_DESTORY,
|
||||
|
||||
//
|
||||
// The state of IP4 service. It starts from UNSTARTED. It transits
|
||||
// to STARTED if autoconfigure is started. If default address is
|
||||
// configured, it becomes CONFIGED. and if partly destoried, it goes
|
||||
// to DESTORY.
|
||||
//
|
||||
IP4_SERVICE_UNSTARTED = 0,
|
||||
IP4_SERVICE_STARTED,
|
||||
IP4_SERVICE_CONFIGED,
|
||||
IP4_SERVICE_DESTORY,
|
||||
};
|
||||
|
||||
//
|
||||
// IP4_TXTOKEN_WRAP wraps the upper layer's transmit token.
|
||||
// The user's data is kept in the Packet. When fragment is
|
||||
// needed, each fragment of the Packet has a reference to the
|
||||
// Packet, no data is actually copied. The Packet will be
|
||||
// released when all the fragments of it have been recycled by
|
||||
// MNP. Upon then, the IP4_TXTOKEN_WRAP will be released, and
|
||||
// user's event signalled.
|
||||
//
|
||||
typedef struct {
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
EFI_IP4_COMPLETION_TOKEN *Token;
|
||||
NET_BUF *Packet;
|
||||
BOOLEAN Sent;
|
||||
INTN Life;
|
||||
} IP4_TXTOKEN_WRAP;
|
||||
|
||||
//
|
||||
// IP4_RXDATA_WRAP wraps the data IP4 child delivers to the
|
||||
// upper layers. The received packet is kept in the Packet.
|
||||
// The Packet itself may be constructured from some fragments.
|
||||
// All the fragments of the Packet is organized by a
|
||||
// IP4_ASSEMBLE_ENTRY structure. If the Packet is recycled by
|
||||
// the upper layer, the assemble entry and its associated
|
||||
// fragments will be freed at last.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Link;
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
NET_BUF *Packet;
|
||||
EFI_IP4_RECEIVE_DATA RxData;
|
||||
} IP4_RXDATA_WRAP;
|
||||
|
||||
typedef struct _IP4_PROTOCOL {
|
||||
UINT32 Signature;
|
||||
|
||||
EFI_IP4_PROTOCOL Ip4Proto;
|
||||
EFI_HANDLE Handle;
|
||||
INTN State;
|
||||
|
||||
IP4_SERVICE *Service;
|
||||
NET_LIST_ENTRY Link; // Link to all the IP protocol from the service
|
||||
|
||||
//
|
||||
// User's transmit/receive tokens, and received/deliverd packets
|
||||
//
|
||||
NET_MAP RxTokens;
|
||||
NET_MAP TxTokens; // map between (User's Token, IP4_TXTOKE_WRAP)
|
||||
NET_LIST_ENTRY Received; // Received but not delivered packet
|
||||
NET_LIST_ENTRY Delivered; // Delivered and to be recycled packets
|
||||
EFI_LOCK RecycleLock;
|
||||
|
||||
//
|
||||
// Instance's address and route tables. There are two route tables.
|
||||
// RouteTable is used by the IP4 driver to route packet. EfiRouteTable
|
||||
// is used to communicate the current route info to the upper layer.
|
||||
//
|
||||
IP4_INTERFACE *Interface;
|
||||
NET_LIST_ENTRY AddrLink; // Ip instances with the same IP address.
|
||||
IP4_ROUTE_TABLE *RouteTable;
|
||||
|
||||
EFI_IP4_ROUTE_TABLE *EfiRouteTable;
|
||||
UINT32 EfiRouteCount;
|
||||
|
||||
//
|
||||
// IGMP data for this instance
|
||||
//
|
||||
IP4_ADDR *Groups; // stored in network byte order
|
||||
UINT32 GroupCount;
|
||||
|
||||
EFI_IP4_CONFIG_DATA ConfigData;
|
||||
|
||||
} IP4_PROTOCOL;
|
||||
|
||||
typedef struct _IP4_SERVICE {
|
||||
UINT32 Signature;
|
||||
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
|
||||
INTN State;
|
||||
BOOLEAN InDestory;
|
||||
|
||||
//
|
||||
// List of all the IP instances and interfaces, and default
|
||||
// interface and route table and caches.
|
||||
//
|
||||
UINTN NumChildren;
|
||||
NET_LIST_ENTRY Children;
|
||||
|
||||
NET_LIST_ENTRY Interfaces;
|
||||
|
||||
IP4_INTERFACE *DefaultInterface;
|
||||
IP4_ROUTE_TABLE *DefaultRouteTable;
|
||||
|
||||
//
|
||||
// Ip reassemble utilities, and IGMP data
|
||||
//
|
||||
IP4_ASSEMBLE_TABLE Assemble;
|
||||
IGMP_SERVICE_DATA IgmpCtrl;
|
||||
|
||||
//
|
||||
// Low level protocol used by this service instance
|
||||
//
|
||||
EFI_HANDLE Image;
|
||||
EFI_HANDLE Controller;
|
||||
|
||||
EFI_HANDLE MnpChildHandle;
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
|
||||
EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData;
|
||||
EFI_SIMPLE_NETWORK_MODE SnpMode;
|
||||
|
||||
EFI_EVENT Timer;
|
||||
|
||||
//
|
||||
// Auto configure staff
|
||||
//
|
||||
EFI_IP4_CONFIG_PROTOCOL *Ip4Config;
|
||||
EFI_EVENT DoneEvent;
|
||||
EFI_EVENT ReconfigEvent;
|
||||
|
||||
//
|
||||
// The string representation of the current mac address of the
|
||||
// NIC this IP4_SERVICE works on.
|
||||
//
|
||||
CHAR16 *MacString;
|
||||
} IP4_SERVICE;
|
||||
|
||||
#define IP4_INSTANCE_FROM_PROTOCOL(Ip4) \
|
||||
CR ((Ip4), IP4_PROTOCOL, Ip4Proto, IP4_PROTOCOL_SIGNATURE)
|
||||
|
||||
#define IP4_SERVICE_FROM_PROTOCOL(Sb) \
|
||||
CR ((Sb), IP4_SERVICE, ServiceBinding, IP4_SERVICE_SIGNATURE)
|
||||
|
||||
#define IP4_NO_MAPPING(IpInstance) (!(IpInstance)->Interface->Configured)
|
||||
|
||||
extern EFI_IP4_PROTOCOL mEfiIp4ProtocolTemplete;
|
||||
|
||||
EFI_STATUS
|
||||
Ip4ServiceConfigMnp (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN BOOLEAN Force
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4InitProtocol (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4CleanProtocol (
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4Cancel (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN EFI_IP4_COMPLETION_TOKEN *Token
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4Groups (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN BOOLEAN JoinFlag,
|
||||
IN EFI_IPv4_ADDRESS *GroupAddress
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip4TimerTicking (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4SentPacketTicking (
|
||||
IN NET_MAP *Map,
|
||||
IN NET_MAP_ITEM *Item,
|
||||
IN VOID *Context
|
||||
);
|
||||
#endif
|
1235
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c
Normal file
1235
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c
Normal file
File diff suppressed because it is too large
Load Diff
138
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.h
Normal file
138
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Input.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_INPUT_H__
|
||||
#define __EFI_IP4_INPUT_H__
|
||||
|
||||
enum {
|
||||
IP4_MIN_HEADLEN = 20,
|
||||
IP4_MAX_HEADLEN = 60,
|
||||
|
||||
IP4_ASSEMLE_HASH_SIZE = 31,
|
||||
IP4_FRAGMENT_LIFE = 120,
|
||||
IP4_MAX_PACKET_SIZE = 65535,
|
||||
};
|
||||
|
||||
//
|
||||
// Per packet information for input process. LinkFlag specifies whether
|
||||
// the packet is received as Link layer unicast, multicast or broadcast.
|
||||
// The CastType is the IP layer cast type, such as IP multicast or unicast.
|
||||
// Start, End and Length are staffs used to assemble the packets. Start
|
||||
// is the sequence number of the first byte of data in the packet. Length
|
||||
// is the number of bytes of data. End = Start + Length, that is, the
|
||||
// sequence number of last byte + 1. Each assembled packet has a count down
|
||||
// life. If it isn't consumed before Life reaches zero, the packet is released.
|
||||
//
|
||||
typedef struct {
|
||||
UINTN LinkFlag;
|
||||
INTN CastType;
|
||||
INTN Start;
|
||||
INTN End;
|
||||
INTN Length;
|
||||
UINT32 Life;
|
||||
EFI_STATUS Status;
|
||||
} IP4_CLIP_INFO;
|
||||
|
||||
//
|
||||
// Structure used to assemble IP packets.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Link;
|
||||
|
||||
//
|
||||
// Identity of one IP4 packet. Each fragment of a packet has
|
||||
// the same (Dst, Src, Id, Protocol).
|
||||
//
|
||||
IP4_ADDR Dst;
|
||||
IP4_ADDR Src;
|
||||
UINT16 Id;
|
||||
UINT8 Protocol;
|
||||
|
||||
INTN TotalLen;
|
||||
INTN CurLen;
|
||||
NET_LIST_ENTRY Fragments; // List of all the fragments of this packet
|
||||
|
||||
IP4_HEAD *Head; // IP head of the first fragment
|
||||
IP4_CLIP_INFO *Info; // Per packet info of the first fragment
|
||||
INTN Life; // Count down life for the packet.
|
||||
} IP4_ASSEMBLE_ENTRY;
|
||||
|
||||
//
|
||||
// Each Ip service instance has an assemble table to reassemble
|
||||
// the packets before delivery to its children. It is organized
|
||||
// as hash table.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Bucket[IP4_ASSEMLE_HASH_SIZE];
|
||||
} IP4_ASSEMBLE_TABLE;
|
||||
|
||||
#define IP4_GET_CLIP_INFO(Packet) ((IP4_CLIP_INFO *) ((Packet)->ProtoData))
|
||||
|
||||
#define IP4_ASSEMBLE_HASH(Dst, Src, Id, Proto) \
|
||||
(((Dst) + (Src) + ((Id) << 16) + (Proto)) % IP4_ASSEMLE_HASH_SIZE)
|
||||
|
||||
#define IP4_RXDATA_WRAP_SIZE(NumFrag) \
|
||||
(sizeof (IP4_RXDATA_WRAP) + sizeof (EFI_IP4_FRAGMENT_DATA) * ((NumFrag) - 1))
|
||||
|
||||
VOID
|
||||
Ip4InitAssembleTable (
|
||||
IN IP4_ASSEMBLE_TABLE *Table
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4CleanAssembleTable (
|
||||
IN IP4_ASSEMBLE_TABLE *Table
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4AccpetFrame (
|
||||
IN IP4_PROTOCOL *Ip4Instance,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN UINT32 Flag,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4Demultiplex (
|
||||
IN IP4_SERVICE *SbInstance,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
INTN
|
||||
Ip4InterfaceEnquePacket (
|
||||
IN IP4_SERVICE *SbInstance,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_INTERFACE *Interface
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4InstanceDeliverPacket (
|
||||
IN IP4_PROTOCOL *Ip4Instance
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4PacketTimerTicking (
|
||||
IN IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
#endif
|
231
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Option.c
Normal file
231
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Option.c
Normal file
@@ -0,0 +1,231 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Option.c
|
||||
|
||||
Abstract:
|
||||
|
||||
IP4 option support functions
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Validate the IP4 option format for both the packets we received
|
||||
and will transmit. It will compute the ICMP error message fields
|
||||
if the option is mal-formated. But this information isn't used.
|
||||
|
||||
@param Option The first byte of the option
|
||||
@param OptionLen The length of the whole option
|
||||
@param Rcvd The option is from the packet we received if TRUE,
|
||||
otherwise the option we wants to transmit.
|
||||
|
||||
@return TRUE: The option is properly formated
|
||||
@return FALSE: The option is mal-formated
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip4OptionIsValid (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptionLen,
|
||||
IN BOOLEAN Rcvd
|
||||
)
|
||||
{
|
||||
UINT32 Cur;
|
||||
UINT32 Len;
|
||||
UINT32 Point;
|
||||
UINT8 IcmpType;
|
||||
UINT8 IcmpCode;
|
||||
UINT32 IcmpPoint;
|
||||
|
||||
IcmpType = ICMP_PARAMETER_PROBLEM;
|
||||
IcmpCode = 0;
|
||||
IcmpPoint = 0;
|
||||
|
||||
Cur = 0;
|
||||
|
||||
while (Cur < OptionLen) {
|
||||
switch (Option[Cur]) {
|
||||
case IP4_OPTION_NOP:
|
||||
Cur++;
|
||||
break;
|
||||
|
||||
case IP4_OPTION_EOP:
|
||||
Cur = OptionLen;
|
||||
break;
|
||||
|
||||
case IP4_OPTION_LSRR:
|
||||
case IP4_OPTION_SSRR:
|
||||
case IP4_OPTION_RR:
|
||||
Len = Option[Cur + 1];
|
||||
Point = Option[Cur + 2];
|
||||
|
||||
//
|
||||
// SRR/RR options are formated as |Type|Len|Point|Ip1|Ip2|...
|
||||
//
|
||||
if ((OptionLen - Cur < Len) || (Len < 3) || ((Len - 3) % 4 != 0)) {
|
||||
IcmpPoint = Cur + 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((Point > Len + 1) || (Point % 4 != 0)) {
|
||||
IcmpPoint = Cur + 2;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// The Point must point pass the last entry if the packet is received
|
||||
// by us. It must point to 4 if the packet is to be sent by us for
|
||||
// source route option.
|
||||
//
|
||||
if ((Option[Cur] != IP4_OPTION_RR) &&
|
||||
((Rcvd && (Point != Len + 1)) || (!Rcvd && (Point != 4)))) {
|
||||
|
||||
IcmpType = ICMP_DEST_UNREACHABLE;
|
||||
IcmpCode = ICMP_SOURCEROUTE_FAILED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Cur += Len;
|
||||
break;
|
||||
|
||||
default:
|
||||
Len = Option[Cur + 1];
|
||||
|
||||
if ((OptionLen - Cur < Len) || (Len < 2)) {
|
||||
IcmpPoint = Cur + 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Cur = Cur + Len;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Copy the option from the original option to buffer. It
|
||||
handles the details such as:
|
||||
1. whether copy the single IP4 option to the first/non-first
|
||||
fragments.
|
||||
2. Pad the options copied over to aligened to 4 bytes.
|
||||
|
||||
@param Option The original option to copy from
|
||||
@param OptionLen The length of the original option
|
||||
@param FirstFragment Whether it is the first fragment
|
||||
@param Buf The buffer to copy options to
|
||||
@param 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
|
||||
Ip4CopyOption (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptionLen,
|
||||
IN BOOLEAN FirstFragment,
|
||||
IN UINT8 *Buf, OPTIONAL
|
||||
IN OUT UINT32 *BufLen
|
||||
)
|
||||
{
|
||||
UINT8 OptBuf[40];
|
||||
UINT32 Cur;
|
||||
UINT32 Next;
|
||||
UINT8 Type;
|
||||
UINT32 Len;
|
||||
|
||||
ASSERT ((BufLen != NULL) && (OptionLen <= 40));
|
||||
|
||||
Cur = 0;
|
||||
Next = 0;
|
||||
|
||||
while (Cur < OptionLen) {
|
||||
Type = Option[Cur];
|
||||
Len = Option[Cur + 1];
|
||||
|
||||
if (Type == IP4_OPTION_NOP) {
|
||||
//
|
||||
// Keep the padding, in case that the sender wants to align
|
||||
// the option, say, to 4 bytes
|
||||
//
|
||||
OptBuf[Next] = IP4_OPTION_NOP;
|
||||
Next++;
|
||||
Cur++;
|
||||
|
||||
} else if (Type == IP4_OPTION_EOP) {
|
||||
//
|
||||
// Don't append the EOP to avoid including only a EOP option
|
||||
//
|
||||
break;
|
||||
|
||||
} else {
|
||||
//
|
||||
// don't copy options that is only valid for the first fragment
|
||||
//
|
||||
if (FirstFragment || (Type & IP4_OPTION_COPY_MASK)) {
|
||||
NetCopyMem (OptBuf + Next, Option + Cur, Len);
|
||||
Next += Len;
|
||||
}
|
||||
|
||||
Cur += Len;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Don't append an EOP only option.
|
||||
//
|
||||
if (Next == 0) {
|
||||
*BufLen = 0;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Append an EOP if the end of option doesn't coincide with the
|
||||
// end of the IP header, that is, isn't aligned to 4 bytes..
|
||||
//
|
||||
if ((Next % 4) != 0) {
|
||||
OptBuf[Next] = IP4_OPTION_EOP;
|
||||
Next++;
|
||||
}
|
||||
|
||||
//
|
||||
// Head length is in the unit of 4 bytes. Now, Len is the
|
||||
// acutal option length to appear in the IP header.
|
||||
//
|
||||
Len = ((Next + 3) &~0x03);
|
||||
|
||||
//
|
||||
// If the buffer is too small, set the BufLen then return
|
||||
//
|
||||
if ((Buf == NULL) || (*BufLen < Len)) {
|
||||
*BufLen = Len;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the option to the Buf, zero the buffer first to pad
|
||||
// the options with NOP to align to 4 bytes.
|
||||
//
|
||||
NetZeroMem (Buf, Len);
|
||||
NetCopyMem (Buf, OptBuf, Next);
|
||||
*BufLen = Len;
|
||||
return EFI_SUCCESS;
|
||||
}
|
52
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Option.h
Normal file
52
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Option.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Option.h
|
||||
|
||||
Abstract:
|
||||
|
||||
IP4 option support routines.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_OPTION_H__
|
||||
#define __EFI_IP4_OPTION_H__
|
||||
|
||||
enum {
|
||||
IP4_OPTION_EOP = 0,
|
||||
IP4_OPTION_NOP = 1,
|
||||
IP4_OPTION_LSRR = 131, // Loss source and record routing, 10000011
|
||||
IP4_OPTION_SSRR = 137, // Strict source and record routing, 10001001
|
||||
IP4_OPTION_RR = 7, // Record routing, 00000111
|
||||
|
||||
IP4_OPTION_COPY_MASK = 0x80,
|
||||
};
|
||||
|
||||
BOOLEAN
|
||||
Ip4OptionIsValid (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen,
|
||||
IN BOOLEAN Rcvd
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4CopyOption (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen,
|
||||
IN BOOLEAN Fragment,
|
||||
IN UINT8 *Buf, OPTIONAL
|
||||
IN OUT UINT32 *BufLen
|
||||
);
|
||||
#endif
|
457
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c
Normal file
457
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c
Normal file
@@ -0,0 +1,457 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Output.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Transmit the IP4 packet
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
UINT16 mIp4Id;
|
||||
|
||||
|
||||
/**
|
||||
Prepend an IP4 head to the Packet. It will copy the options and
|
||||
build the IP4 header fields. Used for IP4 fragmentation.
|
||||
|
||||
@param Packet The packet to prepend IP4 header to
|
||||
@param Head The caller supplied header. The caller should set
|
||||
the following header fields: Tos, TotalLen, Id,
|
||||
Fragment, Ttl, Protocol, Src and Dst. All the fields
|
||||
are in host byte order. This function will fill in
|
||||
the Ver, HeadLen, and checksum.
|
||||
@param Option The orginal IP4 option to copy from
|
||||
@param OptLen The length of the IP4 option
|
||||
|
||||
@retval EFI_BAD_BUFFER_SIZE There is no enought room in the head space of
|
||||
Packet.
|
||||
@retval EFI_SUCCESS The IP4 header is successfully added to the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4PrependHead (
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_HEAD *Head,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen
|
||||
)
|
||||
{
|
||||
UINT32 HeadLen;
|
||||
UINT32 Len;
|
||||
IP4_HEAD *PacketHead;
|
||||
BOOLEAN FirstFragment;
|
||||
|
||||
//
|
||||
// Prepend the options: first get the option length, then copy it over.
|
||||
//
|
||||
HeadLen = 0;
|
||||
FirstFragment = IP4_FIRST_FRAGMENT (Head->Fragment);
|
||||
|
||||
Ip4CopyOption (Option, OptLen, FirstFragment, NULL, &Len);
|
||||
|
||||
HeadLen = IP4_MIN_HEADLEN + Len;
|
||||
ASSERT (((Len %4) == 0) && (HeadLen <= IP4_MAX_HEADLEN));
|
||||
|
||||
PacketHead = (IP4_HEAD *) NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD);
|
||||
|
||||
if (PacketHead == NULL) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
Ip4CopyOption (Option, OptLen, FirstFragment, (UINT8 *) (PacketHead + 1), &Len);
|
||||
|
||||
//
|
||||
// Set the head up, convert the host byte order to network byte order
|
||||
//
|
||||
PacketHead->Ver = 4;
|
||||
PacketHead->HeadLen = (UINT8) (HeadLen >> 2);
|
||||
PacketHead->Tos = Head->Tos;
|
||||
PacketHead->TotalLen = HTONS (Packet->TotalSize);
|
||||
PacketHead->Id = HTONS (Head->Id);
|
||||
PacketHead->Fragment = HTONS (Head->Fragment);
|
||||
PacketHead->Checksum = 0;
|
||||
PacketHead->Ttl = Head->Ttl;
|
||||
PacketHead->Protocol = Head->Protocol;
|
||||
PacketHead->Src = HTONL (Head->Src);
|
||||
PacketHead->Dst = HTONL (Head->Dst);
|
||||
PacketHead->Checksum = ~NetblockChecksum ((UINT8 *) PacketHead, HeadLen);
|
||||
|
||||
Packet->Ip = PacketHead;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Select an interface to send the packet generated in the IP4 driver
|
||||
itself, that is, not by the requests of IP4 child's consumer. Such
|
||||
packets include the ICMP echo replies, and other ICMP error packets.
|
||||
|
||||
@param IpSb The IP4 service that wants to send the packets.
|
||||
@param Dst The destination of the packet
|
||||
@param Src The source of the packet
|
||||
|
||||
@return NULL if no proper interface is found, otherwise the interface that
|
||||
@return can be used to send the system packet from.
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4SelectInterface (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src
|
||||
)
|
||||
{
|
||||
IP4_INTERFACE *IpIf;
|
||||
IP4_INTERFACE *Selected;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
|
||||
//
|
||||
// Select the interface the Dst is on if one of the connected
|
||||
// network. Some IP instance may be configured with 0.0.0.0/0,
|
||||
// don't select that interface now.
|
||||
//
|
||||
IpIf = Ip4FindNet (IpSb, Dst);
|
||||
|
||||
if ((IpIf != NULL) && (IpIf->Ip != IP4_ALLZERO_ADDRESS)) {
|
||||
return IpIf;
|
||||
}
|
||||
|
||||
//
|
||||
// If source is one of the interface address, select it.
|
||||
//
|
||||
IpIf = Ip4FindInterface (IpSb, Src);
|
||||
|
||||
if ((IpIf != NULL) && (IpIf->Ip != IP4_ALLZERO_ADDRESS)) {
|
||||
return IpIf;
|
||||
}
|
||||
|
||||
//
|
||||
// Select a configured interface as the fall back. Always prefer
|
||||
// an interface with non-zero address.
|
||||
//
|
||||
Selected = NULL;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && ((Selected == NULL) || (Selected->Ip == 0))) {
|
||||
Selected = IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return Selected;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The default callback function for system generated packet.
|
||||
It will free the packet.
|
||||
|
||||
@param Ip4Instance The IP4 child that issued the transmission. It most
|
||||
like is NULL.
|
||||
@param Packet The packet that transmitted.
|
||||
@param IoStatus The result of the transmission, succeeded or failed.
|
||||
@param LinkFlag Not used when transmission. check IP4_FRAME_CALLBACK
|
||||
for reference.
|
||||
@param Context The context provided by us
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4SysPacketSent (
|
||||
IP4_PROTOCOL *Ip4Instance,
|
||||
NET_BUF *Packet,
|
||||
EFI_STATUS IoStatus,
|
||||
UINT32 LinkFlag,
|
||||
VOID *Context
|
||||
)
|
||||
{
|
||||
NetbufFree (Packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Transmit an IP4 packet. The packet comes either from the IP4
|
||||
child's consumer (IpInstance != NULL) or the IP4 driver itself
|
||||
(IpInstance == NULL). It will route the packet, fragment it,
|
||||
then transmit all the fragments through some interface.
|
||||
|
||||
@param IpSb The IP4 service instance to transmit the packet
|
||||
@param IpInstance The IP4 child that issues the transmission. It is
|
||||
NULL if the packet is from the system.
|
||||
@param Packet The user data to send, excluding the IP header.
|
||||
@param Head The caller supplied header. The caller should set
|
||||
the following header fields: Tos, TotalLen, Id, tl,
|
||||
Fragment, Protocol, Src and Dst. All the fields are
|
||||
in host byte order. This function will fill in the
|
||||
Ver, HeadLen, Fragment, and checksum. The Fragment
|
||||
only need to include the DF flag. Ip4Output will
|
||||
compute the MF and offset for you.
|
||||
@param Option The original option to append to the IP headers
|
||||
@param OptLen The length of the option
|
||||
@param GateWay The next hop address to transmit packet to.
|
||||
255.255.255.255 means broadcast.
|
||||
@param Callback The callback function to issue when transmission
|
||||
completed.
|
||||
@param Context The opaque context for the callback
|
||||
|
||||
@retval EFI_NO_MAPPING There is no interface to the destination.
|
||||
@retval EFI_NOT_FOUND There is no route to the destination
|
||||
@retval EFI_SUCCESS The packet is successfully transmitted.
|
||||
@retval Others Failed to transmit the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Output (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_PROTOCOL *IpInstance, OPTIONAL
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_HEAD *Head,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen,
|
||||
IN IP4_ADDR GateWay,
|
||||
IN IP4_FRAME_CALLBACK Callback,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
IP4_INTERFACE *IpIf;
|
||||
IP4_ROUTE_CACHE_ENTRY *CacheEntry;
|
||||
IP4_ADDR Dest;
|
||||
EFI_STATUS Status;
|
||||
NET_BUF *Fragment;
|
||||
UINT32 Index;
|
||||
UINT32 HeadLen;
|
||||
UINT32 PacketLen;
|
||||
UINT32 Offset;
|
||||
UINT32 Mtu;
|
||||
UINT32 Num;
|
||||
|
||||
//
|
||||
// Select an interface/source for system packet, application
|
||||
// should select them itself.
|
||||
//
|
||||
if (IpInstance == NULL) {
|
||||
IpIf = Ip4SelectInterface (IpSb, Head->Dst, Head->Src);
|
||||
} else {
|
||||
IpIf = IpInstance->Interface;
|
||||
}
|
||||
|
||||
if (IpIf == NULL) {
|
||||
return EFI_NO_MAPPING;
|
||||
}
|
||||
|
||||
if ((Head->Src == IP4_ALLZERO_ADDRESS) && (IpInstance == NULL)) {
|
||||
Head->Src = IpIf->Ip;
|
||||
}
|
||||
|
||||
//
|
||||
// Route the packet unless overrided, that is, GateWay isn't zero.
|
||||
//
|
||||
if (GateWay == IP4_ALLZERO_ADDRESS) {
|
||||
Dest = Head->Dst;
|
||||
|
||||
if (IP4_IS_BROADCAST (Ip4GetNetCast (Dest, IpIf)) || (Dest == IP4_ALLONE_ADDRESS)) {
|
||||
//
|
||||
// Set the gateway to local broadcast if the Dest is
|
||||
// is the broadcast address for the connected network
|
||||
// or it is local broadcast.
|
||||
//
|
||||
GateWay = IP4_ALLONE_ADDRESS;
|
||||
|
||||
} else if (IP4_IS_MULTICAST (Dest)) {
|
||||
//
|
||||
// Set the gateway to the destination if it is an multicast
|
||||
// address. The IP4_INTERFACE won't consult ARP to send local
|
||||
// broadcast and multicast.
|
||||
//
|
||||
GateWay = Head->Dst;
|
||||
|
||||
} else {
|
||||
//
|
||||
// Consult the route table to route the packet
|
||||
//
|
||||
if (IpInstance == NULL) {
|
||||
CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src);
|
||||
} else {
|
||||
CacheEntry = Ip4Route (IpInstance->RouteTable, Head->Dst, Head->Src);
|
||||
}
|
||||
|
||||
if (CacheEntry == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
GateWay = CacheEntry->NextHop;
|
||||
Ip4FreeRouteCacheEntry (CacheEntry);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// OK, selected the source and route, fragment the packet then send
|
||||
// them. Tag each fragment other than the first one as spawn from it.
|
||||
//
|
||||
Mtu = IpSb->SnpMode.MaxPacketSize;
|
||||
HeadLen = sizeof (IP4_HEAD) + (OptLen + 3) &~0x03;
|
||||
Head->Id = mIp4Id++;
|
||||
|
||||
if (Packet->TotalSize + HeadLen > Mtu) {
|
||||
//
|
||||
// Packet is fragmented from the tail to the head, that is, the
|
||||
// first frame sent is the last fragment of the packet. The first
|
||||
// fragment is NOT sent in this loop. First compute how many
|
||||
// fragments there are.
|
||||
//
|
||||
Mtu = (Mtu - HeadLen) & (~0x07);
|
||||
Num = (Packet->TotalSize + Mtu - 1) / Mtu;
|
||||
|
||||
//
|
||||
// Initialize the packet length and Offset. Other than the last
|
||||
// fragment, the packet length equals to MTU. The offset is always
|
||||
// aligned to MTU.
|
||||
//
|
||||
PacketLen = Packet->TotalSize - (Num - 1) * Mtu;
|
||||
Offset = Mtu * (Num - 1);
|
||||
|
||||
for (Index = 0; Index < Num - 1; Index++, Offset -= Mtu) {
|
||||
Fragment = NetbufGetFragment (Packet, Offset, PacketLen, IP4_MAX_HEADLEN);
|
||||
|
||||
if (Fragment == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Update the header's fragment. The caller fills the IP4 header
|
||||
// fields that are required by Ip4PrependHead except the fragment.
|
||||
//
|
||||
Head->Fragment = IP4_HEAD_FRAGMENT_FIELD (FALSE, (Index != 0), Offset);
|
||||
Ip4PrependHead (Fragment, Head, Option, OptLen);
|
||||
|
||||
//
|
||||
// Transmit the fragments, pass the Packet address as the context.
|
||||
// So, we can find all the fragments spawned from the Packet by
|
||||
// compare the NetBuf and Context to the Packet.
|
||||
//
|
||||
Status = Ip4SendFrame (
|
||||
IpIf,
|
||||
IpInstance,
|
||||
Fragment,
|
||||
GateWay,
|
||||
Ip4SysPacketSent,
|
||||
Packet
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
PacketLen = Mtu;
|
||||
}
|
||||
|
||||
//
|
||||
// Trim the already sent data, then adjust the head's fragment field.
|
||||
//
|
||||
NetbufTrim (Packet, Packet->TotalSize - Mtu, FALSE);
|
||||
Head->Fragment = IP4_HEAD_FRAGMENT_FIELD (FALSE, TRUE, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Send the first fragment, it is either the orginal packet, or the
|
||||
// first fragment of a fragmented packet. It seems that there is a subtle
|
||||
// bug here: what if the caller free the packet in Callback and IpIf (or
|
||||
// MNP child used by that interface) still holds the fragments and try
|
||||
// to access the data? The caller can free the packet if it recycles the
|
||||
// consumer's (such as UDP) data in the Callback. But this can't happen.
|
||||
// The detailed sequence is:
|
||||
// 1. for the packets generated by IP4 driver itself:
|
||||
// The Callback is Ip4SysPacketSent, which is the same as the
|
||||
// fragments' callback. Ip4SysPacketSent simply calls NetbufFree
|
||||
// to release its reference to the packet. So, no problem for
|
||||
// system packets.
|
||||
//
|
||||
// 2. for the upper layer's packets (use UDP as an example):
|
||||
// UDP requests the IP layer to transmit some data which is
|
||||
// wrapped in an asynchronous token, the token is wrapped
|
||||
// in IP4_TXTOKEN_WRAP by IP4. IP4 also wrap the user's data
|
||||
// in a net buffer, which is Packet we get here. IP4_TXTOKEN_WRAP
|
||||
// is bound with the Packet. It will only be freed when all
|
||||
// the references to Packet have been released. Upon then, the
|
||||
// Packet's OnFree callback will release the IP4_TXTOKEN_WRAP,
|
||||
// and singal the user's recycle event. So, also no problem for
|
||||
// upper layer's packets.
|
||||
//
|
||||
Ip4PrependHead (Packet, Head, Option, OptLen);
|
||||
Status = Ip4SendFrame (IpIf, IpInstance, Packet, GateWay, Callback, Context);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
Ip4CancelPacket (IpIf, Packet, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The filter function to find a packet and all its fragments.
|
||||
The packet's fragments have their Context set to the packet.
|
||||
|
||||
@param Frame The frames hold by the low level interface
|
||||
@param Context Context to the function, which is the packet.
|
||||
|
||||
@retval TRUE This is the packet to cancel or its fragments.
|
||||
@retval FALSE This is unrelated packet.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
Ip4CancelPacketFragments (
|
||||
IP4_LINK_TX_TOKEN *Frame,
|
||||
VOID *Context
|
||||
)
|
||||
{
|
||||
if ((Frame->Packet == (NET_BUF *) Context) || (Frame->Context == Context)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Cancel the Packet and all its fragments.
|
||||
|
||||
@param IpIf The interface from which the Packet is sent
|
||||
@param Packet The Packet to cancel
|
||||
@param IoStatus The status returns to the sender.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4CancelPacket (
|
||||
IN IP4_INTERFACE *IpIf,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus
|
||||
)
|
||||
{
|
||||
Ip4CancelFrames (IpIf, IoStatus, Ip4CancelPacketFragments, Packet);
|
||||
}
|
54
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.h
Normal file
54
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Output.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_OUTPUT_H__
|
||||
#define __EFI_IP4_OUTPUT_H__
|
||||
|
||||
VOID
|
||||
Ip4SysPacketSent (
|
||||
IP4_PROTOCOL *Ip4Instance,
|
||||
NET_BUF *Packet,
|
||||
EFI_STATUS IoStatus,
|
||||
UINT32 Flag,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4Output (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_PROTOCOL *IpInstance, OPTIONAL
|
||||
IN NET_BUF *Data,
|
||||
IN IP4_HEAD *Head,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen,
|
||||
IN IP4_ADDR GateWay,
|
||||
IN IP4_FRAME_CALLBACK Callback,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4CancelPacket (
|
||||
IN IP4_INTERFACE *IpIf,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus
|
||||
);
|
||||
|
||||
extern UINT16 mIp4Id;
|
||||
#endif
|
690
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.c
Normal file
690
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.c
Normal file
@@ -0,0 +1,690 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Route.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Allocate a route entry then initialize it with the Dest/Netmaks
|
||||
and Gateway.
|
||||
|
||||
@param Dest The destination network
|
||||
@param Netmask The destination network mask
|
||||
@param GateWay The nexthop address
|
||||
|
||||
@return NULL if failed to allocate memeory, otherwise the newly created
|
||||
@return route entry.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
IP4_ROUTE_ENTRY *
|
||||
Ip4CreateRouteEntry (
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR GateWay
|
||||
)
|
||||
{
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
|
||||
RtEntry = NetAllocatePool (sizeof (IP4_ROUTE_ENTRY));
|
||||
|
||||
if (RtEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetListInit (&RtEntry->Link);
|
||||
|
||||
RtEntry->RefCnt = 1;
|
||||
RtEntry->Dest = Dest;
|
||||
RtEntry->Netmask = Netmask;
|
||||
RtEntry->NextHop = GateWay;
|
||||
RtEntry->Flag = 0;
|
||||
|
||||
return RtEntry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free the route table entry. It is reference counted.
|
||||
|
||||
@param RtEntry The route entry to free.
|
||||
|
||||
@return NONE
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
Ip4FreeRouteEntry (
|
||||
IN IP4_ROUTE_ENTRY *RtEntry
|
||||
)
|
||||
{
|
||||
ASSERT (RtEntry->RefCnt > 0);
|
||||
|
||||
if (--RtEntry->RefCnt == 0) {
|
||||
NetFreePool (RtEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Allocate and initialize a IP4 route cache entry.
|
||||
|
||||
@param Dst The destination address
|
||||
@param Src The source address
|
||||
@param GateWay The next hop address
|
||||
@param Tag The tag from the caller. This marks all the cache
|
||||
entries spawned from one route table entry.
|
||||
|
||||
@return NULL if failed to allocate memory for the cache, other point
|
||||
@return to the created route cache entry.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4CreateRouteCacheEntry (
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src,
|
||||
IN IP4_ADDR GateWay,
|
||||
IN UINTN Tag
|
||||
)
|
||||
{
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
|
||||
RtCacheEntry = NetAllocatePool (sizeof (IP4_ROUTE_CACHE_ENTRY));
|
||||
|
||||
if (RtCacheEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetListInit (&RtCacheEntry->Link);
|
||||
|
||||
RtCacheEntry->RefCnt = 1;
|
||||
RtCacheEntry->Dest = Dst;
|
||||
RtCacheEntry->Src = Src;
|
||||
RtCacheEntry->NextHop = GateWay;
|
||||
RtCacheEntry->Tag = Tag;
|
||||
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free the route cache entry. It is reference counted.
|
||||
|
||||
@param RtCacheEntry The route cache entry to free.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4FreeRouteCacheEntry (
|
||||
IN IP4_ROUTE_CACHE_ENTRY *RtCacheEntry
|
||||
)
|
||||
{
|
||||
ASSERT (RtCacheEntry->RefCnt > 0);
|
||||
|
||||
if (--RtCacheEntry->RefCnt == 0) {
|
||||
NetFreePool (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialize an empty route cache table.
|
||||
|
||||
@param RtCache The rotue cache table to initialize.
|
||||
|
||||
@return NONE
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4InitRouteCache (
|
||||
IN IP4_ROUTE_CACHE *RtCache
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < IP4_ROUTE_CACHE_HASH; Index++) {
|
||||
NetListInit (&(RtCache->CacheBucket[Index]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Clean up a route cache, that is free all the route cache
|
||||
entries enqueued in the cache.
|
||||
|
||||
@param RtCache The route cache table to clean up
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4CleanRouteCache (
|
||||
IN IP4_ROUTE_CACHE *RtCache
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < IP4_ROUTE_CACHE_HASH; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &(RtCache->CacheBucket[Index])) {
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
NetListRemoveEntry (Entry);
|
||||
Ip4FreeRouteCacheEntry (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Create an empty route table, includes its internal route cache
|
||||
|
||||
None
|
||||
|
||||
@return NULL if failed to allocate memory for the route table, otherwise
|
||||
@return the point to newly created route table.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_TABLE *
|
||||
Ip4CreateRouteTable (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
IP4_ROUTE_TABLE *RtTable;
|
||||
UINT32 Index;
|
||||
|
||||
RtTable = NetAllocatePool (sizeof (IP4_ROUTE_TABLE));
|
||||
|
||||
if (RtTable == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RtTable->RefCnt = 1;
|
||||
RtTable->TotalNum = 0;
|
||||
|
||||
for (Index = 0; Index < IP4_MASK_NUM; Index++) {
|
||||
NetListInit (&(RtTable->RouteArea[Index]));
|
||||
}
|
||||
|
||||
RtTable->Next = NULL;
|
||||
|
||||
Ip4InitRouteCache (&RtTable->Cache);
|
||||
return RtTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free the route table and its associated route cache. Route
|
||||
table is reference counted.
|
||||
|
||||
@param RtTable The route table to free.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4FreeRouteTable (
|
||||
IN IP4_ROUTE_TABLE *RtTable
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
UINT32 Index;
|
||||
|
||||
ASSERT (RtTable->RefCnt > 0);
|
||||
|
||||
if (--RtTable->RefCnt > 0) {
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Free all the route table entry and its route cache.
|
||||
//
|
||||
for (Index = 0; Index < IP4_MASK_NUM; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &(RtTable->RouteArea[Index])) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
NetListRemoveEntry (Entry);
|
||||
Ip4FreeRouteEntry (RtEntry);
|
||||
}
|
||||
}
|
||||
|
||||
Ip4CleanRouteCache (&RtTable->Cache);
|
||||
|
||||
NetFreePool (RtTable);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Remove all the cache entries bearing the Tag. When a route cache
|
||||
entry is created, it is tagged with the address of route entry
|
||||
from which it is spawned. When a route entry is deleted, the cache
|
||||
entries spawned from it are also deleted.
|
||||
|
||||
@param RtCache Route cache to remove the entries from
|
||||
@param Tag The Tag of the entries to remove
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
Ip4PurgeRouteCache (
|
||||
IN IP4_ROUTE_CACHE *RtCache,
|
||||
IN UINTN Tag
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < IP4_ROUTE_CACHE_HASH; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &RtCache->CacheBucket[Index]) {
|
||||
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
if (RtCacheEntry->Tag == Tag) {
|
||||
NetListRemoveEntry (Entry);
|
||||
Ip4FreeRouteCacheEntry (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add a route entry to the route table. All the IP4_ADDRs are in
|
||||
host byte order.
|
||||
|
||||
@param RtTable Route table to add route to
|
||||
@param Dest The destination of the network
|
||||
@param Netmask The netmask of the destination
|
||||
@param Gateway The next hop address
|
||||
|
||||
@retval EFI_ACCESS_DENIED The same route already exists
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the entry
|
||||
@retval EFI_SUCCESS The route is added successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4AddRoute (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Head;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
|
||||
//
|
||||
// All the route entries with the same netmask length are
|
||||
// linke to the same route area
|
||||
//
|
||||
Head = &(RtTable->RouteArea[NetGetMaskLength (Netmask)]);
|
||||
|
||||
//
|
||||
// First check whether the route exists
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, Head) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
if (IP4_NET_EQUAL (RtEntry->Dest, Dest, Netmask) && (RtEntry->NextHop == Gateway)) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create a route entry and insert it to the route area.
|
||||
//
|
||||
RtEntry = Ip4CreateRouteEntry (Dest, Netmask, Gateway);
|
||||
|
||||
if (RtEntry == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (Gateway == IP4_ALLZERO_ADDRESS) {
|
||||
RtEntry->Flag = IP4_DIRECT_ROUTE;
|
||||
}
|
||||
|
||||
NetListInsertHead (Head, &RtEntry->Link);
|
||||
RtTable->TotalNum++;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove a route entry and all the route caches spawn from it.
|
||||
|
||||
@param RtTable The route table to remove the route from
|
||||
@param Dest The destination network
|
||||
@param Netmask The netmask of the Dest
|
||||
@param Gateway The next hop address
|
||||
|
||||
@retval EFI_SUCCESS The route entry is successfully removed
|
||||
@retval EFI_NOT_FOUND There is no route entry in the table with that
|
||||
properity.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4DelRoute (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Head;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
|
||||
Head = &(RtTable->RouteArea[NetGetMaskLength (Netmask)]);
|
||||
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
if (IP4_NET_EQUAL (RtEntry->Dest, Dest, Netmask) && (RtEntry->NextHop == Gateway)) {
|
||||
Ip4PurgeRouteCache (&RtTable->Cache, (UINTN) RtEntry);
|
||||
NetListRemoveEntry (Entry);
|
||||
Ip4FreeRouteEntry (RtEntry);
|
||||
|
||||
RtTable->TotalNum--;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find a route cache with the dst and src. This is used by ICMP
|
||||
redirect messasge process. All kinds of redirect is treated as
|
||||
host redirect according to RFC1122. So, only route cache entries
|
||||
are modified according to the ICMP redirect message.
|
||||
|
||||
@param RtTable The route table to search the cache for
|
||||
@param Dest The destination address
|
||||
@param Src The source address
|
||||
|
||||
@return NULL if no route entry to the (Dest, Src). Otherwise the point
|
||||
@return to the correct route cache entry.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4FindRouteCache (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
UINT32 Index;
|
||||
|
||||
Index = IP4_ROUTE_CACHE_HASH (Dest, Src);
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &RtTable->Cache.CacheBucket[Index]) {
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
if ((RtCacheEntry->Dest == Dest) && (RtCacheEntry->Src == Src)) {
|
||||
NET_GET_REF (RtCacheEntry);
|
||||
return RtCacheEntry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Search the route table for a most specific match to the Dst. It searches
|
||||
from the longest route area (mask length == 32) to the shortest route area (
|
||||
default routes). In each route area, it will first search the instance's
|
||||
route table, then the default route table. This is required by the following
|
||||
requirements:
|
||||
1. IP search the route table for a most specific match
|
||||
2. The local route entries have precedence over the default route entry.
|
||||
|
||||
@param RtTable The route table to search from
|
||||
@param Dst The destionation address to search
|
||||
|
||||
@return NULL if no route matches the Dst, otherwise the point to the
|
||||
@return most specific route to the Dst.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
IP4_ROUTE_ENTRY *
|
||||
Ip4FindRouteEntry (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dst
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
IP4_ROUTE_TABLE *Table;
|
||||
INTN Index;
|
||||
|
||||
RtEntry = NULL;
|
||||
|
||||
for (Index = IP4_MASK_NUM - 1; Index >= 0; Index--) {
|
||||
for (Table = RtTable; Table != NULL; Table = Table->Next) {
|
||||
NET_LIST_FOR_EACH (Entry, &Table->RouteArea[Index]) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
if (IP4_NET_EQUAL (RtEntry->Dest, Dst, RtEntry->Netmask)) {
|
||||
NET_GET_REF (RtEntry);
|
||||
return RtEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Search the route table to route the packet. Return/creat a route
|
||||
cache if there is a route to the destination.
|
||||
|
||||
@param RtTable The route table to search from
|
||||
@param Dest The destination address to search for
|
||||
@param Src The source address to search for
|
||||
|
||||
@return NULL if failed to route packet, otherwise a route cache
|
||||
@return entry that can be used to route packet.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4Route (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Head;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
IP4_ROUTE_CACHE_ENTRY *Cache;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
IP4_ADDR NextHop;
|
||||
UINT32 Count;
|
||||
|
||||
ASSERT (RtTable != NULL);
|
||||
|
||||
Head = &RtTable->Cache.CacheBucket[IP4_ROUTE_CACHE_HASH (Dest, Src)];
|
||||
RtCacheEntry = Ip4FindRouteCache (RtTable, Dest, Src);
|
||||
|
||||
//
|
||||
// If found, promote the cache entry to the head of the hash bucket. LRU
|
||||
//
|
||||
if (RtCacheEntry != NULL) {
|
||||
NetListRemoveEntry (&RtCacheEntry->Link);
|
||||
NetListInsertHead (Head, &RtCacheEntry->Link);
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
||||
//
|
||||
// Search the route table for the most specific route
|
||||
//
|
||||
RtEntry = Ip4FindRouteEntry (RtTable, Dest);
|
||||
|
||||
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 & IP4_DIRECT_ROUTE) {
|
||||
NextHop = Dest;
|
||||
} else {
|
||||
NextHop = RtEntry->NextHop;
|
||||
}
|
||||
|
||||
Ip4FreeRouteEntry (RtEntry);
|
||||
|
||||
//
|
||||
// Create a route cache entry, and tag it as spawned from this route entry
|
||||
//
|
||||
RtCacheEntry = Ip4CreateRouteCacheEntry (Dest, Src, NextHop, (UINTN) RtEntry);
|
||||
|
||||
if (RtCacheEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetListInsertHead (Head, &RtCacheEntry->Link);
|
||||
NET_GET_REF (RtCacheEntry);
|
||||
|
||||
//
|
||||
// Each bucket of route cache can contain at most 64 entries.
|
||||
// Remove the entries at the tail of the bucket. These entries
|
||||
// are likely to be used least.
|
||||
//
|
||||
Count = 0;
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
|
||||
if (++Count < IP4_ROUTE_CACHE_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Cache = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
NetListRemoveEntry (Entry);
|
||||
Ip4FreeRouteCacheEntry (Cache);
|
||||
}
|
||||
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of
|
||||
GetModeData. The EFI_IP4_ROUTE_TABLE is clumsy to use in the
|
||||
internal operation of the IP4 driver.
|
||||
|
||||
@param IpInstance The IP4 child that requests the route table.
|
||||
|
||||
@retval EFI_SUCCESS The route table is successfully build
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the rotue table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4BuildEfiRouteTable (
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
)
|
||||
{
|
||||
IP4_SERVICE *IpSb;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_TABLE *RtTable;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
EFI_IP4_ROUTE_TABLE *Table;
|
||||
UINT32 Count;
|
||||
INT32 Index;
|
||||
|
||||
IpSb = IpInstance->Service;
|
||||
RtTable = IpInstance->RouteTable;
|
||||
|
||||
if (IpInstance->EfiRouteTable != NULL) {
|
||||
NetFreePool (IpInstance->EfiRouteTable);
|
||||
|
||||
IpInstance->EfiRouteTable = NULL;
|
||||
IpInstance->EfiRouteCount = 0;
|
||||
}
|
||||
|
||||
Count = RtTable->TotalNum;
|
||||
|
||||
if (RtTable->Next != NULL) {
|
||||
Count += RtTable->Next->TotalNum;
|
||||
}
|
||||
|
||||
if (Count == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Table = NetAllocatePool (sizeof (EFI_IP4_ROUTE_TABLE) * Count);
|
||||
|
||||
if (Table == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the route entry to EFI route table. Keep the order of
|
||||
// route entry copied from most specific to default route. That
|
||||
// is, interlevel the route entry from the instance's route area
|
||||
// and those from the default route table's route area.
|
||||
//
|
||||
Count = 0;
|
||||
|
||||
for (Index = IP4_MASK_NUM - 1; Index >= 0; Index--) {
|
||||
for (RtTable = IpInstance->RouteTable; RtTable != NULL; RtTable = RtTable->Next) {
|
||||
NET_LIST_FOR_EACH (Entry, &(RtTable->RouteArea[Index])) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
EFI_IP4 (Table[Count].SubnetAddress) = HTONL (RtEntry->Dest & RtEntry->Netmask);
|
||||
EFI_IP4 (Table[Count].SubnetMask) = HTONL (RtEntry->Netmask);
|
||||
EFI_IP4 (Table[Count].GatewayAddress) = HTONL (RtEntry->NextHop);
|
||||
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IpInstance->EfiRouteTable = Table;
|
||||
IpInstance->EfiRouteCount = Count;
|
||||
return EFI_SUCCESS;
|
||||
}
|
151
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.h
Normal file
151
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. 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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
Ip4Route.h
|
||||
|
||||
Abstract:
|
||||
|
||||
EFI IP4 route table and route cache table defintions.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_ROUTE_H__
|
||||
#define __EFI_IP4_ROUTE_H__
|
||||
|
||||
#include "IP4Common.h"
|
||||
|
||||
enum {
|
||||
IP4_DIRECT_ROUTE = 0x00000001,
|
||||
|
||||
IP4_ROUTE_CACHE_HASH = 31,
|
||||
IP4_ROUTE_CACHE_MAX = 64, // Max NO. of cache entry per hash bucket
|
||||
};
|
||||
|
||||
#define IP4_ROUTE_CACHE_HASH(Dst, Src) (((Dst) ^ (Src)) % IP4_ROUTE_CACHE_HASH)
|
||||
|
||||
//
|
||||
// The route entry in the route table. Dest/Netmask is the destion
|
||||
// network. The nexthop is the gateway to send the packet to in
|
||||
// order to reach the Dest/Netmask. If the Flag has IP4_DIRECT_ROUTE
|
||||
// on, the gateway is the destination of the IP packet itself. Route
|
||||
// enties of the connected network have the flag on.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
IP4_ADDR Dest;
|
||||
IP4_ADDR Netmask;
|
||||
IP4_ADDR NextHop;
|
||||
UINT32 Flag;
|
||||
} IP4_ROUTE_ENTRY;
|
||||
|
||||
//
|
||||
// The route cache entry. The route cache entry is optional.
|
||||
// But it is necessary to support the ICMP redirect message.
|
||||
// Check Ip4ProcessIcmpRedirect for information.
|
||||
//
|
||||
// The cache entry field Tag is used to tag all the route
|
||||
// cache entry spawned from a route table entry. This makes
|
||||
// it simple to delete all the route cache entries from a
|
||||
// to-be-deleted route entry.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
IP4_ADDR Dest;
|
||||
IP4_ADDR Src;
|
||||
IP4_ADDR NextHop;
|
||||
UINTN Tag;
|
||||
} IP4_ROUTE_CACHE_ENTRY;
|
||||
|
||||
//
|
||||
// The route cache table is organized as a hash table. Each
|
||||
// IP4 route table has a embedded route cache. For now the
|
||||
// route cache and route table are binded togehter. But keep
|
||||
// the route cache a seperated structure in case we want to
|
||||
// detach them later.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY CacheBucket[IP4_ROUTE_CACHE_HASH];
|
||||
} IP4_ROUTE_CACHE;
|
||||
|
||||
//
|
||||
// Each IP4 instance has its own route table. Each ServiceBinding
|
||||
// instance has a default route table and default address.
|
||||
//
|
||||
// All the route table entries with the same mask are linked
|
||||
// together in one route area. For example, RouteArea[0] contains
|
||||
// the default routes. A route table also contains a route cache.
|
||||
//
|
||||
typedef struct _IP4_ROUTE_TABLE IP4_ROUTE_TABLE;
|
||||
|
||||
typedef struct _IP4_ROUTE_TABLE {
|
||||
INTN RefCnt;
|
||||
UINT32 TotalNum;
|
||||
NET_LIST_ENTRY RouteArea[IP4_MASK_NUM];
|
||||
IP4_ROUTE_TABLE *Next;
|
||||
IP4_ROUTE_CACHE Cache;
|
||||
};
|
||||
|
||||
IP4_ROUTE_TABLE*
|
||||
Ip4CreateRouteTable (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4FreeRouteTable (
|
||||
IN IP4_ROUTE_TABLE *RouteTable
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4AddRoute (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4DelRoute (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
);
|
||||
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4FindRouteCache (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4FreeRouteCacheEntry (
|
||||
IN IP4_ROUTE_CACHE_ENTRY *RtCacheEntry
|
||||
);
|
||||
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4Route (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4BuildEfiRouteTable (
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
);
|
||||
#endif
|
Reference in New Issue
Block a user