Add NetworkPkg (P.UDK2010.UP3.Network.P1)

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10986 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
hhtian
2010-11-01 06:13:54 +00:00
parent 12873d5766
commit a3bcde70e6
142 changed files with 83988 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
/** @file
The interface function declaration of shell application IfConfig6.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _IFCONFIG6_H_
#define _IFCONFIG6_H_
#define EFI_IFCONFIG6_GUID \
{ \
0xbab7296b, 0x222c, 0x4408, {0x9e, 0x6c, 0xc2, 0x5c, 0x18, 0x7e, 0xff, 0x33} \
}
enum {
IfConfig6OpList = 1,
IfConfig6OpSet = 2,
IfConfig6OpClear = 3
};
typedef enum {
VarCheckReserved = -1,
VarCheckOk = 0,
VarCheckDuplicate,
VarCheckConflict,
VarCheckUnknown,
VarCheckLackValue,
VarCheckOutOfMem
} VAR_CHECK_CODE;
typedef enum {
FlagTypeSingle = 0,
FlagTypeNeedVar,
FlagTypeNeedSet,
FlagTypeSkipUnknown
} VAR_CHECK_FLAG_TYPE;
#define MACADDRMAXSIZE 32
#define PREFIXMAXLEN 16
typedef struct _IFCONFIG6_INTERFACE_CB {
EFI_HANDLE NicHandle;
LIST_ENTRY Link;
EFI_IP6_CONFIG_PROTOCOL *IfCfg;
EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
EFI_IP6_CONFIG_INTERFACE_ID *IfId;
EFI_IP6_CONFIG_POLICY Policy;
EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS Xmits;
UINT32 DnsCnt;
EFI_IPv6_ADDRESS DnsAddr[1];
} IFCONFIG6_INTERFACE_CB;
typedef struct _ARG_LIST ARG_LIST;
struct _ARG_LIST {
ARG_LIST *Next;
CHAR16 *Arg;
};
typedef struct _IFCONFIG6_PRIVATE_DATA {
EFI_HANDLE ImageHandle;
LIST_ENTRY IfList;
UINT32 OpCode;
CHAR16 *IfName;
ARG_LIST *VarArg;
} IFCONFIG6_PRIVATE_DATA;
typedef struct _VAR_CHECK_ITEM{
CHAR16 *FlagStr;
UINT32 FlagID;
UINT32 ConflictMask;
VAR_CHECK_FLAG_TYPE FlagType;
} VAR_CHECK_ITEM;
#endif

View File

@@ -0,0 +1,52 @@
## @file
# Component description file for Shell application IfConfig6.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010006
BASE_NAME = IfConfig6
FILE_GUID = 6F71926E-60CE-428d-AA58-A3D9FB879429
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = IfConfig6Initialize
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF
#
[Sources]
IfConfig6Strings.uni
IfConfig6.c
IfConfig6.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
BaseLib
UefiBootServicesTableLib
UefiApplicationEntryPoint
BaseMemoryLib
ShellLib
MemoryAllocationLib
DebugLib
HiiLib
NetLib
[Protocols]
gEfiIp6ServiceBindingProtocolGuid ## CONSUMS
gEfiIp6ConfigProtocolGuid ## CONSUMS

Binary file not shown.

View File

@@ -0,0 +1,110 @@
/** @file
The implementation of delete policy entry function in IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "IpSecConfig.h"
#include "Indexer.h"
#include "Delete.h"
#include "Match.h"
#include "ForEach.h"
/**
Private function to delete entry information in database.
@param[in] Selector The pointer to EFI_IPSEC_CONFIG_SELECTOR structure.
@param[in] Data The pointer to Data.
@param[in] Context The pointer to DELETE_POLICY_ENTRY_CONTEXT.
@retval EFI_ABORTED Abort the iteration.
@retval EFI_SUCCESS Continue the iteration.
**/
EFI_STATUS
DeletePolicyEntry (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN DELETE_POLICY_ENTRY_CONTEXT *Context
)
{
if (mMatchPolicyEntry[Context->DataType] (Selector, Data, &Context->Indexer)) {
Context->Status = mIpSecConfig->SetData (
mIpSecConfig,
Context->DataType,
Selector,
NULL,
NULL
);
//
// Abort the iteration after the insertion.
//
return EFI_ABORTED;
}
return EFI_SUCCESS;
}
/**
Flush or delete entry information in the database according to datatype.
@param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE.
@param[in] ParamPackage The pointer to the ParamPackage list.
@retval EFI_SUCCESS Delete entry information successfully.
@retval EFI_NOT_FOUND Can't find the specified entry.
@retval Others Some mistaken case.
**/
EFI_STATUS
FlushOrDeletePolicyEntry (
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN LIST_ENTRY *ParamPackage
)
{
EFI_STATUS Status;
DELETE_POLICY_ENTRY_CONTEXT Context;
CONST CHAR16 *ValueStr;
//
// If user wants to remove all.
//
if (ShellCommandLineGetFlag (ParamPackage, L"-f")) {
Status = mIpSecConfig->SetData (
mIpSecConfig,
DataType,
NULL,
NULL,
NULL
);
} else {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-d");
if (ValueStr == NULL) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_SPECIFIED), mHiiHandle, mAppName, ValueStr);
return EFI_NOT_FOUND;
}
Status = mConstructPolicyEntryIndexer[DataType] (&Context.Indexer, ParamPackage);
if (!EFI_ERROR (Status)) {
Context.DataType = DataType;
Context.Status = EFI_NOT_FOUND;
ForeachPolicyEntry (DataType, (VISIT_POLICY_ENTRY) DeletePolicyEntry, &Context);
Status = Context.Status;
if (Status == EFI_NOT_FOUND) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_FOUND), mHiiHandle, mAppName, ValueStr);
} else if (EFI_ERROR (Status)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_DELETE_FAILED), mHiiHandle, mAppName);
}
}
}
return Status;
}

View File

@@ -0,0 +1,42 @@
/** @file
The internal structure and function declaration of delete policy entry function
in IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __DELETE_H_
#define __DELETE_H_
typedef struct {
EFI_IPSEC_CONFIG_DATA_TYPE DataType;
POLICY_ENTRY_INDEXER Indexer;
EFI_STATUS Status; //Indicate whether deletion succeeds.
} DELETE_POLICY_ENTRY_CONTEXT;
/**
Flush or delete entry information in the database according to datatype.
@param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE.
@param[in] ParamPackage The pointer to the ParamPackage list.
@retval EFI_SUCCESS Delete entry information successfully.
@retval EFI_NOT_FOUND Can't find the specified entry.
@retval Others Some mistaken case.
**/
EFI_STATUS
FlushOrDeletePolicyEntry (
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN LIST_ENTRY *ParamPackage
);
#endif

View File

@@ -0,0 +1,530 @@
/** @file
The implementation of dump policy entry function in IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "IpSecConfig.h"
#include "Dump.h"
#include "ForEach.h"
#include "Helper.h"
/**
Private function called to get the version infomation from an EFI_IP_ADDRESS_INFO structure.
@param[in] AddressInfo The pointer to the EFI_IP_ADDRESS_INFO structure.
@return the value of version.
**/
UINTN
GetVerFromAddrInfo (
IN EFI_IP_ADDRESS_INFO *AddressInfo
)
{
if((AddressInfo->PrefixLength <= 32) && (AddressInfo->Address.Addr[1] == 0) &&
(AddressInfo->Address.Addr[2] == 0) && (AddressInfo->Address.Addr[3] == 0)) {
return IP_VERSION_4;
} else {
return IP_VERSION_6;
}
}
/**
Private function called to get the version information from a EFI_IP_ADDRESS structure.
@param[in] Address The pointer to the EFI_IP_ADDRESS structure.
@return The value of the version.
**/
UINTN
GetVerFromIpAddr (
IN EFI_IP_ADDRESS *Address
)
{
if ((Address->Addr[1] == 0) && (Address->Addr[2] == 0) && (Address->Addr[3] == 0)) {
return IP_VERSION_4;
} else {
return IP_VERSION_6;
}
}
/**
Private function called to print an ASCII string in unicode char format.
@param[in] Str The pointer to the ASCII string.
@param[in] Length The value of the ASCII string length.
**/
VOID
DumpAsciiString (
IN CHAR8 *Str,
IN UINTN Length
)
{
UINTN Index;
for (Index = 0; Index < Length; Index++) {
Print (L"%c", (CHAR16) Str[Index]);
}
}
/**
Private function called to print EFI_IP_ADDRESS_INFO content.
@param[in] AddressInfo The pointer to the EFI_IP_ADDRESS_INFO structure.
**/
VOID
DumpAddressInfo (
IN EFI_IP_ADDRESS_INFO *AddressInfo
)
{
if (IP_VERSION_4 == GetVerFromAddrInfo (AddressInfo)) {
Print (
L"%d.%d.%d.%d",
(UINTN) AddressInfo->Address.v4.Addr[0],
(UINTN) AddressInfo->Address.v4.Addr[1],
(UINTN) AddressInfo->Address.v4.Addr[2],
(UINTN) AddressInfo->Address.v4.Addr[3]
);
if (AddressInfo->PrefixLength != 32) {
Print (L"/%d", (UINTN) AddressInfo->PrefixLength);
}
}
if (IP_VERSION_6 == GetVerFromAddrInfo (AddressInfo)) {
Print (
L"%x:%x:%x:%x:%x:%x:%x:%x",
(((UINT16) AddressInfo->Address.v6.Addr[0]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[1]),
(((UINT16) AddressInfo->Address.v6.Addr[2]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[3]),
(((UINT16) AddressInfo->Address.v6.Addr[4]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[5]),
(((UINT16) AddressInfo->Address.v6.Addr[6]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[7]),
(((UINT16) AddressInfo->Address.v6.Addr[8]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[9]),
(((UINT16) AddressInfo->Address.v6.Addr[10]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[11]),
(((UINT16) AddressInfo->Address.v6.Addr[12]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[13]),
(((UINT16) AddressInfo->Address.v6.Addr[14]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[15])
);
if (AddressInfo->PrefixLength != 128) {
Print (L"/%d", AddressInfo->PrefixLength);
}
}
}
/**
Private function called to print EFI_IP_ADDRESS content.
@param[in] IpAddress The pointer to the EFI_IP_ADDRESS structure.
**/
VOID
DumpIpAddress (
IN EFI_IP_ADDRESS *IpAddress
)
{
if (IP_VERSION_4 == GetVerFromIpAddr (IpAddress)) {
Print (
L"%d.%d.%d.%d",
(UINTN) IpAddress->v4.Addr[0],
(UINTN) IpAddress->v4.Addr[1],
(UINTN) IpAddress->v4.Addr[2],
(UINTN) IpAddress->v4.Addr[3]
);
}
if (IP_VERSION_6 == GetVerFromIpAddr (IpAddress)) {
Print (
L"%x:%x:%x:%x:%x:%x:%x:%x",
(((UINT16) IpAddress->v6.Addr[0]) << 8) | ((UINT16) IpAddress->v6.Addr[1]),
(((UINT16) IpAddress->v6.Addr[2]) << 8) | ((UINT16) IpAddress->v6.Addr[3]),
(((UINT16) IpAddress->v6.Addr[4]) << 8) | ((UINT16) IpAddress->v6.Addr[5]),
(((UINT16) IpAddress->v6.Addr[6]) << 8) | ((UINT16) IpAddress->v6.Addr[7]),
(((UINT16) IpAddress->v6.Addr[8]) << 8) | ((UINT16) IpAddress->v6.Addr[9]),
(((UINT16) IpAddress->v6.Addr[10]) << 8) | ((UINT16) IpAddress->v6.Addr[11]),
(((UINT16) IpAddress->v6.Addr[12]) << 8) | ((UINT16) IpAddress->v6.Addr[13]),
(((UINT16) IpAddress->v6.Addr[14]) << 8) | ((UINT16) IpAddress->v6.Addr[15])
);
}
}
/**
Private function called to print EFI_IPSEC_SPD_SELECTOR content.
@param[in] Selector The pointer to the EFI_IPSEC_SPD_SELECTOR structure.
**/
VOID
DumpSpdSelector (
IN EFI_IPSEC_SPD_SELECTOR *Selector
)
{
UINT32 Index;
CHAR16 *Str;
for (Index = 0; Index < Selector->LocalAddressCount; Index++) {
if (Index > 0) {
Print (L",");
}
DumpAddressInfo (&Selector->LocalAddress[Index]);
}
if (Index == 0) {
Print (L"localhost");
}
Print (L" -> ");
for (Index = 0; Index < Selector->RemoteAddressCount; Index++) {
if (Index > 0) {
Print (L",");
}
DumpAddressInfo (&Selector->RemoteAddress[Index]);
}
Str = MapIntegerToString (Selector->NextLayerProtocol, mMapIpProtocol);
if (Str != NULL) {
Print (L" %s", Str);
} else {
Print (L" proto:%d", (UINTN) Selector->NextLayerProtocol);
}
if ((Selector->NextLayerProtocol == EFI_IP4_PROTO_TCP) || (Selector->NextLayerProtocol == EFI_IP4_PROTO_UDP)) {
Print (L" port:");
if (Selector->LocalPort != EFI_IPSEC_ANY_PORT) {
Print (L"%d", Selector->LocalPort);
if (Selector->LocalPortRange != 0) {
Print (L"~%d", (UINTN) Selector->LocalPort + Selector->LocalPortRange);
}
} else {
Print (L"any");
}
Print (L" -> ");
if (Selector->RemotePort != EFI_IPSEC_ANY_PORT) {
Print (L"%d", Selector->RemotePort);
if (Selector->RemotePortRange != 0) {
Print (L"~%d", (UINTN) Selector->RemotePort + Selector->RemotePortRange);
}
} else {
Print (L"any");
}
} else if (Selector->NextLayerProtocol == EFI_IP4_PROTO_ICMP) {
Print (L" class/code:");
if (Selector->LocalPort != 0) {
Print (L"%d", (UINTN) (UINT8) Selector->LocalPort);
} else {
Print (L"any");
}
Print (L"/");
if (Selector->RemotePort != 0) {
Print (L"%d", (UINTN) (UINT8) Selector->RemotePort);
} else {
Print (L"any");
}
}
}
/**
Print EFI_IPSEC_SPD_SELECTOR and EFI_IPSEC_SPD_DATA content.
@param[in] Selector The pointer to the EFI_IPSEC_SPD_SELECTOR structure.
@param[in] Data The pointer to the EFI_IPSEC_SPD_DATA structure.
@param[in] EntryIndex The pointer to the Index in SPD Database.
@retval EFI_SUCCESS Dump SPD information successfully.
**/
EFI_STATUS
DumpSpdEntry (
IN EFI_IPSEC_SPD_SELECTOR *Selector,
IN EFI_IPSEC_SPD_DATA *Data,
IN UINTN *EntryIndex
)
{
BOOLEAN HasPre;
CHAR16 DataName[128];
CHAR16 *String1;
CHAR16 *String2;
CHAR16 *String3;
UINT8 Index;
Print (L"%d.", (*EntryIndex)++);
//
// xxx.xxx.xxx.xxx/yy -> xxx.xxx.xxx.xx/yy proto:23 port:100~300 -> 300~400
// Protect PF:0x34323423 Name:First Entry
// ext-sequence sequence-overflow fragcheck life:[B0,S1024,H3600]
// ESP algo1 algo2 Tunnel [xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx set]
//
DumpSpdSelector (Selector);
Print (L"\n ");
Print (L"%s ", MapIntegerToString (Data->Action, mMapIpSecAction));
Print (L"PF:%08x ", Data->PackageFlag);
Index = 0;
while (Data->Name[Index] != 0) {
DataName[Index] = (CHAR16) Data->Name[Index];
Index++;
ASSERT (Index < 128);
}
DataName[Index] = L'\0';
Print (L"Name:%s", DataName);
if (Data->Action == EfiIPsecActionProtect) {
Print (L"\n ");
if (Data->ProcessingPolicy->ExtSeqNum) {
Print (L"ext-sequence ");
}
if (Data->ProcessingPolicy->SeqOverflow) {
Print (L"sequence-overflow ");
}
if (Data->ProcessingPolicy->FragCheck) {
Print (L"fragment-check ");
}
HasPre = FALSE;
if (Data->ProcessingPolicy->SaLifetime.ByteCount != 0) {
Print (HasPre ? L"," : L"life:[");
Print (L"%lxB", Data->ProcessingPolicy->SaLifetime.ByteCount);
HasPre = TRUE;
}
if (Data->ProcessingPolicy->SaLifetime.SoftLifetime != 0) {
Print (HasPre ? L"," : L"life:[");
Print (L"%lxs", Data->ProcessingPolicy->SaLifetime.SoftLifetime);
HasPre = TRUE;
}
if (Data->ProcessingPolicy->SaLifetime.HardLifetime != 0) {
Print (HasPre ? L"," : L"life:[");
Print (L"%lxS", Data->ProcessingPolicy->SaLifetime.HardLifetime);
HasPre = TRUE;
}
if (HasPre) {
Print (L"]");
}
if (HasPre || Data->ProcessingPolicy->ExtSeqNum ||
Data->ProcessingPolicy->SeqOverflow || Data->ProcessingPolicy->FragCheck) {
Print (L"\n ");
}
String1 = MapIntegerToString (Data->ProcessingPolicy->Proto, mMapIpSecProtocol);
String2 = MapIntegerToString (Data->ProcessingPolicy->AuthAlgoId, mMapAuthAlgo);
String3 = MapIntegerToString (Data->ProcessingPolicy->EncAlgoId, mMapEncAlgo);
Print (
L"%s Auth:%s Encrypt:%s ",
String1,
String2,
String3
);
Print (L"%s ", MapIntegerToString (Data->ProcessingPolicy->Mode, mMapIpSecMode));
if (Data->ProcessingPolicy->Mode == EfiIPsecTunnel) {
Print (L"[");
DumpIpAddress (&Data->ProcessingPolicy->TunnelOption->LocalTunnelAddress);
Print (L" -> ");
DumpIpAddress (&Data->ProcessingPolicy->TunnelOption->RemoteTunnelAddress);
Print (L" %s]", MapIntegerToString (Data->ProcessingPolicy->TunnelOption->DF, mMapDfOption));
}
}
Print (L"\n");
return EFI_SUCCESS;
}
/**
Print EFI_IPSEC_SA_ID and EFI_IPSEC_SA_DATA content.
@param[in] SaId The pointer to the EFI_IPSEC_SA_ID structure.
@param[in] Data The pointer to the EFI_IPSEC_SA_DATA structure.
@param[in] EntryIndex The pointer to the Index in the SAD Database.
@retval EFI_SUCCESS Dump SAD information successfully.
**/
EFI_STATUS
DumpSadEntry (
IN EFI_IPSEC_SA_ID *SaId,
IN EFI_IPSEC_SA_DATA *Data,
IN UINTN *EntryIndex
)
{
BOOLEAN HasPre;
CHAR16 *String1;
CHAR16 *String2;
//
// SPI:1234 ESP Destination:xxx.xxx.xxx.xxx
// Mode:Transport SeqNum:134 AntiReplayWin:64 life:[0B,1023s,3400S] PathMTU:34
// Auth:xxxx/password Encrypt:yyyy/password
// xxx.xxx.xxx.xxx/yy -> xxx.xxx.xxx.xx/yy proto:23 port:100~300 -> 300~400
//
Print (L"%d.", (*EntryIndex)++);
Print (L"0x%x %s ", (UINTN) SaId->Spi, MapIntegerToString (SaId->Proto, mMapIpSecProtocol));
Print (L"Destination:");
DumpIpAddress (&SaId->DestAddress);
Print (L"\n");
Print (
L" Mode:%s SeqNum:%lx AntiReplayWin:%d ",
MapIntegerToString (Data->Mode, mMapIpSecMode),
Data->SNCount,
(UINTN) Data->AntiReplayWindows
);
HasPre = FALSE;
if (Data->SaLifetime.ByteCount != 0) {
Print (HasPre ? L"," : L"life:[");
Print (L"%lxB", Data->SaLifetime.ByteCount);
HasPre = TRUE;
}
if (Data->SaLifetime.SoftLifetime != 0) {
Print (HasPre ? L"," : L"life:[");
Print (L"%lxs", Data->SaLifetime.SoftLifetime);
HasPre = TRUE;
}
if (Data->SaLifetime.HardLifetime != 0) {
Print (HasPre ? L"," : L"life:[");
Print (L"%lxS", Data->SaLifetime.HardLifetime);
HasPre = TRUE;
}
if (HasPre) {
Print (L"] ");
}
Print (L"PathMTU:%d\n", (UINTN) Data->PathMTU);
if (SaId->Proto == EfiIPsecAH) {
Print (
L" Auth:%s/%s\n",
MapIntegerToString (Data->AlgoInfo.AhAlgoInfo.AuthAlgoId, mMapAuthAlgo),
Data->AlgoInfo.AhAlgoInfo.AuthKey
);
} else {
String1 = MapIntegerToString (Data->AlgoInfo.EspAlgoInfo.AuthAlgoId, mMapAuthAlgo);
String2 = MapIntegerToString (Data->AlgoInfo.EspAlgoInfo.EncAlgoId, mMapEncAlgo);
Print (
L" Auth:%s/%s Encrypt:%s/%s\n",
String1,
Data->AlgoInfo.EspAlgoInfo.AuthKey,
String2,
Data->AlgoInfo.EspAlgoInfo.EncKey
);
}
if (Data->SpdSelector != NULL) {
Print (L" ");
DumpSpdSelector (Data->SpdSelector);
Print (L"\n");
}
return EFI_SUCCESS;
}
/**
Print EFI_IPSEC_PAD_ID and EFI_IPSEC_PAD_DATA content.
@param[in] PadId The pointer to the EFI_IPSEC_PAD_ID structure.
@param[in] Data The pointer to the EFI_IPSEC_PAD_DATA structure.
@param[in] EntryIndex The pointer to the Index in the PAD Database.
@retval EFI_SUCCESS Dump PAD information successfully.
**/
EFI_STATUS
DumpPadEntry (
IN EFI_IPSEC_PAD_ID *PadId,
IN EFI_IPSEC_PAD_DATA *Data,
IN UINTN *EntryIndex
)
{
CHAR16 *String1;
CHAR16 *String2;
//
// ADDR:10.23.17.34/15
// IDEv1 PreSharedSecret IKE-ID
// password
//
Print (L"%d.", (*EntryIndex)++);
if (PadId->PeerIdValid) {
Print (L"ID:%s", PadId->Id.PeerId);
} else {
Print (L"ADDR:");
DumpAddressInfo (&PadId->Id.IpAddress);
}
Print (L"\n");
String1 = MapIntegerToString (Data->AuthProtocol, mMapAuthProto);
String2 = MapIntegerToString (Data->AuthMethod, mMapAuthMethod);
Print (
L" %s %s",
String1,
String2
);
if (Data->IkeIdFlag) {
Print (L"IKE-ID");
}
Print (L"\n");
if (Data->AuthData != NULL) {
DumpAsciiString (Data->AuthData, Data->AuthDataSize);
Print (L"\n");
}
if (Data->RevocationData != NULL) {
Print (L" %s\n", Data->RevocationData);
}
return EFI_SUCCESS;
}
VISIT_POLICY_ENTRY mDumpPolicyEntry[] = {
(VISIT_POLICY_ENTRY) DumpSpdEntry,
(VISIT_POLICY_ENTRY) DumpSadEntry,
(VISIT_POLICY_ENTRY) DumpPadEntry
};
/**
Print all entry information in the database according to datatype.
@param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE.
@param[in] ParamPackage The pointer to the ParamPackage list.
@retval EFI_SUCCESS Dump all information successfully.
@retval Others Some mistaken case.
**/
EFI_STATUS
ListPolicyEntry (
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN LIST_ENTRY *ParamPackage
)
{
UINTN EntryIndex;
EntryIndex = 0;
return ForeachPolicyEntry (DataType, mDumpPolicyEntry[DataType], &EntryIndex);
}

View File

@@ -0,0 +1,34 @@
/** @file
The function declaration of dump policy entry function in IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _DUMP_H_
#define _DUMP_H_
/**
Print all entry information in the database according to datatype.
@param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE.
@param[in] ParamPackage The pointer to the ParamPackage list.
@retval EFI_SUCCESS Dump all information successfully.
@retval Others Some mistaken case.
**/
EFI_STATUS
ListPolicyEntry (
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN LIST_ENTRY *ParamPackage
);
#endif

View File

@@ -0,0 +1,115 @@
/** @file
The implementation to go through each entry in IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "IpSecConfig.h"
#include "ForEach.h"
/**
Enumerate all entries in the database to execute specified operations according to datatype.
@param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE.
@param[in] Routine The pointer to the function of a specified operation.
@param[in] Context The pointer to the context of a function.
@retval EFI_SUCCESS Execute specified operation successfully.
**/
EFI_STATUS
ForeachPolicyEntry (
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN VISIT_POLICY_ENTRY Routine,
IN VOID *Context
)
{
EFI_STATUS GetNextStatus;
EFI_STATUS GetDataStatus;
EFI_IPSEC_CONFIG_SELECTOR *Selector;
VOID *Data;
UINTN SelectorSize;
UINTN DataSize;
BOOLEAN FirstGetNext;
FirstGetNext = TRUE;
SelectorSize = sizeof (EFI_IPSEC_CONFIG_SELECTOR);
Selector = AllocateZeroPool (SelectorSize);
DataSize = 0;
Data = NULL;
while (TRUE) {
GetNextStatus = mIpSecConfig->GetNextSelector (
mIpSecConfig,
DataType,
&SelectorSize,
Selector
);
if (GetNextStatus == EFI_BUFFER_TOO_SMALL) {
gBS->FreePool (Selector);
Selector = FirstGetNext ? AllocateZeroPool (SelectorSize) : AllocatePool (SelectorSize);
GetNextStatus = mIpSecConfig->GetNextSelector (
mIpSecConfig,
DataType,
&SelectorSize,
Selector
);
}
if (EFI_ERROR (GetNextStatus)) {
break;
}
FirstGetNext = FALSE;
GetDataStatus = mIpSecConfig->GetData (
mIpSecConfig,
DataType,
Selector,
&DataSize,
Data
);
if (GetDataStatus == EFI_BUFFER_TOO_SMALL) {
if (Data != NULL) {
gBS->FreePool (Data);
}
Data = AllocateZeroPool (DataSize);
GetDataStatus = mIpSecConfig->GetData (
mIpSecConfig,
DataType,
Selector,
&DataSize,
Data
);
}
ASSERT_EFI_ERROR (GetDataStatus);
if (EFI_ERROR (Routine (Selector, Data, Context))) {
break;
}
}
if (Data != NULL) {
gBS->FreePool (Data);
}
if (Selector != NULL) {
gBS->FreePool (Selector);
}
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,54 @@
/** @file
The internal structure and function declaration of the implementation
to go through each entry in IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _FOREACH_H_
#define _FOREACH_H_
/**
The prototype for the DumpSpdEntry()/DumpSadEntry()/DumpPadEntry().
Print EFI_IPSEC_CONFIG_SELECTOR and corresponding content.
@param[in] Selector The pointer to the EFI_IPSEC_CONFIG_SELECTOR union.
@param[in] Data The pointer to the corresponding data.
@param[in] Context The pointer to the Index in SPD/SAD/PAD Database.
@retval EFI_SUCCESS Dump SPD/SAD/PAD information successfully.
**/
typedef
EFI_STATUS
(*VISIT_POLICY_ENTRY) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN VOID *Context
);
/**
Enumerate all entry in the database to execute a specified operation according to datatype.
@param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE.
@param[in] Routine The pointer to function of a specified operation.
@param[in] Context The pointer to the context of a function.
@retval EFI_SUCCESS Execute specified operation successfully.
**/
EFI_STATUS
ForeachPolicyEntry (
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN VISIT_POLICY_ENTRY Routine,
IN VOID *Context
);
#endif

View File

@@ -0,0 +1,419 @@
/** @file
The assistant function implementation for IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "IpSecConfig.h"
#include "Helper.h"
/**
Helper function called to change an input parameter in the string format to a number.
@param[in] FlagStr The pointer to the flag string.
@param[in] Maximum Greatest value number.
@param[in, out] ValuePtr The pointer to the input parameter in string format.
@param[in] ByteCount The valid byte count
@param[in] Map The pointer to the STR2INT table.
@param[in] ParamPackage The pointer to the ParamPackage list.
@param[in] FormatMask The bit mask.
BIT 0 set indicates the value of a flag might be a number.
BIT 1 set indicates the value of a flag might be a string that needs to be looked up.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_FOUND The input parameter can't be found.
@retval EFI_INVALID_PARAMETER The input parameter is an invalid input.
**/
EFI_STATUS
GetNumber (
IN CHAR16 *FlagStr,
IN UINT64 Maximum,
IN OUT VOID *ValuePtr,
IN UINTN ByteCount,
IN STR2INT *Map,
IN LIST_ENTRY *ParamPackage,
IN UINT32 FormatMask
)
{
EFI_STATUS Status;
UINT64 Value64;
BOOLEAN Converted;
UINTN Index;
CONST CHAR16 *ValueStr;
ASSERT (FormatMask & (FORMAT_NUMBER | FORMAT_STRING));
Converted = FALSE;
Value64 = 0;
ValueStr = ShellCommandLineGetValue (ParamPackage, FlagStr);
if (ValueStr == NULL) {
return EFI_NOT_FOUND;
} else {
//
// Try to convert to integer directly if MaybeNumber is TRUE.
//
if ((FormatMask & FORMAT_NUMBER) != 0) {
Value64 = StrToUInteger (ValueStr, &Status);
if (!EFI_ERROR (Status)) {
//
// Convert successfully.
//
if (Value64 > Maximum) {
//
// But the result is invalid
//
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
mHiiHandle,
mAppName,
FlagStr,
ValueStr
);
return EFI_INVALID_PARAMETER;
}
Converted = TRUE;
}
}
if (!Converted && ((FormatMask & FORMAT_STRING) != 0)) {
//
// Convert falied, so use String->Integer map.
//
Value64 = MapStringToInteger (ValueStr, Map);
if (Value64 == (UINT32) -1) {
//
// Cannot find the string in the map.
//
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
mHiiHandle,
mAppName,
FlagStr,
ValueStr
);
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ACCEPT_PARAMETERS), mHiiHandle);
for (Index = 0; Map[Index].String != NULL; Index++) {
Print (L" %s", Map[Index].String);
}
Print (L"\n");
return EFI_INVALID_PARAMETER;
}
}
CopyMem (ValuePtr, &Value64, ByteCount);
return EFI_SUCCESS;
}
}
/**
Helper function called to convert a string containing an Ipv4 or Ipv6 Internet Protocol address
into a proper address for the EFI_IP_ADDRESS structure.
@param[in] Ptr The pointer to the string containing an Ipv4 or Ipv6 Internet Protocol address.
@param[out] Ip The pointer to the EFI_IP_ADDRESS structure to contain the result.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
**/
EFI_STATUS
EfiInetAddr2 (
IN CHAR16 *Ptr,
OUT EFI_IP_ADDRESS *Ip
)
{
EFI_STATUS Status;
if ((Ptr == NULL) || (Ip == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Parse the input address as Ipv4 Address first.
//
Status = NetLibStrToIp4 (Ptr, &Ip->v4);
if (!EFI_ERROR (Status)) {
return Status;
}
Status = NetLibStrToIp6 (Ptr, &Ip->v6);
return Status;
}
/**
Helper function called to calculate the prefix length associated with the string
containing an Ipv4 or Ipv6 Internet Protocol address.
@param[in] Ptr The pointer to the string containing an Ipv4 or Ipv6 Internet Protocol address.
@param[out] Addr The pointer to the EFI_IP_ADDRESS_INFO structure to contain the result.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval Others Other mistake case.
**/
EFI_STATUS
EfiInetAddrRange (
IN CHAR16 *Ptr,
OUT EFI_IP_ADDRESS_INFO *Addr
)
{
EFI_STATUS Status;
if ((Ptr == NULL) || (Addr == NULL)) {
return EFI_INVALID_PARAMETER;
}
Status = NetLibStrToIp4 (Ptr, &Addr->Address.v4);
if (!EFI_ERROR (Status)) {
if ((UINT32)(*Addr->Address.v4.Addr) == 0) {
Addr->PrefixLength = 0;
} else {
Addr->PrefixLength = 32;
}
return Status;
}
Status = NetLibStrToIp6andPrefix (Ptr, &Addr->Address.v6, &Addr->PrefixLength);
if (!EFI_ERROR (Status) && (Addr->PrefixLength == 0xFF)) {
Addr->PrefixLength = 128;
}
return Status;
}
/**
Helper function called to calculate the port range associated with the string.
@param[in] Ptr The pointer to the string containing a port and range.
@param[out] Port The pointer to the Port to contain the result.
@param[out] PortRange The pointer to the PortRange to contain the result.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval Others Other mistake case.
**/
EFI_STATUS
EfiInetPortRange (
IN CHAR16 *Ptr,
OUT UINT16 *Port,
OUT UINT16 *PortRange
)
{
CHAR16 *BreakPtr;
CHAR16 Ch;
EFI_STATUS Status;
for (BreakPtr = Ptr; (*BreakPtr != L'\0') && (*BreakPtr != L':'); BreakPtr++) {
;
}
Ch = *BreakPtr;
*BreakPtr = L'\0';
*Port = (UINT16) StrToUInteger (Ptr, &Status);
*BreakPtr = Ch;
if (EFI_ERROR (Status)) {
return Status;
}
*PortRange = 0;
if (*BreakPtr == L':') {
BreakPtr++;
*PortRange = (UINT16) StrToUInteger (BreakPtr, &Status);
if (EFI_ERROR (Status)) {
return Status;
}
if (*PortRange < *Port) {
return EFI_INVALID_PARAMETER;
}
*PortRange = (UINT16) (*PortRange - *Port);
}
return EFI_SUCCESS;
}
/**
Helper function called to transfer a string to an unsigned integer.
@param[in] Str The pointer to the string.
@param[out] Status The operation status.
@return The integer value of converted Str.
**/
UINT64
StrToUInteger (
IN CONST CHAR16 *Str,
OUT EFI_STATUS *Status
)
{
UINT64 Value;
UINT64 NewValue;
CHAR16 *StrTail;
CHAR16 Char;
UINTN Base;
UINTN Len;
Base = 10;
Value = 0;
*Status = EFI_ABORTED;
//
// Skip leading white space.
//
while ((*Str != 0) && (*Str == ' ')) {
Str++;
}
//
// For NULL Str, just return.
//
if (*Str == 0) {
return 0;
}
//
// Skip white space in tail.
//
Len = StrLen (Str);
StrTail = (CHAR16 *) (Str + Len - 1);
while (*StrTail == ' ') {
*StrTail = 0;
StrTail--;
}
Len = StrTail - Str + 1;
//
// Check hex prefix '0x'.
//
if ((Len >= 2) && (*Str == '0') && ((*(Str + 1) == 'x') || (*(Str + 1) == 'X'))) {
Str += 2;
Len -= 2;
Base = 16;
}
if (Len == 0) {
return 0;
}
//
// Convert the string to value.
//
for (; Str <= StrTail; Str++) {
Char = *Str;
if (Base == 16) {
if (RShiftU64 (Value, 60) != 0) {
//
// Overflow here x16.
//
return 0;
}
NewValue = LShiftU64 (Value, 4);
} else {
if (RShiftU64 (Value, 61) != 0) {
//
// Overflow here x8.
//
return 0;
}
NewValue = LShiftU64 (Value, 3);
Value = LShiftU64 (Value, 1);
NewValue += Value;
if (NewValue < Value) {
//
// Overflow here.
//
return 0;
}
}
Value = NewValue;
if ((Base == 16) && (Char >= 'a') && (Char <= 'f')) {
Char = (CHAR16) (Char - 'a' + 'A');
}
if ((Base == 16) && (Char >= 'A') && (Char <= 'F')) {
Value += (Char - 'A') + 10;
} else if ((Char >= '0') && (Char <= '9')) {
Value += (Char - '0');
} else {
//
// Unexpected Char encountered.
//
return 0;
}
}
*Status = EFI_SUCCESS;
return Value;
}
/**
Helper function called to transfer a string to an unsigned integer according to the map table.
@param[in] Str The pointer to the string.
@param[in] Map The pointer to the map table.
@return The integer value of converted Str. If not found, then return -1.
**/
UINT32
MapStringToInteger (
IN CONST CHAR16 *Str,
IN STR2INT *Map
)
{
STR2INT *Item;
for (Item = Map; Item->String != NULL; Item++) {
if (StrCmp (Item->String, Str) == 0) {
return Item->Integer;
}
}
return (UINT32) -1;
}
/**
Helper function called to transfer an unsigned integer to a string according to the map table.
@param[in] Integer The pointer to the string.
@param[in] Map The pointer to the map table.
@return The converted Str. If not found, then return NULL.
**/
CHAR16 *
MapIntegerToString (
IN UINT32 Integer,
IN STR2INT *Map
)
{
STR2INT *Item;
for (Item = Map; Item->String != NULL; Item++) {
if (Integer == Item->Integer) {
return Item->String;
}
}
return NULL;
}

View File

@@ -0,0 +1,143 @@
/** @file
The assistant function declaration for IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _HELPER_H_
#define _HELPER_H_
#define FORMAT_NUMBER 0x1
#define FORMAT_STRING 0x2
/**
Helper function called to change input parameter in string format to number.
@param[in] FlagStr The pointer to the flag string.
@param[in] Maximum most value number.
@param[in, out] ValuePtr The pointer to the input parameter in string format.
@param[in] ByteCount The valid byte count
@param[in] Map The pointer to the STR2INT table.
@param[in] ParamPackage The pointer to the ParamPackage list.
@param[in] FormatMask The bit mask.
BIT 0 set indicates the value of flag might be number.
BIT 1 set indicates the value of flag might be a string that needs to be looked up.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_FOUND The input parameter can't be found.
@retval EFI_INVALID_PARAMETER The input parameter is an invalid input.
**/
EFI_STATUS
GetNumber (
IN CHAR16 *FlagStr,
IN UINT64 Maximum,
IN OUT VOID *ValuePtr,
IN UINTN ByteCount,
IN STR2INT *Map,
IN LIST_ENTRY *ParamPackage,
IN UINT32 FormatMask
);
/**
Helper function called to convert a string containing an (Ipv4) Internet Protocol dotted address
into a proper address for the EFI_IP_ADDRESS structure.
@param[in] Ptr The pointer to the string containing an (Ipv4) Internet Protocol dotted address.
@param[out] Ip The pointer to the Ip address structure to contain the result.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
**/
EFI_STATUS
EfiInetAddr2 (
IN CHAR16 *Ptr,
OUT EFI_IP_ADDRESS *Ip
);
/**
Helper function called to calculate the prefix length associated with the string
containing an Ipv4 or Ipv6 Internet Protocol address.
@param[in] Ptr The pointer to the string containing an Ipv4 or Ipv6 Internet Protocol address.
@param[out] Addr The pointer to the EFI_IP_ADDRESS_INFO structure to contain the result.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval Others Other mistake case.
**/
EFI_STATUS
EfiInetAddrRange (
IN CHAR16 *Ptr,
OUT EFI_IP_ADDRESS_INFO *Addr
);
/**
Helper function called to calculate the port range associated with the string.
@param[in] Ptr The pointer to the string containing a port and range.
@param[out] Port The pointer to the Port to contain the result.
@param[out] PortRange The pointer to the PortRange to contain the result.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval Others Other mistake case.
**/
EFI_STATUS
EfiInetPortRange (
IN CHAR16 *Ptr,
OUT UINT16 *Port,
OUT UINT16 *PortRange
);
/**
Helper function called to transfer a string to an unsigned integer.
@param[in] Str The pointer to the string.
@param[out] Status The operation status.
@return The integer value of a converted str.
**/
UINT64
StrToUInteger (
IN CONST CHAR16 *Str,
OUT EFI_STATUS *Status
);
/**
Helper function called to transfer a string to an unsigned integer according to the map table.
@param[in] Str The pointer to the string.
@param[in] Map The pointer to the map table.
@return The integer value of converted str. If not found, then return -1.
**/
UINT32
MapStringToInteger (
IN CONST CHAR16 *Str,
IN STR2INT *Map
);
/**
Helper function called to transfer an unsigned integer to a string according to the map table.
@param[in] Integer The pointer to the string.
@param[in] Map The pointer to the map table.
@return The converted str. If not found, then return NULL.
**/
CHAR16 *
MapIntegerToString (
IN UINT32 Integer,
IN STR2INT *Map
);
#endif

View File

@@ -0,0 +1,248 @@
/** @file
The implementation of construct ENTRY_INDEXER in IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "IpSecConfig.h"
#include "Indexer.h"
#include "Helper.h"
/**
Fill in SPD_ENTRY_INDEXER through ParamPackage list.
@param[in, out] Indexer The pointer to the SPD_ENTRY_INDEXER structure.
@param[in] ParamPackage The pointer to the ParamPackage list.
@retval EFI_SUCCESS Filled in SPD_ENTRY_INDEXER successfully.
**/
EFI_STATUS
ConstructSpdIndexer (
IN OUT SPD_ENTRY_INDEXER *Indexer,
IN LIST_ENTRY *ParamPackage
)
{
EFI_STATUS Status;
UINT64 Value64;
CONST CHAR16 *ValueStr;
ValueStr = NULL;
if (ShellCommandLineGetFlag (ParamPackage, L"-i")) {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-i");
} else if (ShellCommandLineGetFlag (ParamPackage, L"-d")) {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-d");
} else if (ShellCommandLineGetFlag (ParamPackage, L"-e")) {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-e");
} else {
ASSERT (FALSE);
}
ASSERT (ValueStr != NULL);
Value64 = StrToUInteger (ValueStr, &Status);
if (!EFI_ERROR (Status)) {
Indexer->Index = (UINTN) Value64;
Indexer->Name = NULL;
} else {
UnicodeStrToAsciiStr (ValueStr, (CHAR8 *) Indexer->Name);
}
return EFI_SUCCESS;
}
/**
Fill in SAD_ENTRY_INDEXER through ParamPackage list.
@param[in, out] Indexer The pointer to the SAD_ENTRY_INDEXER structure.
@param[in] ParamPackage The pointer to the ParamPackage list.
@retval EFI_SUCCESS Filled in SPD_ENTRY_INDEXER successfully.
@retval EFI_INVALID_PARAMETER The mistaken user input in ParamPackage list.
**/
EFI_STATUS
ConstructSadIndexer (
IN OUT SAD_ENTRY_INDEXER *Indexer,
IN LIST_ENTRY *ParamPackage
)
{
EFI_STATUS Status;
EFI_STATUS Status1;
UINT64 Value64;
CONST CHAR16 *ValueStr;
ValueStr = NULL;
if (ShellCommandLineGetFlag (ParamPackage, L"-i")) {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-i");
} else if (ShellCommandLineGetFlag (ParamPackage, L"-d")) {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-d");
} else if (ShellCommandLineGetFlag (ParamPackage, L"-e")) {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-e");
} else {
ASSERT (FALSE);
}
ASSERT (ValueStr != NULL);
Value64 = StrToUInteger (ValueStr, &Status);
if (!EFI_ERROR (Status)) {
Indexer->Index = (UINTN) Value64;
ZeroMem (&Indexer->SaId, sizeof (EFI_IPSEC_SA_ID));
} else {
if ((!ShellCommandLineGetFlag (ParamPackage, L"--lookup-spi")) ||
(!ShellCommandLineGetFlag (ParamPackage, L"--lookup-ipsec-proto")) ||
(!ShellCommandLineGetFlag (ParamPackage, L"--lookup-dest"))) {
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
mHiiHandle,
mAppName,
L"--lookup-spi --lookup-ipsec-proto --lookup-dest"
);
return EFI_INVALID_PARAMETER;
}
Status = GetNumber (
L"--lookup-spi",
(UINT32) -1,
&Indexer->SaId.Spi,
sizeof (UINT32),
NULL,
ParamPackage,
FORMAT_NUMBER
);
Status1 = GetNumber (
L"--lookup-ipsec-proto",
0,
&Indexer->SaId.Proto,
sizeof (EFI_IPSEC_PROTOCOL_TYPE),
mMapIpSecProtocol,
ParamPackage,
FORMAT_STRING
);
if (EFI_ERROR (Status) || EFI_ERROR (Status1)) {
return EFI_INVALID_PARAMETER;
}
ValueStr = ShellCommandLineGetValue (ParamPackage, L"--lookup-dest");
ASSERT (ValueStr != NULL);
Status = EfiInetAddr2 ((CHAR16 *) ValueStr, &Indexer->SaId.DestAddress);
if (EFI_ERROR (Status)) {
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
mHiiHandle,
mAppName,
L"--lookup-dest",
ValueStr
);
return EFI_INVALID_PARAMETER;
}
}
return EFI_SUCCESS;
}
/**
Fill in PAD_ENTRY_INDEXER through ParamPackage list.
@param[in, out] Indexer The pointer to the PAD_ENTRY_INDEXER structure.
@param[in] ParamPackage The pointer to the ParamPackage list.
@retval EFI_SUCCESS Filled in PAD_ENTRY_INDEXER successfully.
@retval EFI_INVALID_PARAMETER The mistaken user input in ParamPackage list.
**/
EFI_STATUS
ConstructPadIndexer (
IN OUT PAD_ENTRY_INDEXER *Indexer,
IN LIST_ENTRY *ParamPackage
)
{
EFI_STATUS Status;
UINT64 Value64;
CONST CHAR16 *ValueStr;
ValueStr = NULL;
if (ShellCommandLineGetFlag (ParamPackage, L"-i")) {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-i");
} else if (ShellCommandLineGetFlag (ParamPackage, L"-d")) {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-d");
} else if (ShellCommandLineGetFlag (ParamPackage, L"-e")) {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-e");
} else {
ASSERT (FALSE);
}
ASSERT (ValueStr != NULL);
Value64 = StrToUInteger (ValueStr, &Status);
if (!EFI_ERROR (Status)) {
Indexer->Index = (UINTN) Value64;
ZeroMem (&Indexer->PadId, sizeof (EFI_IPSEC_PAD_ID));
} else {
if (ShellCommandLineGetFlag (ParamPackage, L"--lookup-peer-address")) {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"--lookup-peer-address");
ASSERT (ValueStr != NULL);
Indexer->PadId.PeerIdValid = FALSE;
Status = EfiInetAddrRange ((CHAR16 *) ValueStr, &Indexer->PadId.Id.IpAddress);
if (EFI_ERROR (Status)) {
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
mHiiHandle,
mAppName,
L"--lookup-peer-address",
ValueStr
);
return EFI_INVALID_PARAMETER;
}
} else {
ValueStr = ShellCommandLineGetValue (ParamPackage, L"--lookup-peer-id");
if (ValueStr == NULL) {
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
mHiiHandle,
mAppName,
L"--lookup-peer-address --lookup-peer-id"
);
return EFI_INVALID_PARAMETER;
}
Indexer->PadId.PeerIdValid = TRUE;
StrnCpy ((CHAR16 *) Indexer->PadId.Id.PeerId, ValueStr, ARRAY_SIZE (Indexer->PadId.Id.PeerId) - 1);
}
}
return EFI_SUCCESS;
}
CONSTRUCT_POLICY_ENTRY_INDEXER mConstructPolicyEntryIndexer[] = {
(CONSTRUCT_POLICY_ENTRY_INDEXER) ConstructSpdIndexer,
(CONSTRUCT_POLICY_ENTRY_INDEXER) ConstructSadIndexer,
(CONSTRUCT_POLICY_ENTRY_INDEXER) ConstructPadIndexer
};

View File

@@ -0,0 +1,58 @@
/** @file
The internal structure and function declaration to construct ENTRY_INDEXER in
IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _INDEXER_H_
#define _INDEXER_H_
typedef struct {
UINT8 *Name;
UINTN Index; // Used only if Name is NULL.
} SPD_ENTRY_INDEXER;
typedef struct {
EFI_IPSEC_SA_ID SaId;
UINTN Index;
} SAD_ENTRY_INDEXER;
typedef struct {
EFI_IPSEC_PAD_ID PadId;
UINTN Index;
} PAD_ENTRY_INDEXER;
typedef union {
SPD_ENTRY_INDEXER Spd;
SAD_ENTRY_INDEXER Sad;
PAD_ENTRY_INDEXER Pad;
} POLICY_ENTRY_INDEXER;
/**
The prototype for the ConstructSpdIndexer()/ConstructSadIndexer()/ConstructPadIndexer().
Fill in SPD_ENTRY_INDEXER/SAD_ENTRY_INDEXER/PAD_ENTRY_INDEXER through ParamPackage list.
@param[in, out] Indexer The pointer to the POLICY_ENTRY_INDEXER union.
@param[in] ParamPackage The pointer to the ParamPackage list.
@retval EFI_SUCCESS Filled in POLICY_ENTRY_INDEXER successfully.
**/
typedef
EFI_STATUS
(* CONSTRUCT_POLICY_ENTRY_INDEXER) (
IN POLICY_ENTRY_INDEXER *Indexer,
IN LIST_ENTRY *ParamPackage
);
extern CONSTRUCT_POLICY_ENTRY_INDEXER mConstructPolicyEntryIndexer[];
#endif

View File

@@ -0,0 +1,809 @@
/** @file
The main process for IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/HiiLib.h>
#include <Protocol/IpSec.h>
#include "IpSecConfig.h"
#include "Dump.h"
#include "Indexer.h"
#include "PolicyEntryOperation.h"
#include "Delete.h"
#include "Helper.h"
//
// Used for ShellCommandLineParseEx only
// and to ensure user inputs are in valid format
//
SHELL_PARAM_ITEM mIpSecConfigParamList[] = {
{ L"-p", TypeValue },
{ L"-a", TypeValue },
{ L"-i", TypeValue },
{ L"-e", TypeValue },
{ L"-d", TypeValue },
{ L"-f", TypeFlag },
{ L"-l", TypeFlag },
{ L"-enable", TypeFlag },
{ L"-disable", TypeFlag },
{ L"-status", TypeFlag },
{ L"-?", TypeFlag },
//
// SPD Selector
//
{ L"--local", TypeValue },
{ L"--remote", TypeValue },
{ L"--proto", TypeValue },
{ L"--local-port", TypeValue },
{ L"--remote-port", TypeValue },
{ L"--icmp-type", TypeValue },
{ L"--icmp-code", TypeValue },
//
// SPD Data
//
{ L"--name", TypeValue },
{ L"--packet-flag", TypeValue },
{ L"--action", TypeValue },
{ L"--lifebyte", TypeValue },
{ L"--lifetime-soft", TypeValue },
{ L"--lifetime", TypeValue },
{ L"--mode", TypeValue },
{ L"--tunnel-local", TypeValue },
{ L"--tunnel-remote", TypeValue },
{ L"--dont-fragment", TypeValue },
{ L"--ipsec-proto", TypeValue },
{ L"--auth-algo", TypeValue },
{ L"--encrypt-algo", TypeValue },
{ L"--ext-sequence", TypeFlag },
{ L"--sequence-overflow", TypeFlag },
{ L"--fragment-check", TypeFlag },
{ L"--ext-sequence-", TypeFlag },
{ L"--sequence-overflow-", TypeFlag },
{ L"--fragment-check-", TypeFlag },
//
// SA ID
// --ipsec-proto
//
{ L"--spi", TypeValue },
{ L"--dest", TypeValue },
{ L"--lookup-spi", TypeValue },
{ L"--lookup-ipsec-proto", TypeValue },
{ L"--lookup-dest", TypeValue },
//
// SA DATA
// --mode
// --auth-algo
// --encrypt-algo
//
{ L"--sequence-number", TypeValue },
{ L"--antireplay-window", TypeValue },
{ L"--auth-key", TypeValue },
{ L"--encrypt-key", TypeValue },
{ L"--path-mtu", TypeValue },
//
// PAD ID
//
{ L"--peer-id", TypeValue },
{ L"--peer-address", TypeValue },
{ L"--auth-proto", TypeValue },
{ L"--auth-method", TypeValue },
{ L"--ike-id", TypeValue },
{ L"--ike-id-", TypeValue },
{ L"--auth-data", TypeValue },
{ L"--revocation-data", TypeValue },
{ L"--lookup-peer-id", TypeValue },
{ L"--lookup-peer-address", TypeValue },
{ NULL, TypeMax },
};
//
// -P
//
STR2INT mMapPolicy[] = {
{ L"SPD", IPsecConfigDataTypeSpd },
{ L"SAD", IPsecConfigDataTypeSad },
{ L"PAD", IPsecConfigDataTypePad },
{ NULL, 0 },
};
//
// --proto
//
STR2INT mMapIpProtocol[] = {
{ L"TCP", EFI_IP4_PROTO_TCP },
{ L"UDP", EFI_IP4_PROTO_UDP },
{ L"ICMP", EFI_IP4_PROTO_ICMP },
{ NULL, 0 },
};
//
// --action
//
STR2INT mMapIpSecAction[] = {
{ L"Bypass", EfiIPsecActionBypass },
{ L"Discard", EfiIPsecActionDiscard },
{ L"Protect", EfiIPsecActionProtect },
{ NULL, 0 },
};
//
// --mode
//
STR2INT mMapIpSecMode[] = {
{ L"Transport", EfiIPsecTransport },
{ L"Tunnel", EfiIPsecTunnel },
{ NULL, 0 },
};
//
// --dont-fragment
//
STR2INT mMapDfOption[] = {
{ L"clear", EfiIPsecTunnelClearDf },
{ L"set", EfiIPsecTunnelSetDf },
{ L"copy", EfiIPsecTunnelCopyDf },
{ NULL, 0 },
};
//
// --ipsec-proto
//
STR2INT mMapIpSecProtocol[] = {
{ L"AH", EfiIPsecAH },
{ L"ESP", EfiIPsecESP },
{ NULL, 0 },
};
//
// --auth-algo
//
STR2INT mMapAuthAlgo[] = {
{ L"NONE", EFI_IPSEC_AALG_NONE },
{ L"MD5HMAC", EFI_IPSEC_AALG_MD5HMAC },
{ L"SHA1HMAC", EFI_IPSEC_AALG_SHA1HMAC },
{ L"SHA2-256HMAC", EFI_IPSEC_AALG_SHA2_256HMAC },
{ L"SHA2-384HMAC", EFI_IPSEC_AALG_SHA2_384HMAC },
{ L"SHA2-512HMAC", EFI_IPSEC_AALG_SHA2_512HMAC },
{ L"AES-XCBC-MAC", EFI_IPSEC_AALG_AES_XCBC_MAC },
{ L"NULL", EFI_IPSEC_AALG_NULL },
{ NULL, 0 },
};
//
// --encrypt-algo
//
STR2INT mMapEncAlgo[] = {
{ L"NONE", EFI_IPSEC_EALG_NONE },
{ L"DESCBC", EFI_IPSEC_EALG_DESCBC },
{ L"3DESCBC", EFI_IPSEC_EALG_3DESCBC },
{ L"CASTCBC", EFI_IPSEC_EALG_CASTCBC },
{ L"BLOWFISHCBC", EFI_IPSEC_EALG_BLOWFISHCBC },
{ L"NULL", EFI_IPSEC_EALG_NULL },
{ L"AESCBC", EFI_IPSEC_EALG_AESCBC },
{ L"AESCTR", EFI_IPSEC_EALG_AESCTR },
{ L"AES-CCM-ICV8", EFI_IPSEC_EALG_AES_CCM_ICV8 },
{ L"AES-CCM-ICV12",EFI_IPSEC_EALG_AES_CCM_ICV12 },
{ L"AES-CCM-ICV16",EFI_IPSEC_EALG_AES_CCM_ICV16 },
{ L"AES-GCM-ICV8", EFI_IPSEC_EALG_AES_GCM_ICV8 },
{ L"AES-GCM-ICV12",EFI_IPSEC_EALG_AES_GCM_ICV12 },
{ L"AES-GCM-ICV16",EFI_IPSEC_EALG_AES_GCM_ICV16 },
{ NULL, 0 },
};
//
// --auth-proto
//
STR2INT mMapAuthProto[] = {
{ L"IKEv1", EfiIPsecAuthProtocolIKEv1 },
{ L"IKEv2", EfiIPsecAuthProtocolIKEv2 },
{ NULL, 0 },
};
//
// --auth-method
//
STR2INT mMapAuthMethod[] = {
{ L"PreSharedSecret", EfiIPsecAuthMethodPreSharedSecret },
{ L"Certificates", EfiIPsecAuthMethodCertificates },
{ NULL, 0 },
};
EFI_IPSEC_PROTOCOL *mIpSec;
EFI_IPSEC_CONFIG_PROTOCOL *mIpSecConfig;
EFI_HII_HANDLE mHiiHandle;
EFI_GUID mEfiIpSecConfigGuid = EFI_IPSEC_CONFIG_GUID;
CHAR16 mAppName[] = L"IpSecConfig";
//
// Used for IpSecConfigRetriveCheckListByName only to check the validation of user input
//
VAR_CHECK_ITEM mIpSecConfigVarCheckList[] = {
{ L"-enable", BIT(1)|BIT(0), BIT(1), BIT(2)|BIT(1)|BIT(0), 0 },
{ L"-disable", BIT(1)|BIT(0), BIT(1), BIT(2)|BIT(1)|BIT(0), 0 },
{ L"-status", BIT(1)|BIT(0), BIT(1), BIT(2)|BIT(1)|BIT(0), 0 },
{ L"-p", BIT(1), 0, BIT(2)|BIT(1)|BIT(0), 0 },
{ L"-a", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 },
{ L"-i", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 },
{ L"-d", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 },
{ L"-e", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 },
{ L"-l", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 },
{ L"-f", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 },
{ L"-?", BIT(0), BIT(0), BIT(2)|BIT(1)|BIT(0), 0 },
//
// SPD Selector
//
{ L"--local", 0, 0, BIT(2)|BIT(1), 0 },
{ L"--remote", 0, 0, BIT(2)|BIT(1), 0 },
{ L"--proto", 0, 0, BIT(2)|BIT(1), 0 },
{ L"--local-port", 0, 0, BIT(2)|BIT(1), BIT(0) },
{ L"--remote-port", 0, 0, BIT(2)|BIT(1), BIT(0) },
{ L"--icmp-type", 0, 0, BIT(2)|BIT(1), BIT(1) },
{ L"--icmp-code", 0, 0, BIT(2)|BIT(1), BIT(1) },
//
// SPD Data
//
{ L"--name", 0, 0, BIT(2), 0 },
{ L"--packet-flag", 0, 0, BIT(2), 0 },
{ L"--action", 0, 0, BIT(2)|BIT(1), 0 },
{ L"--lifebyte", 0, 0, BIT(2)|BIT(1), 0 },
{ L"--lifetime-soft", 0, 0, BIT(2)|BIT(1), 0 },
{ L"--lifetime", 0, 0, BIT(2)|BIT(1), 0 },
{ L"--mode", 0, 0, BIT(2)|BIT(1), 0 },
{ L"--tunnel-local", 0, 0, BIT(2), 0 },
{ L"--tunnel-remote", 0, 0, BIT(2), 0 },
{ L"--dont-fragment", 0, 0, BIT(2), 0 },
{ L"--ipsec-proto", 0, 0, BIT(2)|BIT(1), 0 },
{ L"--auth-algo", 0, 0, BIT(2)|BIT(1), 0 },
{ L"--encrypt-algo", 0, 0, BIT(2)|BIT(1), 0 },
{ L"--ext-sequence", 0, 0, BIT(2), BIT(2) },
{ L"--sequence-overflow", 0, 0, BIT(2), BIT(2) },
{ L"--fragment-check", 0, 0, BIT(2), BIT(2) },
{ L"--ext-sequence-", 0, 0, BIT(2), BIT(3) },
{ L"--sequence-overflow-", 0, 0, BIT(2), BIT(3) },
{ L"--fragment-check-", 0, 0, BIT(2), BIT(3) },
//
// SA ID
// --ipsec-proto
//
{ L"--spi", 0, 0, BIT(1), 0 },
{ L"--dest", 0, 0, BIT(1), 0 },
{ L"--lookup-spi", 0, 0, BIT(1), 0 },
{ L"--lookup-ipsec-proto", 0, 0, BIT(1), 0 },
{ L"--lookup-dest", 0, 0, BIT(1), 0 },
//
// SA DATA
// --mode
// --auth-algo
// --encrypt-algo
//
{ L"--sequence-number", 0, 0, BIT(1), 0 },
{ L"--antireplay-window", 0, 0, BIT(1), 0 },
{ L"--auth-key", 0, 0, BIT(1), 0 },
{ L"--encrypt-key", 0, 0, BIT(1), 0 },
{ L"--path-mtu", 0, 0, BIT(1), 0 },
//
// The example to add a PAD:
// "-A --peer-id Mike [--peer-address 10.23.2.2] --auth-proto IKE1/IKE2
// --auth-method PreSharedSeceret/Certificate --ike-id
// --auth-data 343343 --revocation-data 2342432"
// The example to delete a PAD:
// "-D * --lookup-peer-id Mike [--lookup-peer-address 10.23.2.2]"
// "-D 1"
// The example to edit a PAD:
// "-E * --lookup-peer-id Mike --auth-method Certificate"
//
// PAD ID
//
{ L"--peer-id", 0, 0, BIT(0), BIT(4) },
{ L"--peer-address", 0, 0, BIT(0), BIT(5) },
{ L"--auth-proto", 0, 0, BIT(0), 0 },
{ L"--auth-method", 0, 0, BIT(0), 0 },
{ L"--IKE-ID", 0, 0, BIT(0), BIT(6) },
{ L"--IKE-ID-", 0, 0, BIT(0), BIT(7) },
{ L"--auth-data", 0, 0, BIT(0), 0 },
{ L"--revocation-data", 0, 0, BIT(0), 0 },
{ L"--lookup-peer-id", 0, 0, BIT(0), BIT(4) },
{ L"--lookup-peer-address",0, 0, BIT(0), BIT(5) },
{ NULL, 0, 0, 0, 0 },
};
/**
The function to allocate the proper sized buffer for various
EFI interfaces.
@param[in, out] Status Current status.
@param[in, out] Buffer Current allocated buffer, or NULL.
@param[in] BufferSize Current buffer size needed
@retval TRUE If the buffer was reallocated and the caller should try the API again.
@retval FALSE If the buffer was not reallocated successfully.
**/
BOOLEAN
GrowBuffer (
IN OUT EFI_STATUS *Status,
IN OUT VOID **Buffer,
IN UINTN BufferSize
)
{
BOOLEAN TryAgain;
ASSERT (Status != NULL);
ASSERT (Buffer != NULL);
//
// If this is an initial request, buffer will be null with a new buffer size.
//
if ((NULL == *Buffer) && (BufferSize != 0)) {
*Status = EFI_BUFFER_TOO_SMALL;
}
//
// If the status code is "buffer too small", resize the buffer.
//
TryAgain = FALSE;
if (*Status == EFI_BUFFER_TOO_SMALL) {
if (*Buffer != NULL) {
FreePool (*Buffer);
}
*Buffer = AllocateZeroPool (BufferSize);
if (*Buffer != NULL) {
TryAgain = TRUE;
} else {
*Status = EFI_OUT_OF_RESOURCES;
}
}
//
// If there's an error, free the buffer.
//
if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {
FreePool (*Buffer);
*Buffer = NULL;
}
return TryAgain;
}
/**
Function returns an array of handles that support the requested protocol
in a buffer allocated from a pool.
@param[in] SearchType Specifies which handle(s) are to be returned.
@param[in] Protocol Provides the protocol to search by.
This parameter is only valid for SearchType ByProtocol.
@param[in] SearchKey Supplies the search key depending on the SearchType.
@param[in, out] NoHandles The number of handles returned in Buffer.
@param[out] Buffer A pointer to the buffer to return the requested array of
handles that support Protocol.
@retval EFI_SUCCESS The resulting array of handles was returned.
@retval Others Other mistake case.
**/
EFI_STATUS
LocateHandle (
IN EFI_LOCATE_SEARCH_TYPE SearchType,
IN EFI_GUID *Protocol OPTIONAL,
IN VOID *SearchKey OPTIONAL,
IN OUT UINTN *NoHandles,
OUT EFI_HANDLE **Buffer
)
{
EFI_STATUS Status;
UINTN BufferSize;
ASSERT (NoHandles != NULL);
ASSERT (Buffer != NULL);
//
// Initialize for GrowBuffer loop.
//
Status = EFI_SUCCESS;
*Buffer = NULL;
BufferSize = 50 * sizeof (EFI_HANDLE);
//
// Call the real function.
//
while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) {
Status = gBS->LocateHandle (
SearchType,
Protocol,
SearchKey,
&BufferSize,
*Buffer
);
}
*NoHandles = BufferSize / sizeof (EFI_HANDLE);
if (EFI_ERROR (Status)) {
*NoHandles = 0;
}
return Status;
}
/**
Find the first instance of this protocol in the system and return its interface.
@param[in] ProtocolGuid The guid of the protocol.
@param[out] Interface The pointer to the first instance of the protocol.
@retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found.
@retval Others A protocol instance matching ProtocolGuid was not found.
**/
EFI_STATUS
LocateProtocol (
IN EFI_GUID *ProtocolGuid,
OUT VOID **Interface
)
{
EFI_STATUS Status;
UINTN NumberHandles;
UINTN Index;
EFI_HANDLE *Handles;
*Interface = NULL;
Handles = NULL;
NumberHandles = 0;
Status = LocateHandle (ByProtocol, ProtocolGuid, NULL, &NumberHandles, &Handles);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_INFO, "LibLocateProtocol: Handle not found\n"));
return Status;
}
for (Index = 0; Index < NumberHandles; Index++) {
ASSERT (Handles != NULL);
Status = gBS->HandleProtocol (
Handles[Index],
ProtocolGuid,
Interface
);
if (!EFI_ERROR (Status)) {
break;
}
}
if (Handles != NULL) {
FreePool (Handles);
}
return Status;
}
/**
Helper function called to check the conflicted flags.
@param[in] CheckList The pointer to the VAR_CHECK_ITEM table.
@param[in] ParamPackage The pointer to the ParamPackage list.
@retval EFI_SUCCESS No conflicted flags.
@retval EFI_INVALID_PARAMETER The input parameter is erroroneous or there are some conflicted flags.
**/
EFI_STATUS
IpSecConfigRetriveCheckListByName (
IN VAR_CHECK_ITEM *CheckList,
IN LIST_ENTRY *ParamPackage
)
{
LIST_ENTRY *Node;
VAR_CHECK_ITEM *Item;
UINT32 Attribute1;
UINT32 Attribute2;
UINT32 Attribute3;
UINT32 Attribute4;
UINT32 Index;
Attribute1 = 0;
Attribute2 = 0;
Attribute3 = 0;
Attribute4 = 0;
Index = 0;
Item = mIpSecConfigVarCheckList;
if ((ParamPackage == NULL) || (CheckList == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Enumerate through the list of parameters that are input by user.
//
for (Node = GetFirstNode (ParamPackage); !IsNull (ParamPackage, Node); Node = GetNextNode (ParamPackage, Node)) {
if (((SHELL_PARAM_PACKAGE *) Node)->Name != NULL) {
//
// Enumerate the check list that defines the conflicted attributes of each flag.
//
for (; Item->VarName != NULL; Item++) {
if (StrCmp (((SHELL_PARAM_PACKAGE *) Node)->Name, Item->VarName) == 0) {
Index++;
if (Index == 1) {
Attribute1 = Item->Attribute1;
Attribute2 = Item->Attribute2;
Attribute3 = Item->Attribute3;
Attribute4 = Item->Attribute4;
} else {
Attribute1 &= Item->Attribute1;
Attribute2 |= Item->Attribute2;
Attribute3 &= Item->Attribute3;
Attribute4 |= Item->Attribute4;
if (Attribute1 != 0) {
return EFI_INVALID_PARAMETER;
}
if (Attribute2 != 0) {
if ((Index == 2) && (StrCmp (Item->VarName, L"-p") == 0)) {
continue;
}
return EFI_INVALID_PARAMETER;
}
if (Attribute3 == 0) {
return EFI_INVALID_PARAMETER;
}
if (((Attribute4 & 0xFF) == 0x03) || ((Attribute4 & 0xFF) == 0x0C) ||
((Attribute4 & 0xFF) == 0x30) || ((Attribute4 & 0xFF) == 0xC0)) {
return EFI_INVALID_PARAMETER;
}
}
break;
}
}
Item = mIpSecConfigVarCheckList;
}
}
return EFI_SUCCESS;
}
/**
This is the declaration of an EFI image entry point. This entry point is
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
both device drivers and bus drivers.
The entry point for IpSecConfig application that parse the command line input and call an IpSecConfig process.
@param[in] ImageHandle The image handle of this application.
@param[in] SystemTable The pointer to the EFI System Table.
@retval EFI_SUCCESS The operation completed successfully.
**/
EFI_STATUS
EFIAPI
InitializeIpSecConfig (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_IPSEC_CONFIG_DATA_TYPE DataType;
UINT8 Value;
LIST_ENTRY *ParamPackage;
CONST CHAR16 *ValueStr;
CHAR16 *ProblemParam;
UINTN NonOptionCount;
//
// Register our string package with HII and return the handle to it.
//
mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, IpSecConfigStrings, NULL);
ASSERT (mHiiHandle != NULL);
Status = ShellCommandLineParseEx (mIpSecConfigParamList, &ParamPackage, &ProblemParam, TRUE, FALSE);
if (EFI_ERROR (Status)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_UNKNOWN_OPERATION), mHiiHandle, ProblemParam);
goto Done;
}
Status = IpSecConfigRetriveCheckListByName (mIpSecConfigVarCheckList, ParamPackage);
if (EFI_ERROR (Status)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_MISTAKEN_OPTIONS), mHiiHandle);
goto Done;
}
Status = LocateProtocol (&gEfiIpSecConfigProtocolGuid, (VOID **) &mIpSecConfig);
if (EFI_ERROR (Status) || mIpSecConfig == NULL) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_PROTOCOL_INEXISTENT), mHiiHandle, mAppName);
goto Done;
}
Status = LocateProtocol (&gEfiIpSecProtocolGuid, (VOID **) &mIpSec);
if (EFI_ERROR (Status) || mIpSec == NULL) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_PROTOCOL_INEXISTENT), mHiiHandle, mAppName);
goto Done;
}
//
// Enable IPsec.
//
if (ShellCommandLineGetFlag (ParamPackage, L"-enable")) {
if (!(mIpSec->DisabledFlag)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ALREADY_ENABLE), mHiiHandle, mAppName);
} else {
//
// Set enable flag.
//
Value = IPSEC_STATUS_ENABLED;
Status = gRT->SetVariable (
IPSECCONFIG_STATUS_NAME,
&gEfiIpSecConfigProtocolGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
sizeof (Value),
&Value
);
if (!EFI_ERROR (Status)) {
mIpSec->DisabledFlag = FALSE;
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ENABLE_SUCCESS), mHiiHandle, mAppName);
} else {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ENABLE_FAILED), mHiiHandle, mAppName);
}
}
goto Done;
}
//
// Disable IPsec.
//
if (ShellCommandLineGetFlag (ParamPackage, L"-disable")) {
if (mIpSec->DisabledFlag) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ALREADY_DISABLE), mHiiHandle, mAppName);
} else {
//
// Set disable flag; however, leave it to be disabled in the callback function of DisabledEvent.
//
gBS->SignalEvent (mIpSec->DisabledEvent);
if (mIpSec->DisabledFlag) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_DISABLE_SUCCESS), mHiiHandle, mAppName);
} else {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_DISABLE_FAILED), mHiiHandle, mAppName);
}
}
goto Done;
}
//
//IPsec Status.
//
if (ShellCommandLineGetFlag (ParamPackage, L"-status")) {
if (mIpSec->DisabledFlag) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_STATUS_DISABLE), mHiiHandle, mAppName);
} else {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_STATUS_ENABLE), mHiiHandle, mAppName);
}
goto Done;
}
//
// Try to get policy database type.
//
DataType = (EFI_IPSEC_CONFIG_DATA_TYPE) -1;
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-p");
if (ValueStr != NULL) {
DataType = (EFI_IPSEC_CONFIG_DATA_TYPE) MapStringToInteger (ValueStr, mMapPolicy);
if (DataType == -1) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_DB), mHiiHandle, mAppName, ValueStr);
goto Done;
}
}
if (ShellCommandLineGetFlag (ParamPackage, L"-?")) {
switch (DataType) {
case (EFI_IPSEC_CONFIG_DATA_TYPE) -1:
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_HELP), mHiiHandle);
break;
case IPsecConfigDataTypeSpd:
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_SPD_HELP), mHiiHandle);
break;
case IPsecConfigDataTypeSad:
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_SAD_HELP), mHiiHandle);
break;
case IPsecConfigDataTypePad:
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_PAD_HELP), mHiiHandle);
break;
default:
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_DB), mHiiHandle);
break;
}
goto Done;
}
NonOptionCount = ShellCommandLineGetCount ();
if ((NonOptionCount - 1) > 0) {
ValueStr = ShellCommandLineGetRawValue (ParamPackage, (UINT32) (NonOptionCount - 1));
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_REDUNDANCY_MANY), mHiiHandle, mAppName, ValueStr);
goto Done;
}
if (DataType == -1) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_DB), mHiiHandle, mAppName);
goto Done;
}
if (ShellCommandLineGetFlag (ParamPackage, L"-a")) {
Status = AddOrInsertPolicyEntry (DataType, ParamPackage);
if (EFI_ERROR (Status)) {
goto Done;
}
} else if (ShellCommandLineGetFlag (ParamPackage, L"-i")) {
Status = AddOrInsertPolicyEntry (DataType, ParamPackage);
if (EFI_ERROR (Status)) {
goto Done;
}
} else if (ShellCommandLineGetFlag (ParamPackage, L"-e")) {
Status = EditPolicyEntry (DataType, ParamPackage);
if (EFI_ERROR (Status)) {
goto Done;
}
} else if (ShellCommandLineGetFlag (ParamPackage, L"-d")) {
Status = FlushOrDeletePolicyEntry (DataType, ParamPackage);
if (EFI_ERROR (Status)) {
goto Done;
}
} else if (ShellCommandLineGetFlag (ParamPackage, L"-f")) {
Status = FlushOrDeletePolicyEntry (DataType, ParamPackage);
if (EFI_ERROR (Status)) {
goto Done;
}
} else if (ShellCommandLineGetFlag (ParamPackage, L"-l")) {
Status = ListPolicyEntry (DataType, ParamPackage);
if (EFI_ERROR (Status)) {
goto Done;
}
} else {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_UNKNOWN_OPERATION), mHiiHandle, mAppName);
goto Done;
}
Done:
ShellCommandLineFreeVarList (ParamPackage);
HiiRemovePackages (mHiiHandle);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,123 @@
/** @file
The internal structure and function declaration in IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _IPSEC_CONFIG_H_
#define _IPSEC_CONFIG_H_
#include <Library/BaseMemoryLib.h>
#include <Library/UefiLib.h>
#include <Library/ShellLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/NetLib.h>
#include <Protocol/IpSecConfig.h>
#define EFI_IPSEC_CONFIG_GUID \
{ \
0x9db0c3ac, 0xd9d2, 0x4f96, {0x9e, 0xd7, 0x6d, 0xa6, 0x12, 0xa4, 0xf3, 0x27} \
}
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#define IPSECCONFIG_STATUS_NAME L"IpSecStatus"
#define BIT(x) (UINT32) (1 << (x))
#define IPSEC_STATUS_DISABLED 0x0
#define IPSEC_STATUS_ENABLED 0x1
#define EFI_IP4_PROTO_ICMP 0x1
#define EFI_IP4_PROTO_TCP 0x6
#define EFI_IP4_PROTO_UDP 0x11
#define EFI_IPSEC_ANY_PROTOCOL 0xFFFF
#define EFI_IPSEC_ANY_PORT 0
typedef struct _VAR_CHECK_ITEM {
CHAR16 *VarName;
UINT32 Attribute1;
UINT32 Attribute2;
UINT32 Attribute3;
UINT32 Attribute4;
} VAR_CHECK_ITEM;
typedef struct _SHELL_PARAM_PACKAGE{
LIST_ENTRY Link;
CHAR16 *Name;
ParamType Type;
CHAR16 *Value;
UINTN OriginalPosition;
} SHELL_PARAM_PACKAGE;
typedef struct _STR2INT {
CHAR16 *String;
UINT32 Integer;
} STR2INT;
extern EFI_IPSEC_CONFIG_PROTOCOL *mIpSecConfig;
extern EFI_HII_HANDLE mHiiHandle;
extern CHAR16 mAppName[];
//
// -P
//
extern STR2INT mMapPolicy[];
//
// --proto
//
extern STR2INT mMapIpProtocol[];
//
// --action
//
extern STR2INT mMapIpSecAction[];
//
// --mode
//
extern STR2INT mMapIpSecMode[];
//
// --dont-fragment
//
extern STR2INT mMapDfOption[];
//
// --ipsec-proto
//
extern STR2INT mMapIpSecProtocol[];
//
// --auth-algo
//
extern STR2INT mMapAuthAlgo[];
//
// --encrypt-algo
//
extern STR2INT mMapEncAlgo[];
//
// --auth-proto
//
extern STR2INT mMapAuthProto[];
//
// --auth-method
//
extern STR2INT mMapAuthMethod[];
#endif

View File

@@ -0,0 +1,61 @@
## @file
# Component description file for IpSecConfig6 application.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010006
BASE_NAME = IpSecConfig
FILE_GUID = 0922E604-F5EC-42ef-980D-A35E9A2B1844
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = InitializeIpSecConfig
[Sources]
IpSecConfigStrings.uni
IpSecConfig.c
IpSecConfig.h
Dump.c
Dump.h
Indexer.c
Indexer.h
Match.c
Match.h
Delete.h
Delete.c
Helper.c
Helper.h
ForEach.c
ForEach.h
PolicyEntryOperation.c
PolicyEntryOperation.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
UefiBootServicesTableLib
UefiApplicationEntryPoint
BaseMemoryLib
ShellLib
MemoryAllocationLib
DebugLib
HiiLib
NetLib
UefiLib
[Protocols]
gEfiIpSecProtocolGuid ##CONSUMS
gEfiIpSecConfigProtocolGuid ##CONSUMS

View File

@@ -0,0 +1,163 @@
/** @file
The implementation of match policy entry function in IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "IpSecConfig.h"
#include "Indexer.h"
#include "Match.h"
/**
Private function to validate a buffer that should be filled with zero.
@param[in] Memory The pointer to the buffer.
@param[in] Size The size of the buffer.
@retval TRUE The memory is filled with zero.
@retval FALSE The memory isn't filled with zero.
**/
BOOLEAN
IsMemoryZero (
IN VOID *Memory,
IN UINTN Size
)
{
UINTN Index;
for (Index = 0; Index < Size; Index++) {
if (*((UINT8 *) Memory + Index) != 0) {
return FALSE;
}
}
return TRUE;
}
/**
Find the matching SPD with Indexer.
@param[in] Selector The pointer to the EFI_IPSEC_SPD_SELECTOR structure.
@param[in] Data The pointer to the EFI_IPSEC_SPD_DATA structure.
@param[in] Indexer The pointer to the SPD_ENTRY_INDEXER structure.
@retval TRUE The matched SPD is found.
@retval FALSE The matched SPD is not found.
**/
BOOLEAN
MatchSpdEntry (
IN EFI_IPSEC_SPD_SELECTOR *Selector,
IN EFI_IPSEC_SPD_DATA *Data,
IN SPD_ENTRY_INDEXER *Indexer
)
{
BOOLEAN Match;
Match = FALSE;
if (Indexer->Name != NULL) {
if ((Data->Name != NULL) && (AsciiStrCmp ((CHAR8 *) Indexer->Name, (CHAR8 *) Data->Name) == 0)) {
Match = TRUE;
}
} else {
if (Indexer->Index == 0) {
Match = TRUE;
}
Indexer->Index--;
}
return Match;
}
/**
Find the matching SAD with Indexer.
@param[in] SaId The pointer to the EFI_IPSEC_SA_ID structure.
@param[in] Data The pointer to the EFI_IPSEC_SA_DATA structure.
@param[in] Indexer The pointer to the SPD_ENTRY_INDEXER structure.
@retval TRUE The matched SAD is found.
@retval FALSE The matched SAD is not found.
**/
BOOLEAN
MatchSadEntry (
IN EFI_IPSEC_SA_ID *SaId,
IN EFI_IPSEC_SA_DATA *Data,
IN SAD_ENTRY_INDEXER *Indexer
)
{
BOOLEAN Match;
Match = FALSE;
if (!IsMemoryZero (&Indexer->SaId, sizeof (EFI_IPSEC_SA_ID))) {
Match = (BOOLEAN) (CompareMem (&Indexer->SaId, SaId, sizeof (EFI_IPSEC_SA_ID)) == 0);
} else {
if (Indexer->Index == 0) {
Match = TRUE;
}
Indexer->Index--;
}
return Match;
}
/**
Find the matching PAD with Indexer.
@param[in] PadId The pointer to the EFI_IPSEC_PAD_ID structure.
@param[in] Data The pointer to the EFI_IPSEC_PAD_DATA structure.
@param[in] Indexer The pointer to the SPD_ENTRY_INDEXER structure.
@retval TRUE The matched PAD is found.
@retval FALSE The matched PAD is not found.
**/
BOOLEAN
MatchPadEntry (
IN EFI_IPSEC_PAD_ID *PadId,
IN EFI_IPSEC_PAD_DATA *Data,
IN PAD_ENTRY_INDEXER *Indexer
)
{
BOOLEAN Match;
Match = FALSE;
if (!IsMemoryZero (&Indexer->PadId, sizeof (EFI_IPSEC_PAD_ID))) {
Match = (BOOLEAN) ((Indexer->PadId.PeerIdValid == PadId->PeerIdValid) &&
((PadId->PeerIdValid &&
(StrCmp (
(CONST CHAR16 *) Indexer->PadId.Id.PeerId,
(CONST CHAR16 *) PadId->Id.PeerId
) == 0)) ||
((!PadId->PeerIdValid) &&
(Indexer->PadId.Id.IpAddress.PrefixLength == PadId->Id.IpAddress.PrefixLength) &&
(CompareMem (
&Indexer->PadId.Id.IpAddress.Address,
&PadId->Id.IpAddress.Address,
sizeof (EFI_IP_ADDRESS)
) == 0))));
} else {
if (Indexer->Index == 0) {
Match = TRUE;
}
Indexer->Index--;
}
return Match;
}
MATCH_POLICY_ENTRY mMatchPolicyEntry[] = {
(MATCH_POLICY_ENTRY) MatchSpdEntry,
(MATCH_POLICY_ENTRY) MatchSadEntry,
(MATCH_POLICY_ENTRY) MatchPadEntry
};

View File

@@ -0,0 +1,41 @@
/** @file
The internal structure and function declaration of
match policy entry function in IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _MATCH_H_
#define _MATCH_H_
/**
The prototype for the MatchSpdEntry()/MatchSadEntry()/MatchPadEntry().
The functionality is to find the matching SPD/SAD/PAD with Indexer.
@param[in] Selector The pointer to the EFI_IPSEC_CONFIG_SELECTOR union.
@param[in] Data The pointer to corresponding Data.
@param[in] Indexer The pointer to the POLICY_ENTRY_INDEXER union.
@retval TRUE The matched SPD/SAD/PAD is found.
@retval FALSE The matched SPD/SAD/PAD is not found.
**/
typedef
BOOLEAN
(* MATCH_POLICY_ENTRY) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN POLICY_ENTRY_INDEXER *Indexer
);
extern MATCH_POLICY_ENTRY mMatchPolicyEntry[];
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,158 @@
/** @file
The function declaration of policy entry operation in IpSecConfig application.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _POLICY_ENTRY_OPERATION_H_
#define _POLICY_ENTRY_OPERATION_H_
#define LOCAL BIT(0)
#define REMOTE BIT(1)
#define PROTO BIT(2)
#define LOCAL_PORT BIT(3)
#define REMOTE_PORT BIT(4)
#define ICMP_TYPE BIT(5)
#define ICMP_CODE BIT(6)
#define NAME BIT(7)
#define PACKET_FLAG BIT(8)
#define ACTION BIT(9)
#define EXT_SEQUENCE BIT(10)
#define SEQUENCE_OVERFLOW BIT(11)
#define FRAGMENT_CHECK BIT(12)
#define LIFEBYTE BIT(13)
#define LIFETIME_SOFT BIT(14)
#define LIFETIME BIT(15)
#define MODE BIT(16)
#define TUNNEL_LOCAL BIT(17)
#define TUNNEL_REMOTE BIT(18)
#define DONT_FRAGMENT BIT(19)
#define IPSEC_PROTO BIT(20)
#define AUTH_ALGO BIT(21)
#define ENCRYPT_ALGO BIT(22)
#define SPI BIT(23)
#define DEST BIT(24)
#define SEQUENCE_NUMBER BIT(25)
#define ANTIREPLAY_WINDOW BIT(26)
#define AUTH_KEY BIT(27)
#define ENCRYPT_KEY BIT(28)
#define PATH_MTU BIT(29)
#define PEER_ID BIT(0)
#define PEER_ADDRESS BIT(1)
#define AUTH_PROTO BIT(2)
#define AUTH_METHOD BIT(3)
#define IKE_ID BIT(4)
#define AUTH_DATA BIT(5)
#define REVOCATION_DATA BIT(6)
typedef struct {
EFI_IPSEC_CONFIG_DATA_TYPE DataType;
EFI_IPSEC_CONFIG_SELECTOR *Selector; // Data to be inserted.
VOID *Data;
UINT32 Mask;
POLICY_ENTRY_INDEXER Indexer;
EFI_STATUS Status; // Indicate whether insertion succeeds.
} EDIT_POLICY_ENTRY_CONTEXT;
typedef struct {
EFI_IPSEC_CONFIG_DATA_TYPE DataType;
EFI_IPSEC_CONFIG_SELECTOR *Selector; // Data to be inserted.
VOID *Data;
POLICY_ENTRY_INDEXER Indexer;
EFI_STATUS Status; // Indicate whether insertion succeeds.
} INSERT_POLICY_ENTRY_CONTEXT;
/**
The prototype for the CreateSpdEntry()/CreateSadEntry()/CreatePadEntry().
Fill in EFI_IPSEC_CONFIG_SELECTOR and corresponding data thru ParamPackage list.
@param[out] Selector The pointer to the EFI_IPSEC_CONFIG_SELECTOR union.
@param[out] Data The pointer to corresponding data.
@param[in] ParamPackage The pointer to the ParamPackage list.
@param[out] Mask The pointer to the Mask.
@param[in] CreateNew The switch to create new.
@retval EFI_SUCCESS Filled in EFI_IPSEC_CONFIG_SELECTOR and corresponding data successfully.
@retval EFI_INVALID_PARAMETER Invalid user input parameter.
**/
typedef
EFI_STATUS
(*CREATE_POLICY_ENTRY) (
OUT EFI_IPSEC_CONFIG_SELECTOR **Selector,
OUT VOID **Data,
IN LIST_ENTRY *ParamPackage,
OUT UINT32 *Mask,
IN BOOLEAN CreateNew
);
/**
The prototype for the CombineSpdEntry()/CombineSadEntry()/CombinePadEntry().
Combine old SPD/SAD/PAD entry with new SPD/SAD/PAD entry.
@param[in, out] OldSelector The pointer to the old EFI_IPSEC_CONFIG_SELECTOR union.
@param[in, out] OldData The pointer to the corresponding old data.
@param[in] NewSelector The pointer to the new EFI_IPSEC_CONFIG_SELECTOR union.
@param[in] NewData The pointer to the corresponding new data.
@param[in] Mask The pointer to the Mask.
@param[out] CreateNew The switch to create new.
@retval EFI_SUCCESS Combined successfully.
@retval EFI_INVALID_PARAMETER Invalid user input parameter.
**/
typedef
EFI_STATUS
(* COMBINE_POLICY_ENTRY) (
EFI_IPSEC_CONFIG_SELECTOR *OldSelector,
VOID *OldData,
EFI_IPSEC_CONFIG_SELECTOR *NewSelector,
VOID *NewData,
UINT32 Mask,
BOOLEAN *CreateNew
);
/**
Insert or add entry information in database according to datatype.
@param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE.
@param[in] ParamPackage The pointer to the ParamPackage list.
@retval EFI_SUCCESS Insert or add entry information successfully.
@retval EFI_NOT_FOUND Can't find the specified entry.
@retval EFI_BUFFER_TOO_SMALL The entry already existed.
@retval EFI_UNSUPPORTED The operation is not supported./
@retval Others Some mistaken case.
**/
EFI_STATUS
AddOrInsertPolicyEntry (
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN LIST_ENTRY *ParamPackage
);
/**
Edit entry information in the database according to datatype.
@param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE.
@param[in] ParamPackage The pointer to the ParamPackage list.
@retval EFI_SUCCESS Edit entry information successfully.
@retval EFI_NOT_FOUND Can't find the specified entry.
@retval Others Some mistaken case.
**/
EFI_STATUS
EditPolicyEntry (
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN LIST_ENTRY *ParamPackage
);
#endif

View File

@@ -0,0 +1,28 @@
/** @file
The implement to read TSC in IA32 platform.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Library/BaseLib.h>
/**
Reads and returns the current value of the Time Stamp Counter (TSC).
@return The current value of TSC.
**/
UINT64
ReadTime ()
{
return AsmReadTsc ();
}

View File

@@ -0,0 +1,28 @@
/** @file
The implement to read ITC in IA64 platform.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Library/BaseLib.h>
/**
Reads and returns the current value of the Interval Timer Counter Register (ITC).
@return The current value of ITC.
**/
UINT64
ReadTime ()
{
return AsmReadItc ();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,92 @@
/** @file
The interface function declaration of shell application Ping6 (Ping for v6 series).
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _PING6_H_
#define _PING6_H_
#define EFI_PING6_GUID \
{ \
0x3f0b2478, 0x3619, 0x46c5, {0x81, 0x50, 0xa5, 0xab, 0xdd, 0xb6, 0x6b, 0xd9} \
}
#define PING6_DEFAULT_TIMEOUT 5000
#define PING6_MAX_SEND_NUMBER 10000
#define PING6_MAX_BUFFER_SIZE 32768
#define PING6_ONE_SECOND 10000000
//
// A similar amount of time that passes in femtoseconds
// for each increment of TimerValue. It is for NT32 only.
//
#define NTTIMERPERIOD 358049
#pragma pack(1)
typedef struct _ICMP6_ECHO_REQUEST_REPLY {
UINT8 Type;
UINT8 Code;
UINT16 Checksum;
UINT16 Identifier;
UINT16 SequenceNum;
UINT64 TimeStamp;
UINT8 Data[1];
} ICMP6_ECHO_REQUEST_REPLY;
#pragma pack()
typedef struct _PING6_ICMP6_TX_INFO {
LIST_ENTRY Link;
UINT16 SequenceNum;
UINT64 TimeStamp;
EFI_IP6_COMPLETION_TOKEN *Token;
} PING6_ICMP6_TX_INFO;
typedef struct _PING6_PRIVATE_DATA {
EFI_HANDLE ImageHandle;
EFI_HANDLE NicHandle;
EFI_HANDLE Ip6ChildHandle;
EFI_IP6_PROTOCOL *Ip6;
EFI_EVENT Timer;
EFI_STATUS Status;
LIST_ENTRY TxList;
EFI_IP6_COMPLETION_TOKEN RxToken;
UINT16 RxCount;
UINT16 TxCount;
UINT32 RttSum;
UINT32 RttMin;
UINT32 RttMax;
UINT32 SequenceNum;
EFI_IPv6_ADDRESS SrcAddress;
EFI_IPv6_ADDRESS DstAddress;
UINT32 SendNum;
UINT32 BufferSize;
} PING6_PRIVATE_DATA;
/**
Reads and returns the current value of register.
In IA64, the register is the Interval Timer Vector (ITV).
In X86(IA32/X64), the register is the Time Stamp Counter (TSC)
@return The current value of the register.
**/
UINT64
ReadTime (
VOID
);
#endif

View File

@@ -0,0 +1,64 @@
## @file
# Component description file for Ping6 application.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010006
BASE_NAME = Ping6
FILE_GUID = F35F733F-5235-4d7b-83FA-97780CEBCB20
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = InitializePing6
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF
#
[Sources]
Ping6.c
Ping6Strings.uni
Ping6.h
[Sources.IA32]
Ia32/Tsc.c
[Sources.X64]
X64/Tsc.c
[Sources.IPF]
Ipf/Itc.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
BaseLib
UefiBootServicesTableLib
UefiApplicationEntryPoint
BaseMemoryLib
ShellLib
MemoryAllocationLib
DebugLib
HiiLib
NetLib
[Protocols]
gEfiCpuArchProtocolGuid ## CONSUMS
gEfiIp6ProtocolGuid ## CONSUMS
gEfiIp6ServiceBindingProtocolGuid ## CONSUMS
gEfiIp6ConfigProtocolGuid ## CONSUMS

Binary file not shown.

View File

@@ -0,0 +1,28 @@
/** @file
The implement to read TSC in X64 platform.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Library/BaseLib.h>
/**
Reads and returns the current value of Time Stamp Counter (TSC).
@return The current value of TSC
**/
UINT64
ReadTime ()
{
return AsmReadTsc ();
}

View File

@@ -0,0 +1,668 @@
/** @file
Shell application for VLAN configuration.
Copyright (C) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Protocol/VlanConfig.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiLib.h>
#include <Library/ShellLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/HiiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/NetLib.h>
#define INVALID_NIC_INDEX 0xffff
#define INVALID_VLAN_ID 0xffff
//
// This is the generated String package data for all .UNI files.
// This data array is ready to be used as input of HiiAddPackages() to
// create a packagelist (which contains Form packages, String packages, etc).
//
extern UINT8 VConfigStrings[];
EFI_HANDLE mImageHandle = NULL;
EFI_HII_HANDLE mHiiHandle = NULL;
SHELL_PARAM_ITEM mParamList[] = {
{
L"-l",
TypeValue
},
{
L"-a",
TypeMaxValue
},
{
L"-d",
TypeValue
},
{
NULL,
TypeMax
}
};
/**
Locate the network interface handle buffer.
@param[out] NumberOfHandles Pointer to the number of handles.
@param[out] HandleBuffer Pointer to the buffer to store the returned handles.
**/
VOID
LocateNicHandleBuffer (
OUT UINTN *NumberOfHandles,
OUT EFI_HANDLE **HandleBuffer
)
{
EFI_STATUS Status;
*NumberOfHandles = 0;
*HandleBuffer = NULL;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiVlanConfigProtocolGuid,
NULL,
NumberOfHandles,
HandleBuffer
);
if (EFI_ERROR (Status)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_LOCATE_FAIL), mHiiHandle, Status);
}
}
/**
Extract the decimal index from the network interface name.
@param[in] Name Name of the network interface.
@retval INVALID_NIC_INDEX Failed to extract the network interface index.
@return others The network interface index.
**/
UINTN
NicNameToIndex (
IN CHAR16 *Name
)
{
CHAR16 *Str;
Str = Name + 3;
if ((StrnCmp (Name, L"eth", 3) != 0) || (*Str == 0)) {
return INVALID_NIC_INDEX;
}
while (*Str != 0) {
if ((*Str < L'0') || (*Str > L'9')) {
return INVALID_NIC_INDEX;
}
Str++;
}
return (UINT16) StrDecimalToUintn (Name + 3);
}
/**
Find network interface device handle by its name.
@param[in] Name Name of the network interface.
@retval NULL Cannot find the network interface.
@return others Handle of the network interface.
**/
EFI_HANDLE
NicNameToHandle (
IN CHAR16 *Name
)
{
UINTN NumberOfHandles;
EFI_HANDLE *HandleBuffer;
UINTN Index;
EFI_HANDLE Handle;
//
// Find all NIC handles.
//
LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer);
if (NumberOfHandles == 0) {
return NULL;
}
Index = NicNameToIndex (Name);
if (Index >= NumberOfHandles) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_IF), mHiiHandle, Name);
Handle = NULL;
} else {
Handle = HandleBuffer[Index];
}
FreePool (HandleBuffer);
return Handle;
}
/**
Open VlanConfig protocol from a handle.
@param[in] Handle The handle to open the VlanConfig protocol.
@return The VlanConfig protocol interface.
**/
EFI_VLAN_CONFIG_PROTOCOL *
OpenVlanConfigProtocol (
IN EFI_HANDLE Handle
)
{
EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
VlanConfig = NULL;
gBS->OpenProtocol (
Handle,
&gEfiVlanConfigProtocolGuid,
(VOID **) &VlanConfig,
mImageHandle,
Handle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
return VlanConfig;
}
/**
Close VlanConfig protocol of a handle.
@param[in] Handle The handle to close the VlanConfig protocol.
**/
VOID
CloseVlanConfigProtocol (
IN EFI_HANDLE Handle
)
{
gBS->CloseProtocol (
Handle,
&gEfiVlanConfigProtocolGuid,
mImageHandle,
Handle
);
}
/**
Display VLAN configuration of a network interface.
@param[in] Handle Handle of the network interface.
@param[in] NicIndex Index of the network interface.
**/
VOID
ShowNicVlanInfo (
IN EFI_HANDLE Handle,
IN UINTN NicIndex
)
{
CHAR16 *MacStr;
EFI_STATUS Status;
UINTN Index;
EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
UINT16 NumberOfVlan;
EFI_VLAN_FIND_DATA *VlanData;
VlanConfig = OpenVlanConfigProtocol (Handle);
if (VlanConfig == NULL) {
return ;
}
MacStr = NULL;
Status = NetLibGetMacString (Handle, mImageHandle, &MacStr);
if (EFI_ERROR (Status)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_MAC_FAIL), mHiiHandle, Status);
goto Exit;
}
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_ETH_MAC), mHiiHandle, NicIndex, MacStr);
Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData);
if (EFI_ERROR (Status)) {
if (Status == EFI_NOT_FOUND) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VLAN), mHiiHandle);
} else {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_FIND_FAIL), mHiiHandle, Status);
}
goto Exit;
}
for (Index = 0; Index < NumberOfVlan; Index++) {
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_VCONFIG_VLAN_DISPLAY),
mHiiHandle,
VlanData[Index].VlanId,
VlanData[Index].Priority
);
}
FreePool (VlanData);
Exit:
CloseVlanConfigProtocol (Handle);
if (MacStr != NULL) {
FreePool (MacStr);
}
}
/**
Display the VLAN configuration of all, or a specified network interface.
@param[in] Name Name of the network interface. If NULL, the VLAN
configuration of all network will be displayed.
**/
VOID
DisplayVlan (
IN CHAR16 *Name OPTIONAL
)
{
UINTN NumberOfHandles;
EFI_HANDLE *HandleBuffer;
UINTN Index;
EFI_HANDLE NicHandle;
if (Name != NULL) {
//
// Display specified NIC
//
NicHandle = NicNameToHandle (Name);
if (NicHandle == NULL) {
return ;
}
ShowNicVlanInfo (NicHandle, 0);
return ;
}
//
// Find all NIC handles
//
LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer);
if (NumberOfHandles == 0) {
return ;
}
for (Index = 0; Index < NumberOfHandles; Index++) {
ShowNicVlanInfo (HandleBuffer[Index], Index);
}
FreePool (HandleBuffer);
}
/**
Convert a NULL-terminated unicode decimal VLAN ID string to VLAN ID.
@param[in] String Pointer to VLAN ID string from user input.
@retval Value translated from String, or INVALID_VLAN_ID is string is invalid.
**/
UINT16
StrToVlanId (
IN CHAR16 *String
)
{
CHAR16 *Str;
if (String == NULL) {
return INVALID_VLAN_ID;
}
Str = String;
while ((*Str >= '0') && (*Str <= '9')) {
Str++;
}
if (*Str != 0) {
return INVALID_VLAN_ID;
}
return (UINT16) StrDecimalToUintn (String);
}
/**
Add a VLAN device.
@param[in] ParamStr Parameter string from user input.
**/
VOID
AddVlan (
IN CHAR16 *ParamStr
)
{
CHAR16 *Name;
CHAR16 *VlanIdStr;
CHAR16 *PriorityStr;
CHAR16 *StrPtr;
BOOLEAN IsSpace;
UINTN VlanId;
UINTN Priority;
EFI_HANDLE Handle;
EFI_HANDLE VlanHandle;
EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
EFI_STATUS Status;
VlanConfig = NULL;
Priority = 0;
if (ParamStr == NULL) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle);
return ;
}
StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr);
if (StrPtr == NULL) {
return ;
}
Name = StrPtr;
VlanIdStr = NULL;
PriorityStr = NULL;
IsSpace = FALSE;
while (*StrPtr != 0) {
if (*StrPtr == L' ') {
*StrPtr = 0;
IsSpace = TRUE;
} else {
if (IsSpace) {
//
// Start of a parameter.
//
if (VlanIdStr == NULL) {
//
// 2nd parameter is VLAN ID.
//
VlanIdStr = StrPtr;
} else if (PriorityStr == NULL) {
//
// 3rd parameter is Priority.
//
PriorityStr = StrPtr;
} else {
//
// Ignore else parameters.
//
break;
}
}
IsSpace = FALSE;
}
StrPtr++;
}
Handle = NicNameToHandle (Name);
if (Handle == NULL) {
goto Exit;
}
VlanConfig = OpenVlanConfigProtocol (Handle);
if (VlanConfig == NULL) {
goto Exit;
}
//
// Check VLAN ID.
//
if ((VlanIdStr == NULL) || (*VlanIdStr == 0)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle);
goto Exit;
}
VlanId = StrToVlanId (VlanIdStr);
if (VlanId > 4094) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr);
goto Exit;
}
//
// Check Priority.
//
if ((PriorityStr != NULL) && (*PriorityStr != 0)) {
Priority = StrDecimalToUintn (PriorityStr);
if (Priority > 7) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_PRIORITY), mHiiHandle, PriorityStr);
goto Exit;
}
}
//
// Set VLAN
//
Status = VlanConfig->Set (VlanConfig, (UINT16) VlanId, (UINT8) Priority);
if (EFI_ERROR (Status)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_FAIL), mHiiHandle, Status);
goto Exit;
}
//
// Connect the VLAN device.
//
VlanHandle = NetLibGetVlanHandle (Handle, (UINT16) VlanId);
if (VlanHandle != NULL) {
gBS->ConnectController (VlanHandle, NULL, NULL, TRUE);
}
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_SUCCESS), mHiiHandle);
Exit:
if (VlanConfig != NULL) {
CloseVlanConfigProtocol (Handle);
}
FreePool (Name);
}
/**
Remove a VLAN device.
@param[in] ParamStr Parameter string from user input.
**/
VOID
DeleteVlan (
CHAR16 *ParamStr
)
{
CHAR16 *Name;
CHAR16 *VlanIdStr;
CHAR16 *StrPtr;
UINTN VlanId;
EFI_HANDLE Handle;
EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
EFI_STATUS Status;
UINT16 NumberOfVlan;
EFI_VLAN_FIND_DATA *VlanData;
VlanConfig = NULL;
if (ParamStr == NULL) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle);
return ;
}
StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr);
if (StrPtr == NULL) {
return ;
}
Name = StrPtr;
VlanIdStr = NULL;
while (*StrPtr != 0) {
if (*StrPtr == L'.') {
*StrPtr = 0;
VlanIdStr = StrPtr + 1;
break;
}
StrPtr++;
}
Handle = NicNameToHandle (Name);
if (Handle == NULL) {
goto Exit;
}
VlanConfig = OpenVlanConfigProtocol (Handle);
if (VlanConfig == NULL) {
goto Exit;
}
//
// Check VLAN ID
//
if (VlanIdStr == NULL || *VlanIdStr == 0) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle);
goto Exit;
}
VlanId = StrToVlanId (VlanIdStr);
if (VlanId > 4094) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr);
goto Exit;
}
//
// Delete VLAN.
//
Status = VlanConfig->Remove (VlanConfig, (UINT16) VlanId);
if (EFI_ERROR (Status)) {
if (Status == EFI_NOT_FOUND) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NOT_FOUND), mHiiHandle);
} else {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_FAIL), mHiiHandle, Status);
}
goto Exit;
}
//
// Check whether this is the last VLAN to remove.
//
Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData);
if (EFI_ERROR (Status)) {
//
// This is the last VLAN to remove, try to connect the controller handle.
//
gBS->ConnectController (Handle, NULL, NULL, TRUE);
} else {
FreePool (VlanData);
}
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_SUCCESS), mHiiHandle);
Exit:
if (VlanConfig != NULL) {
CloseVlanConfigProtocol (Handle);
}
FreePool (Name);
}
/**
The actual entry point for the application.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The entry point executed successfully.
@retval other Some error occur when executing this entry point.
**/
EFI_STATUS
EFIAPI
VlanConfigMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
LIST_ENTRY *List;
CONST CHAR16 *Str;
mImageHandle = ImageHandle;
//
// Register our string package to HII database.
//
mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, VConfigStrings, NULL);
if (mHiiHandle == NULL) {
return EFI_SUCCESS;
}
List = NULL;
ShellCommandLineParseEx (mParamList, &List, NULL, FALSE, FALSE);
if (List == NULL) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle);
goto Exit;
}
if (ShellCommandLineGetFlag (List, L"-?")) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_HELP), mHiiHandle);
goto Exit;
}
if (ShellCommandLineGetFlag (List, L"-l")) {
Str = ShellCommandLineGetValue (List, L"-l");
DisplayVlan ((CHAR16 *) Str);
goto Exit;
}
if (ShellCommandLineGetFlag (List, L"-a")) {
Str = ShellCommandLineGetValue (List, L"-a");
AddVlan ((CHAR16 *) Str);
goto Exit;
}
if (ShellCommandLineGetFlag (List, L"-d")) {
Str = ShellCommandLineGetValue (List, L"-d");
DeleteVlan ((CHAR16 *) Str);
goto Exit;
}
//
// No valid argument till now.
//
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle);
Exit:
if (List != NULL) {
ShellCommandLineFreeVarList (List);
}
//
// Remove our string package from HII database.
//
HiiRemovePackages (mHiiHandle);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,47 @@
## @file
# Component files for VLAN configuration shell application.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = VConfig
FILE_GUID = 87E36301-0406-44db-AAF3-9E0E591F3725
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = VlanConfigMain
#
# VALID_ARCHITECTURES = IA32 X64 IPF
#
[Sources]
VConfigStrings.uni
VConfig.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
UefiBootServicesTableLib
UefiLib
ShellLib
NetLib
MemoryAllocationLib
HiiLib
[Protocols]
gEfiVlanConfigProtocolGuid

Binary file not shown.

View File

@@ -0,0 +1,312 @@
/** @file
UEFI Component Name(2) protocol implementation for Dhcp6 driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Dhcp6Impl.h"
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Dhcp6ComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is being managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that attempt to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that attempts to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language, from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Dhcp6ComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI Component Name Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gDhcp6ComponentName = {
Dhcp6ComponentNameGetDriverName,
Dhcp6ComponentNameGetControllerName,
"eng"
};
//
// EFI Component Name 2 Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gDhcp6ComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Dhcp6ComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Dhcp6ComponentNameGetControllerName,
"en"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mDhcp6DriverNameTable[] = {
{
"eng;en",
L"DHCP6 Protocol Driver"
},
{
NULL,
NULL
}
};
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Dhcp6ComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mDhcp6DriverNameTable,
DriverName,
(BOOLEAN)(This == &gDhcp6ComponentName)
);
}
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is being managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in the
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language, from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Dhcp6ComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
return EFI_UNSUPPORTED;
}

View File

@@ -0,0 +1,782 @@
/** @file
Driver Binding functions and Service Binding functions
implementationfor for Dhcp6 Driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Dhcp6Impl.h"
EFI_DRIVER_BINDING_PROTOCOL gDhcp6DriverBinding = {
Dhcp6DriverBindingSupported,
Dhcp6DriverBindingStart,
Dhcp6DriverBindingStop,
0xa,
NULL,
NULL
};
EFI_SERVICE_BINDING_PROTOCOL gDhcp6ServiceBindingTemplate = {
Dhcp6ServiceBindingCreateChild,
Dhcp6ServiceBindingDestroyChild
};
/**
Configure the default Udp6Io to receive all the DHCP6 traffic
on this network interface.
@param[in] UdpIo The pointer to Udp6Io to be configured.
@param[in] Context The pointer to the context.
@retval EFI_SUCCESS The Udp6Io is successfully configured.
@retval Others Failed to configure the Udp6Io.
**/
EFI_STATUS
EFIAPI
Dhcp6ConfigureUdpIo (
IN UDP_IO *UdpIo,
IN VOID *Context
)
{
EFI_UDP6_PROTOCOL *Udp6;
EFI_UDP6_CONFIG_DATA *Config;
Udp6 = UdpIo->Protocol.Udp6;
Config = &(UdpIo->Config.Udp6);
ZeroMem (Config, sizeof (EFI_UDP6_CONFIG_DATA));
//
// Set Udp6 configure data for the Dhcp6 instance.
//
Config->AcceptPromiscuous = FALSE;
Config->AcceptAnyPort = FALSE;
Config->AllowDuplicatePort = FALSE;
Config->TrafficClass = 0;
Config->HopLimit = 128;
Config->ReceiveTimeout = 0;
Config->TransmitTimeout = 0;
//
// Configure an endpoint of client(0, 546), server(0, 0), the addresses
// will be overridden later. Note that we MUST not limit RemotePort.
// More details, refer to RFC 3315 section 5.2.
//
Config->StationPort = DHCP6_PORT_CLIENT;
Config->RemotePort = 0;
return Udp6->Configure (Udp6, Config);;
}
/**
Destory the Dhcp6 service. The Dhcp6 service may be partly initialized,
or partly destroyed. If a resource is destroyed, it is marked as such in
case the destroy failed and being called again later.
@param[in, out] Service The pointer to Dhcp6 service to be destroyed.
**/
VOID
Dhcp6DestroyService (
IN OUT DHCP6_SERVICE *Service
)
{
//
// All children instances should have been already destoryed here.
//
ASSERT (Service->NumOfChild == 0);
if (Service->ClientId != NULL) {
FreePool (Service->ClientId);
}
if (Service->UdpIo != NULL) {
UdpIoFreeIo (Service->UdpIo);
}
FreePool (Service);
}
/**
Create a new Dhcp6 service for the Nic controller.
@param[in] Controller The controller to be installed DHCP6 service
binding protocol.
@param[in] ImageHandle The image handle of the Dhcp6 driver.
@param[out] Service The return pointer of the new Dhcp6 service.
@retval EFI_SUCCESS The Dhcp6 service is created successfully.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
**/
EFI_STATUS
Dhcp6CreateService (
IN EFI_HANDLE Controller,
IN EFI_HANDLE ImageHandle,
OUT DHCP6_SERVICE **Service
)
{
DHCP6_SERVICE *Dhcp6Srv;
*Service = NULL;
Dhcp6Srv = AllocateZeroPool (sizeof (DHCP6_SERVICE));
if (Dhcp6Srv == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Open the SNP protocol to get mode data later.
//
Dhcp6Srv->Snp = NULL;
NetLibGetSnpHandle (Controller, &Dhcp6Srv->Snp);
if (Dhcp6Srv->Snp == NULL) {
FreePool (Dhcp6Srv);
return EFI_DEVICE_ERROR;
}
//
// Initialize the fields of the new Dhcp6 service.
//
Dhcp6Srv->Signature = DHCP6_SERVICE_SIGNATURE;
Dhcp6Srv->InDestory = FALSE;
Dhcp6Srv->Controller = Controller;
Dhcp6Srv->Image = ImageHandle;
Dhcp6Srv->Xid = (0xffffff & NET_RANDOM (NetRandomInitSeed ()));
CopyMem (
&Dhcp6Srv->ServiceBinding,
&gDhcp6ServiceBindingTemplate,
sizeof (EFI_SERVICE_BINDING_PROTOCOL)
);
//
// Generate client Duid in the format of Duid-llt.
//
Dhcp6Srv->ClientId = Dhcp6GenerateClientId (Dhcp6Srv->Snp->Mode);
if (Dhcp6Srv->ClientId == NULL) {
FreePool (Dhcp6Srv);
return EFI_DEVICE_ERROR;
}
//
// Create an Udp6Io for stateful transmit/receive of each Dhcp6 instance.
//
Dhcp6Srv->UdpIo = UdpIoCreateIo (
Controller,
ImageHandle,
Dhcp6ConfigureUdpIo,
UDP_IO_UDP6_VERSION,
NULL
);
if (Dhcp6Srv->UdpIo == NULL) {
FreePool (Dhcp6Srv->ClientId);
FreePool (Dhcp6Srv);
return EFI_DEVICE_ERROR;
}
InitializeListHead (&Dhcp6Srv->Child);
*Service = Dhcp6Srv;
return EFI_SUCCESS;
}
/**
Destroy the Dhcp6 instance and recycle the resources.
@param[in, out] Instance The pointer to the Dhcp6 instance.
**/
VOID
Dhcp6DestroyInstance (
IN OUT DHCP6_INSTANCE *Instance
)
{
//
// Clean up the retry list first.
//
Dhcp6CleanupRetry (Instance, DHCP6_PACKET_ALL);
gBS->CloseEvent (Instance->Timer);
//
// Clean up the current configure data.
//
if (Instance->Config != NULL) {
Dhcp6CleanupConfigData (Instance->Config);
FreePool (Instance->Config);
}
//
// Clean up the current Ia.
//
if (Instance->IaCb.Ia != NULL) {
if (Instance->IaCb.Ia->ReplyPacket != NULL) {
FreePool (Instance->IaCb.Ia->ReplyPacket);
}
FreePool (Instance->IaCb.Ia);
}
if (Instance->Unicast != NULL) {
FreePool (Instance->Unicast);
}
if (Instance->AdSelect != NULL) {
FreePool (Instance->AdSelect);
}
FreePool (Instance);
}
/**
Create the Dhcp6 instance and initialize it.
@param[in] Service The pointer to the Dhcp6 service.
@param[out] Instance The pointer to the Dhcp6 instance.
@retval EFI_SUCCESS The Dhcp6 instance is created.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
**/
EFI_STATUS
Dhcp6CreateInstance (
IN DHCP6_SERVICE *Service,
OUT DHCP6_INSTANCE **Instance
)
{
EFI_STATUS Status;
DHCP6_INSTANCE *Dhcp6Ins;
*Instance = NULL;
Dhcp6Ins = AllocateZeroPool (sizeof (DHCP6_INSTANCE));
if (Dhcp6Ins == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Initialize the fields of the new Dhcp6 instance.
//
Dhcp6Ins->Signature = DHCP6_INSTANCE_SIGNATURE;
Dhcp6Ins->UdpSts = EFI_ALREADY_STARTED;
Dhcp6Ins->Service = Service;
Dhcp6Ins->InDestory = FALSE;
Dhcp6Ins->MediaPresent = TRUE;
CopyMem (
&Dhcp6Ins->Dhcp6,
&gDhcp6ProtocolTemplate,
sizeof (EFI_DHCP6_PROTOCOL)
);
InitializeListHead (&Dhcp6Ins->TxList);
InitializeListHead (&Dhcp6Ins->InfList);
//
// There is a timer for each Dhcp6 instance, which is used to track the
// lease time of Ia and the retransmisson time of all sent packets.
//
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL | EVT_TIMER,
TPL_CALLBACK,
Dhcp6OnTimerTick,
Dhcp6Ins,
&Dhcp6Ins->Timer
);
if (EFI_ERROR (Status)) {
FreePool (Dhcp6Ins);
return Status;
}
*Instance = Dhcp6Ins;
return EFI_SUCCESS;
}
/**
Entry point of the DHCP6 driver to install various protocols.
@param[in] ImageHandle The handle of the UEFI image file.
@param[in] SystemTable The pointer to the EFI System Table.
@retval EFI_SUCCESS The operation completed successfully.
@retval Others Unexpected error occurs.
**/
EFI_STATUS
EFIAPI
Dhcp6DriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gDhcp6DriverBinding,
ImageHandle,
&gDhcp6ComponentName,
&gDhcp6ComponentName2
);
}
/**
Test to see if this driver supports ControllerHandle. This service
is called by the EFI boot service ConnectController(). In
order to make drivers as small as possible, there are a few calling
restrictions for this service. ConnectController() must
follow these calling restrictions. If any other agent wishes to call
Supported() it must also follow these calling restrictions.
@param[in] This The pointer to the driver binding protocol.
@param[in] ControllerHandle The handle of device to be tested.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to be started.
@retval EFI_SUCCESS This driver supports this device.
@retval Others This driver does not support this device.
**/
EFI_STATUS
EFIAPI
Dhcp6DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
return gBS->OpenProtocol (
ControllerHandle,
&gEfiUdp6ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
}
/**
Start this driver on ControllerHandle. This service is called by the
EFI boot service ConnectController(). In order to make
drivers as small as possible, there are a few calling restrictions for
this service. ConnectController() must follow these
calling restrictions. If any other agent wishes to call Start() it
must also follow these calling restrictions.
@param[in] This The pointer to the driver binding protocol.
@param[in] ControllerHandle The handle of device to be started.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to be started.
@retval EFI_SUCCESS This driver is installed 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
Dhcp6DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
EFI_STATUS Status;
DHCP6_SERVICE *Service;
//
// Check the Dhcp6 serivce whether already started.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiDhcp6ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (!EFI_ERROR (Status)) {
return EFI_ALREADY_STARTED;
}
//
// Create and initialize the Dhcp6 service.
//
Status = Dhcp6CreateService (
ControllerHandle,
This->DriverBindingHandle,
&Service
);
if (EFI_ERROR (Status)) {
return Status;
}
ASSERT (Service != NULL);
Status = gBS->InstallMultipleProtocolInterfaces (
&ControllerHandle,
&gEfiDhcp6ServiceBindingProtocolGuid,
&Service->ServiceBinding,
NULL
);
if (EFI_ERROR (Status)) {
Dhcp6DestroyService (Service);
return Status;
}
return EFI_SUCCESS;
}
/**
Stop this driver on ControllerHandle. This service is called by the
EFI boot service DisconnectController(). In order to
make drivers as small as possible, there are a few calling
restrictions for this service. DisconnectController()
must follow these calling restrictions. If any other agent wishes
to call Stop() it must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to stop driver on
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
children is zero stop the entire bus driver.
@param[in] ChildHandleBuffer List of Child Handles to Stop.
@retval EFI_SUCCESS This driver is removed ControllerHandle
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval other This driver was not removed from this device
**/
EFI_STATUS
EFIAPI
Dhcp6DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
)
{
EFI_STATUS Status;
EFI_TPL OldTpl;
EFI_HANDLE NicHandle;
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
DHCP6_SERVICE *Service;
DHCP6_INSTANCE *Instance;
//
// Find and check the Nic handle by the controller handle.
//
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);
if (NicHandle == NULL) {
return EFI_DEVICE_ERROR;
}
Status = gBS->OpenProtocol (
NicHandle,
&gEfiDhcp6ServiceBindingProtocolGuid,
(VOID **) &ServiceBinding,
This->DriverBindingHandle,
NicHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
Service = DHCP6_SERVICE_FROM_THIS (ServiceBinding);
if (Service->InDestory) {
return EFI_SUCCESS;
}
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
if (NumberOfChildren == 0) {
//
// Destory the service itself if no child instance left.
//
Service->InDestory = TRUE;
Status = gBS->UninstallProtocolInterface (
NicHandle,
&gEfiDhcp6ServiceBindingProtocolGuid,
ServiceBinding
);
if (EFI_ERROR (Status)) {
Service->InDestory = FALSE;
goto ON_EXIT;
}
Dhcp6DestroyService (Service);
} else {
//
// Destory all the children instances before destory the service.
//
while (!IsListEmpty (&Service->Child)) {
Instance = NET_LIST_HEAD (&Service->Child, DHCP6_INSTANCE, Link);
ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
}
//
// Any of child failed to be destroyed.
//
if (Service->NumOfChild != 0) {
Status = EFI_DEVICE_ERROR;
}
}
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}
/**
Creates a child handle and installs a protocol.
The CreateChild() function installs a protocol on ChildHandle.
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param[in, out] ChildHandle Pointer to the handle of the child to create. If it is NULL,
then a new handle is created. If it is a pointer to an existing
UEFI handle, then the protocol is added to the existing UEFI handle.
@retval EFI_SUCCES The protocol was added to ChildHandle.
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
@retval other The child handle was not created.
**/
EFI_STATUS
EFIAPI
Dhcp6ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN OUT EFI_HANDLE *ChildHandle
)
{
EFI_STATUS Status;
EFI_TPL OldTpl;
DHCP6_SERVICE *Service;
DHCP6_INSTANCE *Instance;
VOID *Udp6;
if (This == NULL || ChildHandle == NULL) {
return EFI_INVALID_PARAMETER;
}
Service = DHCP6_SERVICE_FROM_THIS (This);
Status = Dhcp6CreateInstance (Service, &Instance);
if (EFI_ERROR (Status)) {
return Status;
}
ASSERT (Instance != NULL);
//
// Start the timer when the instance is ready to use.
//
Status = gBS->SetTimer (
Instance->Timer,
TimerPeriodic,
TICKS_PER_SECOND
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Install the DHCP6 protocol onto ChildHandle.
//
Status = gBS->InstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiDhcp6ProtocolGuid,
&Instance->Dhcp6,
NULL
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Instance->Handle = *ChildHandle;
//
// Open the UDP6 protocol BY_CHILD.
//
Status = gBS->OpenProtocol (
Service->UdpIo->UdpHandle,
&gEfiUdp6ProtocolGuid,
(VOID **) &Udp6,
gDhcp6DriverBinding.DriverBindingHandle,
Instance->Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
gBS->UninstallMultipleProtocolInterfaces (
Instance->Handle,
&gEfiDhcp6ProtocolGuid,
&Instance->Dhcp6,
NULL
);
goto ON_ERROR;
}
//
// Add into the children list of its parent service.
//
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
InsertTailList (&Service->Child, &Instance->Link);
Service->NumOfChild++;
gBS->RestoreTPL (OldTpl);
return EFI_SUCCESS;
ON_ERROR:
Dhcp6DestroyInstance (Instance);
return Status;
}
/**
Destroys a child handle with a protocol installed on it.
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
last protocol on ChildHandle, then ChildHandle is destroyed.
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param[in] ChildHandle Handle of the child to destroy
@retval EFI_SUCCES The protocol was removed from ChildHandle.
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
@retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
@retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
because its services are being used.
@retval other The child handle was not destroyed
**/
EFI_STATUS
EFIAPI
Dhcp6ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
)
{
EFI_STATUS Status;
EFI_TPL OldTpl;
EFI_DHCP6_PROTOCOL *Dhcp6;
DHCP6_SERVICE *Service;
DHCP6_INSTANCE *Instance;
if (This == NULL || ChildHandle == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Retrieve the private context data structures
//
Status = gBS->OpenProtocol (
ChildHandle,
&gEfiDhcp6ProtocolGuid,
(VOID **) &Dhcp6,
gDhcp6DriverBinding.DriverBindingHandle,
ChildHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
Instance = DHCP6_INSTANCE_FROM_THIS (Dhcp6);
Service = DHCP6_SERVICE_FROM_THIS (This);
if (Instance->Service != Service) {
return EFI_INVALID_PARAMETER;
}
if (Instance->InDestory) {
return EFI_SUCCESS;
}
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
Instance->InDestory = TRUE;
Status = gBS->CloseProtocol (
Service->UdpIo->UdpHandle,
&gEfiUdp6ProtocolGuid,
gDhcp6DriverBinding.DriverBindingHandle,
ChildHandle
);
if (EFI_ERROR (Status)) {
Instance->InDestory = FALSE;
gBS->RestoreTPL (OldTpl);
return Status;
}
//
// Uninstall the MTFTP6 protocol first to enable a top down destruction.
//
Status = gBS->UninstallProtocolInterface (
ChildHandle,
&gEfiDhcp6ProtocolGuid,
Dhcp6
);
if (EFI_ERROR (Status)) {
Instance->InDestory = FALSE;
gBS->RestoreTPL (OldTpl);
return Status;
}
//
// Remove it from the children list of its parent service.
//
RemoveEntryList (&Instance->Link);
Service->NumOfChild--;
Dhcp6DestroyInstance (Instance);
gBS->RestoreTPL (OldTpl);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,155 @@
/** @file
Driver Binding functions and Service Binding functions
declaration for Dhcp6 Driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_DHCP6_DRIVER_H__
#define __EFI_DHCP6_DRIVER_H__
#include <Protocol/ServiceBinding.h>
extern EFI_COMPONENT_NAME_PROTOCOL gDhcp6ComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gDhcp6ComponentName2;
/**
Test to see if this driver supports ControllerHandle. This service
is called by the EFI boot service ConnectController(). In
order to make drivers as small as possible, there are a few calling
restrictions for this service. ConnectController() must
follow these calling restrictions. If any other agent wishes to call
Supported(), it must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to test.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to start.
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_ALREADY_STARTED This driver is already running on this device.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
Dhcp6DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
);
/**
Start this driver on ControllerHandle. This service is called by the
EFI boot service ConnectController(). In order to make
drivers as small as possible, there are a few calling restrictions for
this service. ConnectController() must follow these
calling restrictions. If any other agent wishes to call Start(), it
must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to bind driver to.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to start.
@retval EFI_SUCCESS This driver is added to ControllerHandle.
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
Dhcp6DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
);
/**
Stop this driver on ControllerHandle. This service is called by the
EFI boot service DisconnectController(). In order to
make drivers as small as possible, there are a few calling
restrictions for this service. DisconnectController()
must follow these calling restrictions. If any other agent wishes
to call Stop() it must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to stop driver on.
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of
children is zero, stop the entire bus driver.
@param[in] ChildHandleBuffer List of Child Handles to Stop.
@retval EFI_SUCCESS This driver is removed ControllerHandle.
@retval other This driver was not removed from this device.
**/
EFI_STATUS
EFIAPI
Dhcp6DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
);
/**
Creates a child handle and installs a protocol.
The CreateChild() function installs a protocol on ChildHandle.
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param ChildHandle Pointer to the handle of the child to create. If it is NULL,
then a new handle is created. If it is a pointer to an existing UEFI handle,
then the protocol is added to the existing UEFI handle.
@retval EFI_SUCCES The protocol was added to ChildHandle.
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
@retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
the child.
@retval other The child handle was not created.
**/
EFI_STATUS
EFIAPI
Dhcp6ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN OUT EFI_HANDLE *ChildHandle
);
/**
Destroys a child handle with a protocol installed on it.
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
last protocol on ChildHandle, then ChildHandle is destroyed.
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param ChildHandle Handle of the child to destroy.
@retval EFI_SUCCES The protocol was removed from ChildHandle.
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
@retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
@retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
because its services are being used.
@retval other The child handle was not destroyed
**/
EFI_STATUS
EFIAPI
Dhcp6ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
);
#endif

View File

@@ -0,0 +1,69 @@
## @file
# Component description file for Dhcp6 module.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = Dhcp6Dxe
FILE_GUID = 95E3669D-34BE-4775-A651-7EA41B69D89E
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = Dhcp6DriverEntryPoint
UNLOAD_IMAGE = NetLibDefaultUnload
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
# DRIVER_BINDING = gDhcp6DriverBinding
# COMPONENT_NAME = gDhcp6ComponentName
# COMPONENT_NAME2 = gDhcp6ComponentName2
#
[Sources]
Dhcp6Driver.c
Dhcp6Driver.h
Dhcp6Impl.c
Dhcp6Impl.h
Dhcp6Io.c
Dhcp6Io.h
Dhcp6Utility.c
Dhcp6Utility.h
ComponentName.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiLib
BaseLib
BaseMemoryLib
MemoryAllocationLib
UefiDriverEntryPoint
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
DebugLib
NetLib
UdpIoLib
[Protocols]
gEfiUdp6ServiceBindingProtocolGuid
gEfiUdp6ProtocolGuid
gEfiDhcp6ServiceBindingProtocolGuid
gEfiDhcp6ProtocolGuid

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,597 @@
/** @file
Dhcp6 internal data structure and definition declaration.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_DHCP6_IMPL_H__
#define __EFI_DHCP6_IMPL_H__
#include <Uefi.h>
#include <Protocol/Dhcp6.h>
#include <Protocol/Udp6.h>
#include <Protocol/ServiceBinding.h>
#include <Protocol/DriverBinding.h>
#include <Library/UdpIoLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Library/NetLib.h>
typedef struct _DHCP6_IA_CB DHCP6_IA_CB;
typedef struct _DHCP6_INF_CB DHCP6_INF_CB;
typedef struct _DHCP6_TX_CB DHCP6_TX_CB;
typedef struct _DHCP6_SERVICE DHCP6_SERVICE;
typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE;
#include "Dhcp6Utility.h"
#include "Dhcp6Io.h"
#include "Dhcp6Driver.h"
#define DHCP6_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'S')
#define DHCP6_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'I')
//
// Transmit parameters of solicit message, refers to section-5.5 of rfc-3315.
//
#define DHCP6_SOL_MAX_DELAY 1
#define DHCP6_SOL_IRT 1
#define DHCP6_SOL_MRC 0
#define DHCP6_SOL_MRT 120
#define DHCP6_SOL_MRD 0
//
// Transmit parameters of request message, refers to section-5.5 of rfc-3315.
//
#define DHCP6_REQ_IRT 1
#define DHCP6_REQ_MRC 10
#define DHCP6_REQ_MRT 30
#define DHCP6_REQ_MRD 0
//
// Transmit parameters of confirm message, refers to section-5.5 of rfc-3315.
//
#define DHCP6_CNF_MAX_DELAY 1
#define DHCP6_CNF_IRT 1
#define DHCP6_CNF_MRC 0
#define DHCP6_CNF_MRT 4
#define DHCP6_CNF_MRD 10
//
// Transmit parameters of renew message, refers to section-5.5 of rfc-3315.
//
#define DHCP6_REN_IRT 10
#define DHCP6_REN_MRC 0
#define DHCP6_REN_MRT 600
#define DHCP6_REN_MRD 0
//
// Transmit parameters of rebind message, refers to section-5.5 of rfc-3315.
//
#define DHCP6_REB_IRT 10
#define DHCP6_REB_MRC 0
#define DHCP6_REB_MRT 600
#define DHCP6_REB_MRD 0
//
// Transmit parameters of information request message, refers to section-5.5 of rfc-3315.
//
#define DHCP6_INF_MAX_DELAY 1
#define DHCP6_INF_IRT 1
#define DHCP6_INF_MRC 0
#define DHCP6_INF_MRT 120
#define DHCP6_INF_MRD 0
//
// Transmit parameters of release message, refers to section-5.5 of rfc-3315.
//
#define DHCP6_REL_IRT 1
#define DHCP6_REL_MRC 5
#define DHCP6_REL_MRT 0
#define DHCP6_REL_MRD 0
//
// Transmit parameters of decline message, refers to section-5.5 of rfc-3315.
//
#define DHCP6_DEC_IRT 1
#define DHCP6_DEC_MRC 5
#define DHCP6_DEC_MRT 0
#define DHCP6_DEC_MRD 0
#define DHCP6_PACKET_ALL 0
#define DHCP6_PACKET_STATEFUL 1
#define DHCP6_PACKET_STATELESS 2
#define DHCP6_BASE_PACKET_SIZE 1024
#define DHCP6_PORT_CLIENT 546
#define DHCP6_PORT_SERVER 547
#define DHCP6_INSTANCE_FROM_THIS(Instance) CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE)
#define DHCP6_SERVICE_FROM_THIS(Service) CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE)
extern EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress;
extern EFI_IPv6_ADDRESS mAllDhcpServersAddress;
extern EFI_DHCP6_PROTOCOL gDhcp6ProtocolTemplate;
//
// Enumeration of Dhcp6 message type, refers to section-5.3 of rfc-3315.
//
typedef enum {
Dhcp6MsgSolicit = 1,
Dhcp6MsgAdvertise = 2,
Dhcp6MsgRequest = 3,
Dhcp6MsgConfirm = 4,
Dhcp6MsgRenew = 5,
Dhcp6MsgRebind = 6,
Dhcp6MsgReply = 7,
Dhcp6MsgRelease = 8,
Dhcp6MsgDecline = 9,
Dhcp6MsgReconfigure = 10,
Dhcp6MsgInfoRequest = 11
} DHCP6_MSG_TYPE;
//
// Enumeration of option code in Dhcp6 packet, refers to section-24.3 of rfc-3315.
//
typedef enum {
Dhcp6OptClientId = 1,
Dhcp6OptServerId = 2,
Dhcp6OptIana = 3,
Dhcp6OptIata = 4,
Dhcp6OptIaAddr = 5,
Dhcp6OptRequestOption = 6,
Dhcp6OptPreference = 7,
Dhcp6OptElapsedTime = 8,
Dhcp6OptReplayMessage = 9,
Dhcp6OptAuthentication = 11,
Dhcp6OptServerUnicast = 12,
Dhcp6OptStatusCode = 13,
Dhcp6OptRapidCommit = 14,
Dhcp6OptUserClass = 15,
Dhcp6OptVendorClass = 16,
Dhcp6OptVendorInfo = 17,
Dhcp6OptInterfaceId = 18,
Dhcp6OptReconfigMessage = 19,
Dhcp6OptReconfigureAccept = 20
} DHCP6_OPT_CODE;
//
// Enumeration of status code recorded by IANA, refers to section-24.4 of rfc-3315.
//
typedef enum {
Dhcp6StsSuccess = 0,
Dhcp6StsUnspecFail = 1,
Dhcp6StsNoAddrsAvail = 2,
Dhcp6StsNoBinding = 3,
Dhcp6StsNotOnLink = 4,
Dhcp6StsUseMulticast = 5
} DHCP6_STS_CODE;
//
// Enumeration of Duid type recorded by IANA, refers to section-24.5 of rfc-3315.
//
typedef enum {
Dhcp6DuidTypeLlt = 1,
Dhcp6DuidTypeEn = 2,
Dhcp6DuidTypeLl = 3
} DHCP6_DUID_TYPE;
//
// Control block for each IA.
//
struct _DHCP6_IA_CB {
EFI_DHCP6_IA *Ia;
UINT32 T1;
UINT32 T2;
UINT32 AllExpireTime;
UINT32 LeaseTime;
};
//
// Control block for each transmitted message.
//
struct _DHCP6_TX_CB {
LIST_ENTRY Link;
UINT32 Xid;
EFI_DHCP6_PACKET *TxPacket;
EFI_DHCP6_RETRANSMISSION RetryCtl;
UINT32 RetryCnt;
UINT32 RetryExp;
UINT32 RetryLos;
UINT32 TickTime;
UINT16 *Elapsed;
};
//
// Control block for each info-request message.
//
struct _DHCP6_INF_CB {
LIST_ENTRY Link;
UINT32 Xid;
EFI_DHCP6_INFO_CALLBACK ReplyCallback;
VOID *CallbackContext;
EFI_EVENT TimeoutEvent;
};
//
// Control block for Dhcp6 instance, it's per configuration data.
//
struct _DHCP6_INSTANCE {
UINT32 Signature;
EFI_HANDLE Handle;
DHCP6_SERVICE *Service;
LIST_ENTRY Link;
EFI_DHCP6_PROTOCOL Dhcp6;
EFI_EVENT Timer;
EFI_DHCP6_CONFIG_DATA *Config;
EFI_DHCP6_IA *CacheIa;
DHCP6_IA_CB IaCb;
LIST_ENTRY TxList;
LIST_ENTRY InfList;
EFI_DHCP6_PACKET *AdSelect;
UINT8 AdPref;
EFI_IPv6_ADDRESS *Unicast;
EFI_STATUS UdpSts;
BOOLEAN InDestory;
BOOLEAN MediaPresent;
UINT64 StartTime;
};
//
// Control block for Dhcp6 service, it's per Nic handle.
//
struct _DHCP6_SERVICE {
UINT32 Signature;
EFI_HANDLE Controller;
EFI_HANDLE Image;
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
EFI_DHCP6_DUID *ClientId;
UDP_IO *UdpIo;
UINT32 Xid;
LIST_ENTRY Child;
UINTN NumOfChild;
BOOLEAN InDestory;
};
/**
Starts the DHCPv6 standard S.A.R.R. process.
The Start() function starts the DHCPv6 standard process. This function can
be called only when the state of Dhcp6 instance is in the Dhcp6Init state.
If the DHCP process completes successfully, the state of the Dhcp6 instance
will be transferred through Dhcp6Selecting and Dhcp6Requesting to the
Dhcp6Bound state.
Refer to rfc-3315 for precise state transitions during this process. At the
time when each event occurs in this process, the callback function that was set
by EFI_DHCP6_PROTOCOL.Configure() will be called and the user can take this
opportunity to control the process.
@param[in] This The pointer to Dhcp6 protocol.
@retval EFI_SUCCESS The DHCPv6 standard process has started, or it
completed when CompletionEvent was NULL.
@retval EFI_ACCESS_DENIED The EFI DHCPv6 Child instance hasn't been configured.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_TIMEOUT The DHCPv6 configuration process failed because no
response was received from the server within the
specified timeout value.
@retval EFI_ABORTED The user aborted the DHCPv6 process.
@retval EFI_ALREADY_STARTED Some other Dhcp6 instance already started the DHCPv6
standard process.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
EfiDhcp6Start (
IN EFI_DHCP6_PROTOCOL *This
);
/**
Stops the DHCPv6 standard S.A.R.R. process.
The Stop() function is used to stop the DHCPv6 standard process. After this
function is called successfully, the state of Dhcp6 instance is transferred
into the Dhcp6Init. EFI_DHCP6_PROTOCOL.Configure() needs to be called
before DHCPv6 standard process can be started again. This function can be
called when the Dhcp6 instance is in any state.
@param[in] This The pointer to the Dhcp6 protocol.
@retval EFI_SUCCESS The Dhcp6 instance is now in the Dhcp6Init state.
@retval EFI_INVALID_PARAMETER This is NULL.
**/
EFI_STATUS
EFIAPI
EfiDhcp6Stop (
IN EFI_DHCP6_PROTOCOL *This
);
/**
Returns the current operating mode data for the Dhcp6 instance.
The GetModeData() function returns the current operating mode and
cached data packet for the Dhcp6 instance.
@param[in] This The pointer to the Dhcp6 protocol.
@param[out] Dhcp6ModeData The pointer to the Dhcp6 mode data.
@param[out] Dhcp6ConfigData The pointer to the Dhcp6 configure data.
@retval EFI_SUCCESS The mode data was returned.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_ACCESS_DENIED The EFI DHCPv6 Protocol instance has not
been configured when Dhcp6ConfigData is
not NULL.
**/
EFI_STATUS
EFIAPI
EfiDhcp6GetModeData (
IN EFI_DHCP6_PROTOCOL *This,
OUT EFI_DHCP6_MODE_DATA *Dhcp6ModeData OPTIONAL,
OUT EFI_DHCP6_CONFIG_DATA *Dhcp6ConfigData OPTIONAL
);
/**
Initializes, changes, or resets the operational settings for the Dhcp6 instance.
The Configure() function is used to initialize or clean up the configuration
data of the Dhcp6 instance:
- When Dhcp6CfgData is not NULL and Configure() is called successfully, the
configuration data will be initialized in the Dhcp6 instance and the state
of the configured IA will be transferred into Dhcp6Init.
- When Dhcp6CfgData is NULL and Configure() is called successfully, the
configuration data will be cleaned up and no IA will be associated with
the Dhcp6 instance.
To update the configuration data for an Dhcp6 instance, the original data
must be cleaned up before setting the new configuration data.
@param[in] This The pointer to the Dhcp6 protocol
@param[in] Dhcp6CfgData The pointer to the EFI_DHCP6_CONFIG_DATA.
@retval EFI_SUCCESS The Dhcp6 is configured successfully with the
Dhcp6Init state, or cleaned up the original
configuration setting.
@retval EFI_ACCESS_DENIED The Dhcp6 instance has been already configured
when Dhcp6CfgData is not NULL.
The Dhcp6 instance has already started the
DHCPv6 S.A.R.R when Dhcp6CfgData is NULL.
@retval EFI_INVALID_PARAMETER Some of the parameter is invalid.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
EfiDhcp6Configure (
IN EFI_DHCP6_PROTOCOL *This,
IN EFI_DHCP6_CONFIG_DATA *Dhcp6CfgData OPTIONAL
);
/**
Request configuration information without the assignment of any
Ia addresses of the client.
The InfoRequest() function is used to request configuration information
without the assignment of any IPv6 address of the client. Client sends
out Information Request packet to obtain the required configuration
information, and DHCPv6 server responds with Reply packet containing
the information for the client. The received Reply packet will be passed
to the user by ReplyCallback function. If user returns EFI_NOT_READY from
ReplyCallback, the Dhcp6 instance will continue to receive other Reply
packets unless timeout according to the Retransmission parameter.
Otherwise, the Information Request exchange process will be finished
successfully if user returns EFI_SUCCESS from ReplyCallback.
@param[in] This The pointer to the Dhcp6 protocol.
@param[in] SendClientId If TRUE, the DHCPv6 protocol instance will build Client
Identifier option and include it into Information Request
packet. Otherwise, Client Identifier option will not be included.
@param[in] OptionRequest The pointer to the buffer of option request options.
@param[in] OptionCount The option number in the OptionList.
@param[in] OptionList The list of appended options.
@param[in] Retransmission The pointer to the retransmission of the message.
@param[in] TimeoutEvent The event of timeout.
@param[in] ReplyCallback The callback function when a reply was received.
@param[in] CallbackContext The pointer to the parameter passed to the callback.
@retval EFI_SUCCESS The DHCPv6 information request exchange process
completed when TimeoutEvent is NULL. Information
Request packet has been sent to DHCPv6 server when
TimeoutEvent is not NULL.
@retval EFI_NO_RESPONSE The DHCPv6 information request exchange process failed
because of no response, or not all requested-options
are responded to by DHCPv6 servers when Timeout happened.
@retval EFI_ABORTED The DHCPv6 information request exchange process was aborted
by the user.
@retval EFI_INVALID_PARAMETER Some parameter is NULL.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
EfiDhcp6InfoRequest (
IN EFI_DHCP6_PROTOCOL *This,
IN BOOLEAN SendClientId,
IN EFI_DHCP6_PACKET_OPTION *OptionRequest,
IN UINT32 OptionCount,
IN EFI_DHCP6_PACKET_OPTION *OptionList[] OPTIONAL,
IN EFI_DHCP6_RETRANSMISSION *Retransmission,
IN EFI_EVENT TimeoutEvent OPTIONAL,
IN EFI_DHCP6_INFO_CALLBACK ReplyCallback,
IN VOID *CallbackContext OPTIONAL
);
/**
Manually extend the valid and preferred lifetimes for the IPv6 addresses
of the configured IA and update other configuration parameters by sending
Renew or Rebind packet.
The RenewRebind() function is used to manually extend the valid and preferred
lifetimes for the IPv6 addresses of the configured IA and update other
configuration parameters by sending a Renew or Rebind packet.
- When RebindRequest is FALSE and the state of the configured IA is Dhcp6Bound,
it will send Renew packet to the previously DHCPv6 server and transfer the
state of the configured IA to Dhcp6Renewing. If valid Reply packet received,
the state transfers to Dhcp6Bound and the valid and preferred timer restarts.
If fails, the state transfers to Dhcp6Bound but the timer continues.
- When RebindRequest is TRUE and the state of the configured IA is Dhcp6Bound,
it will send a Rebind packet. If a valid Reply packet is received, the state transfers
to Dhcp6Bound, and the valid and preferred timer restarts. If it fails, the state
transfers to Dhcp6Init, and the IA can't be used.
@param[in] This The pointer to the Dhcp6 protocol.
@param[in] RebindRequest If TRUE, Rebind packet will be sent and enter Dhcp6Rebinding state.
Otherwise, Renew packet will be sent and enter Dhcp6Renewing state.
@retval EFI_SUCCESS The DHCPv6 renew/rebind exchange process
completed and at least one IPv6 address of the
configured IA was bound again when
EFI_DHCP6_CONFIG_DATA.IaInfoEvent was NULL.
The EFI DHCPv6 Protocol instance has sent Renew
or Rebind packet when
EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL.
@retval EFI_ACCESS_DENIED The Dhcp6 instance hasn't been configured, or the
state of the configured IA is not in Dhcp6Bound.
@retval EFI_ALREADY_STARTED The state of the configured IA has already entered
Dhcp6Renewing when RebindRequest is FALSE.
The state of the configured IA has already entered
Dhcp6Rebinding when RebindRequest is TRUE.
@retval EFI_ABORTED The DHCPv6 renew/rebind exchange process aborted
by user.
@retval EFI_NO_RESPONSE The DHCPv6 renew/rebind exchange process failed
because of no response.
@retval EFI_NO_MAPPING No IPv6 address has been bound to the configured
IA after the DHCPv6 renew/rebind exchange process.
@retval EFI_INVALID_PARAMETER Some parameter is NULL.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
EfiDhcp6RenewRebind (
IN EFI_DHCP6_PROTOCOL *This,
IN BOOLEAN RebindRequest
);
/**
Inform that one or more addresses assigned by a server are already
in use by another node.
The Decline() function is used to manually decline the assignment of
IPv6 addresses, which have been already used by another node. If all
IPv6 addresses of the configured IA are declined through this function,
the state of the IA will switch through Dhcp6Declining to Dhcp6Init.
Otherwise, the state of the IA will restore to Dhcp6Bound after the
declining process. The Decline() can only be called when the IA is in
Dhcp6Bound state. If the EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL,
this function is a blocking operation. It will return after the
declining process finishes, or aborted by user.
@param[in] This The pointer to the Dhcp6 protocol.
@param[in] AddressCount The number of declining addresses.
@param[in] Addresses The pointer to the buffer stored the declining
addresses.
@retval EFI_SUCCESS The DHCPv6 decline exchange process completed
when EFI_DHCP6_CONFIG_DATA.IaInfoEvent was NULL.
The Dhcp6 instance has sent Decline packet when
EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL.
@retval EFI_ACCESS_DENIED The Dhcp6 instance hasn't been configured, or the
state of the configured IA is not in Dhcp6Bound.
@retval EFI_ABORTED The DHCPv6 decline exchange process was aborted by the user.
@retval EFI_NOT_FOUND Any specified IPv6 address is not correlated with
the configured IA for this instance.
@retval EFI_INVALID_PARAMETER Some parameter is NULL.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
EfiDhcp6Decline (
IN EFI_DHCP6_PROTOCOL *This,
IN UINT32 AddressCount,
IN EFI_IPv6_ADDRESS *Addresses
);
/**
Release one or more addresses associated with the configured Ia
for the current instance.
The Release() function is used to manually release the one or more
IPv6 address. If AddressCount is zero, it will release all IPv6
addresses of the configured IA. If all IPv6 addresses of the IA are
released through this function, the state of the IA will switch
through Dhcp6Releasing to Dhcp6Init, otherwise, the state of the
IA will restore to Dhcp6Bound after the releasing process.
The Release() can only be called when the IA is in a Dhcp6Bound state.
If the EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL, the function is
a blocking operation. It will return after the releasing process
finishes, or aborted by user.
@param[in] This The pointer to the Dhcp6 protocol.
@param[in] AddressCount The number of releasing addresses.
@param[in] Addresses The pointer to the buffer stored the releasing
addresses.
@retval EFI_SUCCESS The DHCPv6 release exchange process has
completed when EFI_DHCP6_CONFIG_DATA.IaInfoEvent
is NULL. The Dhcp6 instance has sent Release
packet when EFI_DHCP6_CONFIG_DATA.IaInfoEvent
is not NULL.
@retval EFI_ACCESS_DENIED The Dhcp6 instance hasn't been configured, or the
state of the configured IA is not in Dhcp6Bound.
@retval EFI_ABORTED The DHCPv6 release exchange process was aborted by the user.
@retval EFI_NOT_FOUND Any specified IPv6 address is not correlated with
the configured IA for this instance.
@retval EFI_INVALID_PARAMETER Some parameter is NULL.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
EfiDhcp6Release (
IN EFI_DHCP6_PROTOCOL *This,
IN UINT32 AddressCount,
IN EFI_IPv6_ADDRESS *Addresses
);
/**
Parse the option data in the Dhcp6 packet.
The Parse() function is used to retrieve the option list in the DHCPv6 packet.
@param[in] This The pointer to the Dhcp6 protocol.
@param[in] Packet The pointer to the Dhcp6 packet.
@param[in, out] OptionCount The number of option in the packet.
@param[out] PacketOptionList The array of pointers to the each option in the packet.
@retval EFI_SUCCESS The packet was successfully parsed.
@retval EFI_INVALID_PARAMETER Some parameter is NULL.
@retval EFI_BUFFER_TOO_SMALL *OptionCount is smaller than the number of options
that were found in the Packet.
**/
EFI_STATUS
EFIAPI
EfiDhcp6Parse (
IN EFI_DHCP6_PROTOCOL *This,
IN EFI_DHCP6_PACKET *Packet,
IN OUT UINT32 *OptionCount,
OUT EFI_DHCP6_PACKET_OPTION *PacketOptionList[] OPTIONAL
);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,193 @@
/** @file
Dhcp6 internal functions declaration.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_DHCP6_IO_H__
#define __EFI_DHCP6_IO_H__
/**
Clean up the specific nodes in the retry list.
@param[in] Instance The pointer to the Dhcp6 instance.
@param[in] Scope The scope of cleanup nodes.
**/
VOID
Dhcp6CleanupRetry (
IN DHCP6_INSTANCE *Instance,
IN UINT32 Scope
);
/**
Clean up the session of the instance stateful exchange.
@param[in, out] Instance The pointer to the Dhcp6 instance.
@param[in] Status The return status from udp.
**/
VOID
Dhcp6CleanupSession (
IN OUT DHCP6_INSTANCE *Instance,
IN EFI_STATUS Status
);
/**
Create the solicit message and send it.
@param[in] Instance The pointer to Dhcp6 instance.
@retval EFI_SUCCESS Create and send the solicit message successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval Others Failed to send the solicit message.
**/
EFI_STATUS
Dhcp6SendSolicitMsg (
IN DHCP6_INSTANCE *Instance
);
/**
Create the request message and send it.
@param[in] Instance The pointer to the Dhcp6 instance.
@retval EFI_SUCCESS Create and send the request message successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_DEVICE_ERROR An unexpected error.
@retval Others Failed to send the request message.
**/
EFI_STATUS
Dhcp6SendRequestMsg (
IN DHCP6_INSTANCE *Instance
);
/**
Create the renew/rebind message and send it.
@param[in] Instance The pointer to the Dhcp6 instance.
@param[in] RebindRequest If TRUE, it is a Rebind type message.
Otherwise, it is a Renew type message.
@retval EFI_SUCCESS Create and send the renew/rebind message successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_DEVICE_ERROR An unexpected error.
@retval Others Failed to send the renew/rebind message.
**/
EFI_STATUS
Dhcp6SendRenewRebindMsg (
IN DHCP6_INSTANCE *Instance,
IN BOOLEAN RebindRequest
);
/**
Create the decline message and send it.
@param[in] Instance The pointer to the Dhcp6 instance.
@param[in] DecIa The pointer to the decline Ia.
@retval EFI_SUCCESS Create and send the decline message successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_DEVICE_ERROR An unexpected error.
@retval Others Failed to send the decline message.
**/
EFI_STATUS
Dhcp6SendDeclineMsg (
IN DHCP6_INSTANCE *Instance,
IN EFI_DHCP6_IA *DecIa
);
/**
Create the release message and send it.
@param[in] Instance The pointer to the Dhcp6 instance.
@param[in] RelIa The pointer to the release Ia.
@retval EFI_SUCCESS Create and send the release message successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_DEVICE_ERROR An unexpected error.
@retval Others Failed to send the release message.
**/
EFI_STATUS
Dhcp6SendReleaseMsg (
IN DHCP6_INSTANCE *Instance,
IN EFI_DHCP6_IA *RelIa
);
/**
Create the information request message and send it.
@param[in] Instance The pointer to the Dhcp6 instance.
@param[in] InfCb The pointer to the information request control block.
@param[in] SendClientId If TRUE, the client identifier option will be included in
information request message. Otherwise, the client identifier
option will not be included.
@param[in] OptionRequest The pointer to the option request option.
@param[in] OptionCount The number options in the OptionList.
@param[in] OptionList The array pointers to the appended options.
@param[in] Retransmission The pointer to the retransmission control.
@retval EFI_SUCCESS Create and send the info-request message successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval Others Failed to send the info-request message.
**/
EFI_STATUS
Dhcp6SendInfoRequestMsg (
IN DHCP6_INSTANCE *Instance,
IN DHCP6_INF_CB *InfCb,
IN BOOLEAN SendClientId,
IN EFI_DHCP6_PACKET_OPTION *OptionRequest,
IN UINT32 OptionCount,
IN EFI_DHCP6_PACKET_OPTION *OptionList[],
IN EFI_DHCP6_RETRANSMISSION *Retransmission
);
/**
The receive callback function for the Dhcp6 exchange process.
@param[in] Udp6Wrap The pointer to the received net buffer.
@param[in] EndPoint The pointer to the udp end point.
@param[in] IoStatus The return status from udp io.
@param[in] Context The opaque parameter to the function.
**/
VOID
EFIAPI
Dhcp6ReceivePacket (
IN NET_BUF *Udp6Wrap,
IN UDP_END_POINT *EndPoint,
IN EFI_STATUS IoStatus,
IN VOID *Context
);
/**
The timer routine of the Dhcp6 instance for each second.
@param[in] Event The timer event.
@param[in] Context The opaque parameter to the function.
**/
VOID
EFIAPI
Dhcp6OnTimerTick (
IN EFI_EVENT Event,
IN VOID *Context
);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,340 @@
/** @file
Dhcp6 support functions declaration.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_DHCP6_UTILITY_H__
#define __EFI_DHCP6_UTILITY_H__
#define DHCP6_10_BIT_MASK 0x3ff
/**
Generate client Duid in the format of Duid-llt.
@param[in] Mode The pointer to the mode of SNP.
@retval NULL if failed to generate client Id.
@retval Others The pointer to the new client id.
**/
EFI_DHCP6_DUID *
Dhcp6GenerateClientId (
IN EFI_SIMPLE_NETWORK_MODE *Mode
);
/**
Copy the Dhcp6 configure data.
@param[in] DstCfg The pointer to the destination configure data.
@param[in] SorCfg The pointer to the source configure data.
@retval EFI_SUCCESS Copy the content from SorCfg from DstCfg successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
**/
EFI_STATUS
Dhcp6CopyConfigData (
IN EFI_DHCP6_CONFIG_DATA *DstCfg,
IN EFI_DHCP6_CONFIG_DATA *SorCfg
);
/**
Clean up the configure data.
@param[in, out] CfgData The pointer to the configure data.
**/
VOID
Dhcp6CleanupConfigData (
IN OUT EFI_DHCP6_CONFIG_DATA *CfgData
);
/**
Clean up the mode data.
@param[in, out] ModeData The pointer to the mode data.
**/
VOID
Dhcp6CleanupModeData (
IN OUT EFI_DHCP6_MODE_DATA *ModeData
);
/**
Calculate the expire time by the algorithm defined in rfc.
@param[in] Base The base value of the time.
@param[in] IsFirstRt If TRUE, it is the first time to calculate expire time.
@param[in] NeedSigned If TRUE, the the signed factor is needed.
@return Expire The calculated result for the new expire time.
**/
UINT32
Dhcp6CalculateExpireTime (
IN UINT32 Base,
IN BOOLEAN IsFirstRt,
IN BOOLEAN NeedSigned
);
/**
Calculate the lease time by the algorithm defined in rfc.
@param[in] IaCb The pointer to the Ia control block.
**/
VOID
Dhcp6CalculateLeaseTime (
IN DHCP6_IA_CB *IaCb
);
/**
Check whether the addresses are all included by the configured Ia.
@param[in] Ia The pointer to the Ia.
@param[in] AddressCount The number of addresses.
@param[in] Addresses The pointer to the addresses buffer.
@retval EFI_SUCCESS The addresses are all included by the configured IA.
@retval EFI_NOT_FOUND The addresses are not included by the configured IA.
**/
EFI_STATUS
Dhcp6CheckAddress (
IN EFI_DHCP6_IA *Ia,
IN UINT32 AddressCount,
IN EFI_IPv6_ADDRESS *Addresses
);
/**
Deprive the addresses from current Ia, and generate another eliminated Ia.
@param[in] Ia The pointer to the Ia.
@param[in] AddressCount The number of addresses.
@param[in] Addresses The pointer to the addresses buffer.
@retval NULL If failed to generate the deprived Ia.
@retval others The pointer to the deprived Ia.
**/
EFI_DHCP6_IA *
Dhcp6DepriveAddress (
IN EFI_DHCP6_IA *Ia,
IN UINT32 AddressCount,
IN EFI_IPv6_ADDRESS *Addresses
);
/**
The dummy ext buffer free callback routine.
@param[in] Arg The pointer to the parameter.
**/
VOID
EFIAPI
Dhcp6DummyExtFree (
IN VOID *Arg
);
/**
The callback routine once message transmitted.
@param[in] Udp6Wrap The pointer to the received net buffer.
@param[in] EndPoint The pointer to the udp end point.
@param[in] IoStatus The return status from udp io.
@param[in] Context The opaque parameter to the function.
**/
VOID
EFIAPI
Dhcp6OnTransmitted (
IN NET_BUF *Wrap,
IN UDP_END_POINT *EndPoint,
IN EFI_STATUS IoStatus,
IN VOID *Context
);
/**
Append the appointed option to the buf, and move the buf to the end.
@param[in, out] Buf The pointer to buffer.
@param[in] OptType The option type.
@param[in] OptLen The lenght of option content.s
@param[in] Data The pointer to the option content.
@return Buf The position to append the next option.
**/
UINT8 *
Dhcp6AppendOption (
IN OUT UINT8 *Buf,
IN UINT16 OptType,
IN UINT16 OptLen,
IN UINT8 *Data
);
/**
Append the Ia option to Buf, and move Buf to the end.
@param[in, out] Buf The pointer to the position to append.
@param[in] Ia The pointer to the Ia.
@param[in] T1 The time of T1.
@param[in] T2 The time of T2.
@return Buf The position to append the next Ia option.
**/
UINT8 *
Dhcp6AppendIaOption (
IN OUT UINT8 *Buf,
IN EFI_DHCP6_IA *Ia,
IN UINT32 T1,
IN UINT32 T2
);
/**
Append the appointed Elapsed time option to Buf, and move Buf to the end.
@param[in, out] Buf The pointer to the position to append.
@param[in] Instance The pointer to the Dhcp6 instance.
@param[out] Elapsed The pointer to the elapsed time value in
the generated packet.
@return Buf The position to append the next Ia option.
**/
UINT8 *
Dhcp6AppendETOption (
IN OUT UINT8 *Buf,
IN DHCP6_INSTANCE *Instance,
OUT UINT16 **Elapsed
);
/**
Set the elapsed time based on the given instance and the pointer to the
elapsed time option.
@param[in] Elapsed The pointer to the position to append.
@param[in] Instance The pointer to the Dhcp6 instance.
**/
VOID
SetElapsedTime (
IN UINT16 *Elapsed,
IN DHCP6_INSTANCE *Instance
);
/**
Seek the address of the first byte of the option header.
@param[in] Buf The pointer to buffer.
@param[in] SeekLen The length to seek.
@param[in] OptType The option type.
@retval NULL If failed to seek the option.
@retval others The position to the option.
**/
UINT8 *
Dhcp6SeekOption (
IN UINT8 *Buf,
IN UINT32 SeekLen,
IN UINT16 OptType
);
/**
Seek the address of the first byte of the Ia option header.
@param[in] Buf The pointer to the buffer.
@param[in] SeekLen The length to seek.
@param[in] IaDesc The pointer to the Ia descriptor.
@retval NULL If failed to seek the Ia option.
@retval others The position to the Ia option.
**/
UINT8 *
Dhcp6SeekIaOption (
IN UINT8 *Buf,
IN UINT32 SeekLen,
IN EFI_DHCP6_IA_DESCRIPTOR *IaDesc
);
/**
Parse the address option and update the address info.
@param[in] IaInnerOpt The pointer to the buffer.
@param[in] IaInnerLen The length to parse.
@param[out] AddrNum The number of addresses.
@param[in, out] AddrBuf The pointer to the address buffer.
**/
VOID
Dhcp6ParseAddrOption (
IN UINT8 *IaInnerOpt,
IN UINT16 IaInnerLen,
OUT UINT32 *AddrNum,
IN OUT EFI_DHCP6_IA_ADDRESS *AddrBuf
);
/**
Create a control blcok for the Ia according to the corresponding options.
@param[in] Instance The pointer to DHCP6 Instance.
@param[in] IaInnerOpt The pointer to the inner options in the Ia option.
@param[in] IaInnerLen The length of all the inner options in the Ia option.
@param[in] T1 T1 time in the Ia option.
@param[in] T2 T2 time in the Ia option.
@retval EFI_NOT_FOUND No valid IA option is found.
@retval EFI_SUCCESS Create an IA control block successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
**/
EFI_STATUS
Dhcp6GenerateIaCb (
IN DHCP6_INSTANCE *Instance,
IN UINT8 *IaInnerOpt,
IN UINT16 IaInnerLen,
IN UINT32 T1,
IN UINT32 T2
);
/**
Cache the current IA configuration information.
@param[in] Instance The pointer to DHCP6 Instance.
@retval EFI_SUCCESS Cache the current IA successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
**/
EFI_STATUS
Dhcp6CacheIa (
IN DHCP6_INSTANCE *Instance
);
/**
Append CacheIa to the currrent IA. Meanwhile, clear CacheIa.ValidLifetime to 0.
@param[in] Instance The pointer to DHCP6 instance.
**/
VOID
Dhcp6AppendCacheIa (
IN DHCP6_INSTANCE *Instance
);
#endif

View File

@@ -0,0 +1,313 @@
/** @file
Implementation of EFI_COMPONENT_NAME_PROTOCOL and
EFI_COMPONENT_NAME2_PROTOCOL protocol.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ip6Impl.h"
//
// EFI Component Name Functions
//
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Ip6ComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Ip6ComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI Component Name Protocol.
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIp6ComponentName = {
Ip6ComponentNameGetDriverName,
Ip6ComponentNameGetControllerName,
"eng"
};
//
// EFI Component Name 2 Protocol.
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIp6ComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Ip6ComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Ip6ComponentNameGetControllerName,
"en"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIp6DriverNameTable[] = {
{
"eng;en",
L"IP6 Network Service Driver"
},
{
NULL,
NULL
}
};
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Ip6ComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mIp6DriverNameTable,
DriverName,
(BOOLEAN) (This == &gIp6ComponentName)
);
}
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is being managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Ip6ComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
return EFI_UNSUPPORTED;
}

View File

@@ -0,0 +1,796 @@
/** @file
The implementation of common functions shared by IP6 driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ip6Impl.h"
/**
Build a array of EFI_IP6_ADDRESS_INFO to be returned to the caller. The number
of EFI_IP6_ADDRESS_INFO is also returned. If AddressList is NULL,
only the address count is returned.
@param[in] IpSb The IP6 service binding instance.
@param[out] AddressCount The number of returned addresses.
@param[out] AddressList The pointer to the array of EFI_IP6_ADDRESS_INFO.
This is an optional parameter.
@retval EFI_SUCCESS The address array successfully built.
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the address info.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
Ip6BuildEfiAddressList (
IN IP6_SERVICE *IpSb,
OUT UINT32 *AddressCount,
OUT EFI_IP6_ADDRESS_INFO **AddressList OPTIONAL
)
{
UINT32 Count;
LIST_ENTRY *Entry;
EFI_IP6_ADDRESS_INFO *EfiAddrInfo;
IP6_ADDRESS_INFO *AddrInfo;
if (AddressCount == NULL) {
return EFI_INVALID_PARAMETER;
}
if (IpSb->LinkLocalOk) {
Count = 1 + IpSb->DefaultInterface->AddressCount;
} else {
Count = 0;
}
*AddressCount = Count;
if ((AddressList == NULL) || (Count == 0)) {
return EFI_SUCCESS;
}
if (*AddressList == NULL) {
*AddressList = AllocatePool (sizeof (EFI_IP6_ADDRESS_INFO) * Count);
if (*AddressList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
}
EfiAddrInfo = *AddressList;
IP6_COPY_ADDRESS (&EfiAddrInfo->Address, &IpSb->LinkLocalAddr);
EfiAddrInfo->PrefixLength = IP6_LINK_LOCAL_PREFIX_LENGTH;
EfiAddrInfo++;
Count = 1;
NET_LIST_FOR_EACH (Entry, &IpSb->DefaultInterface->AddressList) {
AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
IP6_COPY_ADDRESS (&EfiAddrInfo->Address, &AddrInfo->Address);
EfiAddrInfo->PrefixLength = AddrInfo->PrefixLength;
EfiAddrInfo++;
Count++;
}
ASSERT (Count == *AddressCount);
return EFI_SUCCESS;
}
/**
Generate the multicast addresses identify the group of all IPv6 nodes or IPv6
routers defined in RFC4291.
All Nodes Addresses: FF01::1, FF02::1.
All Router Addresses: FF01::2, FF02::2, FF05::2.
@param[in] Router If TRUE, generate all routers addresses,
else generate all node addresses.
@param[in] Scope interface-local(1), link-local(2), or site-local(5)
@param[out] Ip6Addr The generated multicast address.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
@retval EFI_SUCCESS The address is generated.
**/
EFI_STATUS
Ip6SetToAllNodeMulticast (
IN BOOLEAN Router,
IN UINT8 Scope,
OUT EFI_IPv6_ADDRESS *Ip6Addr
)
{
if (Ip6Addr == NULL) {
return EFI_INVALID_PARAMETER;
}
if (!Router && Scope == IP6_SITE_LOCAL_SCOPE) {
return EFI_INVALID_PARAMETER;
}
ZeroMem (Ip6Addr, sizeof (EFI_IPv6_ADDRESS));
Ip6Addr->Addr[0] = 0xFF;
Ip6Addr->Addr[1] = Scope;
if (!Router) {
Ip6Addr->Addr[15] = 0x1;
} else {
Ip6Addr->Addr[15] = 0x2;
}
return EFI_SUCCESS;
}
/**
This function converts MAC address to 64 bits interface ID according to RFC4291
and returns the interface ID. Currently only 48-bit MAC address is supported by
this function.
@param[in, out] IpSb The IP6 service binding instance.
@retval NULL The operation fails.
@return Pointer to the generated interface ID.
**/
UINT8 *
Ip6CreateInterfaceID (
IN OUT IP6_SERVICE *IpSb
)
{
UINT8 InterfaceId[8];
UINT8 Byte;
EFI_MAC_ADDRESS *MacAddr;
UINT32 AddrLen;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
AddrLen = IpSb->SnpMode.HwAddressSize;
//
// Currently only IEEE 802 48-bit MACs are supported to create link local address.
//
if (AddrLen != IP6_MAC_LEN || IpSb->InterfaceIdLen != IP6_IF_ID_LEN) {
return NULL;
}
MacAddr = &IpSb->SnpMode.CurrentAddress;
//
// Convert MAC address to 64 bits interface ID according to Appendix A of RFC4291:
// 1. Insert 0xFFFE to the middle
// 2. Invert the universal/local bit - bit 6 in network order
//
CopyMem (InterfaceId, MacAddr, 3);
InterfaceId[3] = 0xFF;
InterfaceId[4] = 0xFE;
CopyMem (&InterfaceId[5], &MacAddr->Addr[3], 3);
Byte = (UINT8) (InterfaceId[0] & IP6_U_BIT);
if (Byte == IP6_U_BIT) {
InterfaceId[0] &= ~IP6_U_BIT;
} else {
InterfaceId[0] |= IP6_U_BIT;
}
//
// Return the interface ID.
//
return AllocateCopyPool (IpSb->InterfaceIdLen, InterfaceId);
}
/**
This function creates link-local address from interface identifier. The
interface identifier is normally created from MAC address. It might be manually
configured by administrator if the link-local address created from MAC address
is a duplicate address.
@param[in, out] IpSb The IP6 service binding instance.
@retval NULL If the operation fails.
@return The generated Link Local address, in network order.
**/
EFI_IPv6_ADDRESS *
Ip6CreateLinkLocalAddr (
IN OUT IP6_SERVICE *IpSb
)
{
EFI_IPv6_ADDRESS *Ip6Addr;
EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
UINTN DataSize;
EFI_IP6_CONFIG_INTERFACE_ID InterfaceId;
EFI_STATUS Status;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
if (IpSb->InterfaceId != NULL) {
FreePool (IpSb->InterfaceId);
}
//
// Get the interface id if it is manully configured.
//
Ip6Config = &IpSb->Ip6ConfigInstance.Ip6Config;
DataSize = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);
ZeroMem (&InterfaceId, DataSize);
Status = Ip6Config->GetData (
Ip6Config,
Ip6ConfigDataTypeAltInterfaceId,
&DataSize,
&InterfaceId
);
if (Status == EFI_NOT_FOUND) {
//
// Since the interface id is not configured, generate the interface id from
// MAC address.
//
IpSb->InterfaceId = Ip6CreateInterfaceID (IpSb);
if (IpSb->InterfaceId == NULL) {
return NULL;
}
CopyMem (&InterfaceId, IpSb->InterfaceId, IpSb->InterfaceIdLen);
//
// Record the interface id.
//
Status = Ip6Config->SetData (
Ip6Config,
Ip6ConfigDataTypeAltInterfaceId,
DataSize,
&InterfaceId
);
if (EFI_ERROR (Status)) {
FreePool (IpSb->InterfaceId);
IpSb->InterfaceId = NULL;
return NULL;
}
} else if (!EFI_ERROR (Status)) {
IpSb->InterfaceId = AllocateCopyPool (DataSize, &InterfaceId);
if (IpSb->InterfaceId == NULL) {
return NULL;
}
} else {
return NULL;
}
//
// Append FE80::/64 to the left of IPv6 address then return.
//
Ip6Addr = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
if (Ip6Addr == NULL) {
FreePool (IpSb->InterfaceId);
IpSb->InterfaceId = NULL;
return NULL;
}
CopyMem (&Ip6Addr->Addr[8], IpSb->InterfaceId, IpSb->InterfaceIdLen);
Ip6Addr->Addr[1] = 0x80;
Ip6Addr->Addr[0] = 0xFE;
return Ip6Addr;
}
/**
Compute the solicited-node multicast address for an unicast or anycast address,
by taking the low-order 24 bits of this address, and appending those bits to
the prefix FF02:0:0:0:0:1:FF00::/104.
@param[in] Ip6Addr The unicast or anycast address, in network order.
@param[out] MulticastAddr The generated solicited-node multicast address,
in network order.
**/
VOID
Ip6CreateSNMulticastAddr (
IN EFI_IPv6_ADDRESS *Ip6Addr,
OUT EFI_IPv6_ADDRESS *MulticastAddr
)
{
ASSERT (Ip6Addr != NULL && MulticastAddr != NULL);
ZeroMem (MulticastAddr, sizeof (EFI_IPv6_ADDRESS));
MulticastAddr->Addr[0] = 0xFF;
MulticastAddr->Addr[1] = 0x02;
MulticastAddr->Addr[11] = 0x1;
MulticastAddr->Addr[12] = 0xFF;
CopyMem (&MulticastAddr->Addr[13], &Ip6Addr->Addr[13], 3);
}
/**
Insert a node IP6_ADDRESS_INFO to an IP6 interface.
@param[in, out] IpIf Points to an IP6 interface.
@param[in] AddrInfo Points to IP6_ADDRESS_INFO
**/
VOID
Ip6AddAddr (
IN OUT IP6_INTERFACE *IpIf,
IN IP6_ADDRESS_INFO *AddrInfo
)
{
InsertHeadList (&IpIf->AddressList, &AddrInfo->Link);
IpIf->AddressCount++;
}
/**
Destroy the IP instance if its StationAddress is removed. It is the help function
for Ip6RemoveAddr().
@param[in, out] IpSb Points to an IP6 service binding instance.
@param[in] Address The to be removed address
**/
VOID
Ip6DestroyInstanceByAddress (
IN OUT IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Address
)
{
BOOLEAN OneDestroyed;
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
LIST_ENTRY *Entry;
IP6_PROTOCOL *Instance;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
ServiceBinding = &IpSb->ServiceBinding;
//
// Upper layer IP protocol consumers may have tight relationship between several
// IP protocol instances, in other words, calling ServiceBinding->DestroyChild to
// destroy one IP child may cause other related IP children destroyed too. This
// will probably leave hole in the children list when we iterate it. So everytime
// we just destroy one child then back to the start point to iterate the list.
//
do {
OneDestroyed = FALSE;
NET_LIST_FOR_EACH (Entry, &IpSb->Children) {
Instance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);
if ((Instance->State == IP6_STATE_CONFIGED) && EFI_IP6_EQUAL (&Instance->ConfigData.StationAddress, Address)) {
ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
OneDestroyed = TRUE;
break;
}
}
} while (OneDestroyed);
}
/**
Remove the IPv6 address from the address list node points to IP6_ADDRESS_INFO.
This function removes the matching IPv6 addresses from the address list and
adjusts the address count of the address list. If IpSb is not NULL, this function
calls Ip6LeaveGroup to see whether it should call Mnp->Groups() to remove the
its solicited-node multicast MAC address from the filter list and sends out
a Multicast Listener Done. If Prefix is NULL, all address in the address list
will be removed. If Prefix is not NULL, the address that matching the Prefix
with PrefixLength in the address list will be removed.
@param[in] IpSb NULL or points to IP6 service binding instance.
@param[in, out] AddressList Address list array.
@param[in, out] AddressCount The count of addresses in address list array.
@param[in] Prefix NULL or an IPv6 address prefix.
@param[in] PrefixLength The length of Prefix.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_FOUND The address matching the Prefix with PrefixLength
cannot be found in the address list.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
Ip6RemoveAddr (
IN IP6_SERVICE *IpSb OPTIONAL,
IN OUT LIST_ENTRY *AddressList,
IN OUT UINT32 *AddressCount,
IN EFI_IPv6_ADDRESS *Prefix OPTIONAL,
IN UINT8 PrefixLength
)
{
EFI_STATUS Status;
LIST_ENTRY *Entry;
LIST_ENTRY *Next;
IP6_ADDRESS_INFO *AddrInfo;
EFI_IPv6_ADDRESS SnMCastAddr;
if (IsListEmpty (AddressList) || *AddressCount < 1 || PrefixLength > IP6_PREFIX_NUM) {
return EFI_INVALID_PARAMETER;
}
Status = EFI_NOT_FOUND;
NET_LIST_FOR_EACH_SAFE (Entry, Next, AddressList) {
AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
if (Prefix == NULL ||
(PrefixLength == 128 && EFI_IP6_EQUAL (Prefix, &AddrInfo->Address)) ||
(PrefixLength == AddrInfo->PrefixLength && NetIp6IsNetEqual (Prefix, &AddrInfo->Address, PrefixLength))
) {
if (IpSb != NULL) {
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
Ip6CreateSNMulticastAddr (&AddrInfo->Address, &SnMCastAddr);
Ip6LeaveGroup (IpSb, &SnMCastAddr);
//
// Destroy any instance who is using the dying address as the source address.
//
Ip6DestroyInstanceByAddress (IpSb, &AddrInfo->Address);
}
RemoveEntryList (Entry);
FreePool (AddrInfo);
(*AddressCount)--;
Status = EFI_SUCCESS;
}
}
return Status;
}
/**
Check whether the incoming Ipv6 address is a solicited-node multicast address.
@param[in] Ip6 Ip6 address, in network order.
@retval TRUE Yes, solicited-node multicast address
@retval FALSE No
**/
BOOLEAN
Ip6IsSNMulticastAddr (
IN EFI_IPv6_ADDRESS *Ip6
)
{
EFI_IPv6_ADDRESS Sn;
BOOLEAN Flag;
Ip6CreateSNMulticastAddr (Ip6, &Sn);
Flag = FALSE;
if (CompareMem (Sn.Addr, Ip6->Addr, 13) == 0) {
Flag = TRUE;
}
return Flag;
}
/**
Check whether the incoming IPv6 address is one of the maintained addresses in
the IP6 service binding instance.
@param[in] IpSb Points to a IP6 service binding instance.
@param[in] Address The IP6 address to be checked.
@param[out] Interface If not NULL, output the IP6 interface which
maintains the Address.
@param[out] AddressInfo If not NULL, output the IP6 address information
of the Address.
@retval TRUE Yes, it is one of the maintained address.
@retval FALSE No, it is not one of the maintained address.
**/
BOOLEAN
Ip6IsOneOfSetAddress (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Address,
OUT IP6_INTERFACE **Interface OPTIONAL,
OUT IP6_ADDRESS_INFO **AddressInfo OPTIONAL
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *Entry2;
IP6_INTERFACE *IpIf;
IP6_ADDRESS_INFO *TmpAddressInfo;
//
// Check link-local address first
//
if (IpSb->LinkLocalOk && EFI_IP6_EQUAL (&IpSb->LinkLocalAddr, Address)) {
if (Interface != NULL) {
*Interface = IpSb->DefaultInterface;
}
if (AddressInfo != NULL) {
*AddressInfo = NULL;
}
return TRUE;
}
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {
TmpAddressInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
if (EFI_IP6_EQUAL (&TmpAddressInfo->Address, Address)) {
if (Interface != NULL) {
*Interface = IpIf;
}
if (AddressInfo != NULL) {
*AddressInfo = TmpAddressInfo;
}
return TRUE;
}
}
}
return FALSE;
}
/**
Check whether the incoming MAC address is valid.
@param[in] IpSb Points to a IP6 service binding instance.
@param[in] LinkAddress The MAC address.
@retval TRUE Yes, it is valid.
@retval FALSE No, it is not valid.
**/
BOOLEAN
Ip6IsValidLinkAddress (
IN IP6_SERVICE *IpSb,
IN EFI_MAC_ADDRESS *LinkAddress
)
{
UINT32 Index;
//
// TODO: might be updated later to be more acceptable.
//
for (Index = IpSb->SnpMode.HwAddressSize; Index < sizeof (EFI_MAC_ADDRESS); Index++) {
if (LinkAddress->Addr[Index] != 0) {
return FALSE;
}
}
return TRUE;
}
/**
Copy the PrefixLength bits from Src to Dest.
@param[out] Dest A pointer to the buffer to copy to.
@param[in] Src A pointer to the buffer to copy from.
@param[in] PrefixLength The number of bits to copy.
**/
VOID
Ip6CopyAddressByPrefix (
OUT EFI_IPv6_ADDRESS *Dest,
IN EFI_IPv6_ADDRESS *Src,
IN UINT8 PrefixLength
)
{
UINT8 Byte;
UINT8 Bit;
UINT8 Mask;
ASSERT (Dest != NULL && Src != NULL);
ASSERT (PrefixLength < IP6_PREFIX_NUM);
Byte = (UINT8) (PrefixLength / 8);
Bit = (UINT8) (PrefixLength % 8);
ZeroMem (Dest, sizeof (EFI_IPv6_ADDRESS));
CopyMem (Dest, Src, Byte);
if (Bit > 0) {
Mask = (UINT8) (0xFF << (8 - Bit));
ASSERT (Byte < 16);
Dest->Addr[Byte] = (UINT8) (Src->Addr[Byte] & Mask);
}
}
/**
Get the MAC address for a multicast IP address. Call
Mnp's McastIpToMac to find the MAC address instead of
hard-coding the NIC to be Ethernet.
@param[in] Mnp The Mnp instance to get the MAC address.
@param[in] Multicast The multicast IP address to translate.
@param[out] Mac The buffer to hold the translated address.
@retval EFI_SUCCESS The multicast IP successfully
translated to a multicast MAC address.
@retval Other The address is not converted because an error occurred.
**/
EFI_STATUS
Ip6GetMulticastMac (
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
IN EFI_IPv6_ADDRESS *Multicast,
OUT EFI_MAC_ADDRESS *Mac
)
{
EFI_IP_ADDRESS EfiIp;
IP6_COPY_ADDRESS (&EfiIp.v6, Multicast);
return Mnp->McastIpToMac (Mnp, TRUE, &EfiIp, Mac);
}
/**
Set the Ip6 variable data.
@param[in] IpSb Points to an IP6 service binding instance.
@retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.
@retval other Set variable failed.
**/
EFI_STATUS
Ip6SetVariableData (
IN IP6_SERVICE *IpSb
)
{
UINT32 NumConfiguredInstance;
LIST_ENTRY *Entry;
UINTN VariableDataSize;
EFI_IP6_VARIABLE_DATA *Ip6VariableData;
EFI_IP6_ADDRESS_PAIR *Ip6AddressPair;
IP6_PROTOCOL *IpInstance;
CHAR16 *NewMacString;
EFI_STATUS Status;
NumConfiguredInstance = 0;
//
// Go through the children list to count the configured children.
//
NET_LIST_FOR_EACH (Entry, &IpSb->Children) {
IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);
if (IpInstance->State == IP6_STATE_CONFIGED) {
NumConfiguredInstance++;
}
}
//
// Calculate the size of the Ip6VariableData. As there may be no IP child,
// we should add extra buffer for the address paris only if the number of configured
// children is more than 1.
//
VariableDataSize = sizeof (EFI_IP6_VARIABLE_DATA);
if (NumConfiguredInstance > 1) {
VariableDataSize += sizeof (EFI_IP6_ADDRESS_PAIR) * (NumConfiguredInstance - 1);
}
Ip6VariableData = AllocatePool (VariableDataSize);
if (Ip6VariableData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Ip6VariableData->DriverHandle = IpSb->Image;
Ip6VariableData->AddressCount = NumConfiguredInstance;
Ip6AddressPair = &Ip6VariableData->AddressPairs[0];
//
// Go through the children list to fill the configured children's address pairs.
//
NET_LIST_FOR_EACH (Entry, &IpSb->Children) {
IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);
if (IpInstance->State == IP6_STATE_CONFIGED) {
Ip6AddressPair->InstanceHandle = IpInstance->Handle;
Ip6AddressPair->PrefixLength = IpInstance->PrefixLength;
IP6_COPY_ADDRESS (&Ip6AddressPair->Ip6Address, &IpInstance->ConfigData.StationAddress);
Ip6AddressPair++;
}
}
//
// Get the mac string.
//
Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &NewMacString);
if (EFI_ERROR (Status)) {
goto Exit;
}
if (IpSb->MacString != NULL) {
//
// The variable is set already, we're going to update it.
//
if (StrCmp (IpSb->MacString, NewMacString) != 0) {
//
// The mac address is changed, delete the previous variable first.
//
gRT->SetVariable (
IpSb->MacString,
&gEfiIp6ServiceBindingProtocolGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS,
0,
NULL
);
}
FreePool (IpSb->MacString);
}
IpSb->MacString = NewMacString;
Status = gRT->SetVariable (
IpSb->MacString,
&gEfiIp6ServiceBindingProtocolGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS,
VariableDataSize,
(VOID *) Ip6VariableData
);
Exit:
FreePool (Ip6VariableData);
return Status;
}
/**
Clear the variable and free the resource.
@param[in] IpSb Ip6 service binding instance.
**/
VOID
Ip6ClearVariableData (
IN IP6_SERVICE *IpSb
)
{
ASSERT (IpSb->MacString != NULL);
gRT->SetVariable (
IpSb->MacString,
&gEfiIp6ServiceBindingProtocolGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS,
0,
NULL
);
FreePool (IpSb->MacString);
IpSb->MacString = NULL;
}
/**
Convert the multibyte field in IP header's byter order.
In spite of its name, it can also be used to convert from
host to network byte order.
@param[in, out] Head The IP head to convert.
@return Point to the converted IP head.
**/
EFI_IP6_HEADER *
Ip6NtohHead (
IN OUT EFI_IP6_HEADER *Head
)
{
Head->FlowLabelL = NTOHS (Head->FlowLabelL);
Head->PayloadLength = NTOHS (Head->PayloadLength);
return Head;
}

View File

@@ -0,0 +1,338 @@
/** @file
Common definition and functions for IP6 driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6_COMMON_H__
#define __EFI_IP6_COMMON_H__
#define IP6_LINK_EQUAL(Mac1, Mac2) (CompareMem ((Mac1), (Mac2), sizeof (EFI_MAC_ADDRESS)) == 0)
//
// Convert the Microsecond to second. IP transmit/receive time is
// in the unit of microsecond. IP ticks once per second.
//
#define IP6_US_TO_SEC(Us) (((Us) + 999999) / 1000000)
#define IP6_ETHER_PROTO 0x86DD
#define IP6_MAC_LEN 6
#define IP6_IF_ID_LEN 8
#define IP6_INTERFACE_LOCAL_SCOPE 1
#define IP6_LINK_LOCAL_SCOPE 2
#define IP6_SITE_LOCAL_SCOPE 5
#define IP6_INFINIT_LIFETIME 0xFFFFFFFF
#define IP6_HOP_LIMIT 255
//
// Make it to 64 since all 54 bits are zero.
//
#define IP6_LINK_LOCAL_PREFIX_LENGTH 64
#define IP6_TIMER_INTERVAL_IN_MS 100
#define IP6_ONE_SECOND_IN_MS 1000
//
// The packet is received as link level broadcast/multicast/promiscuous.
//
#define IP6_LINK_BROADCAST 0x00000001
#define IP6_LINK_MULTICAST 0x00000002
#define IP6_LINK_PROMISC 0x00000004
#define IP6_U_BIT 0x02
typedef enum {
Ip6Promiscuous = 1,
Ip6Unicast,
Ip6Multicast,
Ip6AnyCast
} IP6_ADDRESS_TYPE;
typedef struct _IP6_INTERFACE IP6_INTERFACE;
typedef struct _IP6_PROTOCOL IP6_PROTOCOL;
typedef struct _IP6_SERVICE IP6_SERVICE;
typedef struct _IP6_ADDRESS_INFO IP6_ADDRESS_INFO;
/**
Build a array of EFI_IP6_ADDRESS_INFO to be returned to the caller. The number
of EFI_IP6_ADDRESS_INFO is also returned. If AddressList is NULL,
only the address count is returned.
@param[in] IpSb The IP6 service binding instance.
@param[out] AddressCount The number of returned addresses.
@param[out] AddressList The pointer to the array of EFI_IP6_ADDRESS_INFO.
This is an optional parameter.
@retval EFI_SUCCESS The address array is successfully build
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the address info.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
Ip6BuildEfiAddressList (
IN IP6_SERVICE *IpSb,
OUT UINT32 *AddressCount,
OUT EFI_IP6_ADDRESS_INFO **AddressList OPTIONAL
);
/**
Generate the multicast addresses identify the group of all IPv6 nodes or IPv6
routers defined in RFC4291.
All Nodes Addresses: FF01::1, FF02::1.
All Router Addresses: FF01::2, FF02::2, FF05::2.
@param[in] Router If TRUE, generate all routers addresses,
else generate all node addresses.
@param[in] Scope interface-local(1), link-local(2), or site-local(5)
@param[out] Ip6Addr The generated multicast address.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
@retval EFI_SUCCESS The address is generated.
**/
EFI_STATUS
Ip6SetToAllNodeMulticast (
IN BOOLEAN Router,
IN UINT8 Scope,
OUT EFI_IPv6_ADDRESS *Ip6Addr
);
/**
This function converts MAC address to 64 bits interface ID according to RFC4291
and returns the interface ID. Currently only 48-bit MAC address is supported by
this function.
@param[in, out] IpSb The IP6 service binding instance.
@retval NULL The operation fails.
@return Pointer to the generated interface ID.
**/
UINT8 *
Ip6CreateInterfaceID (
IN OUT IP6_SERVICE *IpSb
);
/**
This function creates link-local address from interface identifier. The
interface identifier is normally created from MAC address. It might be manually
configured by administrator if the link-local address created from MAC address
is a duplicate address.
@param[in, out] IpSb The IP6 service binding instance.
@retval NULL If the operation fails.
@return The generated Link Local address, in network order.
**/
EFI_IPv6_ADDRESS *
Ip6CreateLinkLocalAddr (
IN OUT IP6_SERVICE *IpSb
);
/**
Compute the solicited-node multicast address for an unicast or anycast address,
by taking the low-order 24 bits of this address, and appending those bits to
the prefix FF02:0:0:0:0:1:FF00::/104.
@param Ip6Addr The unicast or anycast address, in network order.
@param MulticastAddr The generated solicited-node multicast address,
in network order.
**/
VOID
Ip6CreateSNMulticastAddr (
IN EFI_IPv6_ADDRESS *Ip6Addr,
OUT EFI_IPv6_ADDRESS *MulticastAddr
);
/**
Check whether the incoming Ipv6 address is a solicited-node multicast address.
@param[in] Ip6 Ip6 address, in network order.
@retval TRUE Yes, solicited-node multicast address
@retval FALSE No
**/
BOOLEAN
Ip6IsSNMulticastAddr (
IN EFI_IPv6_ADDRESS *Ip6
);
/**
Check whether the incoming IPv6 address is one of the maintained address in
the IP6 service binding instance.
@param[in] IpSb Points to a IP6 service binding instance
@param[in] Address The IP6 address to be checked.
@param[out] Interface If not NULL, output the IP6 interface which
maintains the Address.
@param[out] AddressInfo If not NULL, output the IP6 address information
of the Address.
@retval TRUE Yes, it is one of the maintained addresses.
@retval FALSE No, it is not one of the maintained addresses.
**/
BOOLEAN
Ip6IsOneOfSetAddress (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Address,
OUT IP6_INTERFACE **Interface OPTIONAL,
OUT IP6_ADDRESS_INFO **AddressInfo OPTIONAL
);
/**
Check whether the incoming MAC address is valid.
@param[in] IpSb Points to a IP6 service binding instance.
@param[in] LinkAddress The MAC address.
@retval TRUE Yes, it is valid.
@retval FALSE No, it is not valid.
**/
BOOLEAN
Ip6IsValidLinkAddress (
IN IP6_SERVICE *IpSb,
IN EFI_MAC_ADDRESS *LinkAddress
);
/**
Copy the PrefixLength bits from Src to Dest.
@param[out] Dest A pointer to the buffer to copy to.
@param[in] Src A pointer to the buffer to copy from.
@param[in] PrefixLength The number of bits to copy.
**/
VOID
Ip6CopyAddressByPrefix (
OUT EFI_IPv6_ADDRESS *Dest,
IN EFI_IPv6_ADDRESS *Src,
IN UINT8 PrefixLength
);
/**
Insert a node IP6_ADDRESS_INFO to an IP6 interface.
@param[in, out] IpIf Points to an IP6 interface.
@param[in] AddrInfo Points to an IP6_ADDRESS_INFO.
**/
VOID
Ip6AddAddr (
IN OUT IP6_INTERFACE *IpIf,
IN IP6_ADDRESS_INFO *AddrInfo
);
/**
Remove the IPv6 address from the address list node points to IP6_ADDRESS_INFO.
This function removes the matching IPv6 addresses from the address list and
adjusts the address count of the address list. If IpSb is not NULL, this function
calls Ip6LeaveGroup to see whether it should call Mnp->Groups() to remove the
its solicited-node multicast MAC address from the filter list and sends out
a Multicast Listener Done. If Prefix is NULL, all address in the address list
will be removed. If Prefix is not NULL, the address that matching the Prefix
with PrefixLength in the address list will be removed.
@param[in] IpSb NULL or points to IP6 service binding instance.
@param[in, out] AddressList address list array
@param[in, out] AddressCount the count of addresses in address list array
@param[in] Prefix NULL or an IPv6 address prefix
@param[in] PrefixLength the length of Prefix
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_FOUND The address matching the Prefix with PrefixLength
cannot be found in address list.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
Ip6RemoveAddr (
IN IP6_SERVICE *IpSb OPTIONAL,
IN OUT LIST_ENTRY *AddressList,
IN OUT UINT32 *AddressCount,
IN EFI_IPv6_ADDRESS *Prefix OPTIONAL,
IN UINT8 PrefixLength
);
/**
Set the Ip6 variable data.
@param[in] IpSb Points to an IP6 service binding instance
@retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.
@retval other Set variable failed.
**/
EFI_STATUS
Ip6SetVariableData (
IN IP6_SERVICE *IpSb
);
/**
Clear the variable and free the resource.
@param[in] IpSb Ip6 service binding instance.
**/
VOID
Ip6ClearVariableData (
IN IP6_SERVICE *IpSb
);
/**
Get the MAC address for a multicast IP address. Call
Mnp's McastIpToMac to find the MAC address instead of
hard-coding the NIC to be Ethernet.
@param[in] Mnp The Mnp instance to get the MAC address.
@param[in] Multicast The multicast IP address to translate.
@param[out] Mac The buffer to hold the translated address.
@retval EFI_SUCCESS The multicast IP is successfully
translated to a multicast MAC address.
@retval Other The address is not converted because an error occurred.
**/
EFI_STATUS
Ip6GetMulticastMac (
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
IN EFI_IPv6_ADDRESS *Multicast,
OUT EFI_MAC_ADDRESS *Mac
);
/**
Convert the multibyte field in IP header's byter order.
In spite of its name, it can also be used to convert from
host to network byte order.
@param[in, out] Head The IP head to convert.
@return Point to the converted IP head.
**/
EFI_IP6_HEADER *
Ip6NtohHead (
IN OUT EFI_IP6_HEADER *Head
);
#endif

View File

@@ -0,0 +1,170 @@
/** @file
VFR file used by the IP6 configuration component.
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ip6NvData.h"
#define EFI_NETWORK_DEVICE_CLASS 0x04
formset
guid = IP6_CONFIG_NVDATA_GUID,
title = STRING_TOKEN(STR_IP6_CONFIG_FORM_TITLE),
help = STRING_TOKEN(STR_IP6_CONFIG_FORM_HELP),
class = EFI_NETWORK_DEVICE_CLASS,
subclass = 0x03,
varstore IP6_CONFIG_IFR_NVDATA,
name = IP6_CONFIG_IFR_NVDATA,
guid = IP6_CONFIG_NVDATA_GUID;
form formid = FORMID_MAIN_FORM,
title = STRING_TOKEN(STR_IP6_DEVICE_FORM_TITLE);
text
help = STRING_TOKEN(STR_IP6_INTERFACE_NAME_HELP),
text = STRING_TOKEN(STR_IP6_INTERFACE_NAME),
text = STRING_TOKEN(STR_IP6_INTERFACE_NAME_CONTENT);
text
help = STRING_TOKEN(STR_IP6_INTERFACE_TYPE_HELP),
text = STRING_TOKEN(STR_IP6_INTERFACE_TYPE),
text = STRING_TOKEN(STR_IP6_INTERFACE_TYPE_CONTENT);
text
help = STRING_TOKEN(STR_IP6_MAC_ADDRESS_HELP),
text = STRING_TOKEN(STR_IP6_MAC_ADDRESS),
text = STRING_TOKEN(STR_IP6_MAC_ADDRESS_CONTENT);
text
help = STRING_TOKEN(STR_IP6_HOST_ADDRESS_HELP),
text = STRING_TOKEN(STR_IP6_HOST_ADDRESS),
text = STRING_TOKEN(STR_NULL);
label HOST_ADDRESS_LABEL;
label LABEL_END;
text
help = STRING_TOKEN(STR_IP6_ROUTE_TABLE_HELP),
text = STRING_TOKEN(STR_IP6_ROUTE_TABLE),
text = STRING_TOKEN(STR_NULL);
label ROUTE_TABLE_LABEL;
label LABEL_END;
text
help = STRING_TOKEN(STR_IP6_GATEWAY_ADDRESS_HELP),
text = STRING_TOKEN(STR_IP6_GATEWAY_ADDRESS),
text = STRING_TOKEN(STR_NULL);
label GATEWAY_ADDRESS_LABEL;
label LABEL_END;
text
help = STRING_TOKEN(STR_IP6_DNS_ADDRESS_HELP),
text = STRING_TOKEN(STR_IP6_DNS_ADDRESS),
text = STRING_TOKEN(STR_NULL);
label DNS_ADDRESS_LABEL;
label LABEL_END;
string varid = IP6_CONFIG_IFR_NVDATA.InterfaceId,
prompt = STRING_TOKEN(STR_IP6_INTERFACE_ID),
help = STRING_TOKEN(STR_IP6_INTERFACE_ID_HELP),
flags = INTERACTIVE,
key = KEY_INTERFACE_ID,
minsize = INTERFACE_ID_STR_MIN_SIZE,
maxsize = INTERFACE_ID_STR_MAX_SIZE,
endstring;
numeric varid = IP6_CONFIG_IFR_NVDATA.DadTransmitCount,
prompt = STRING_TOKEN(STR_IP6_DAD_TRANSMIT_COUNT),
help = STRING_TOKEN(STR_IP6_DAD_TRANSMIT_COUNT_HELP),
flags = 0,
minimum = 0,
maximum = DAD_MAX_TRANSMIT_COUNT,
step = 0,
endnumeric;
oneof varid = IP6_CONFIG_IFR_NVDATA.Policy,
prompt = STRING_TOKEN(STR_POLICY_TYPE_PROMPT),
help = STRING_TOKEN(STR_POLICY_TYPE_HELP),
option text = STRING_TOKEN(STR_POLICY_TYPE_AUTO), value = IP6_POLICY_AUTO, flags = DEFAULT;
option text = STRING_TOKEN(STR_POLICY_TYPE_MANUAL), value = IP6_POLICY_MANUAL, flags = 0;
endoneof;
subtitle text = STRING_TOKEN(STR_NULL);
suppressif ideqval IP6_CONFIG_IFR_NVDATA.Policy == IP6_POLICY_AUTO;
goto FORMID_MANUAL_CONFIG_FORM,
prompt = STRING_TOKEN(STR_IP6_AD_CONFIG_FORM),
help = STRING_TOKEN(STR_IP6_AD_CONFIG_FORM_HELP),
flags = 0;
subtitle text = STRING_TOKEN(STR_NULL);
endif;
text
help = STRING_TOKEN (STR_SAVE_CHANGES_HELP),
text = STRING_TOKEN (STR_SAVE_CHANGES),
text = STRING_TOKEN (STR_NULL),
flags = INTERACTIVE,
key = KEY_SAVE_CHANGES;
endform;
form formid = FORMID_MANUAL_CONFIG_FORM,
title = STRING_TOKEN(STR_IP6_AD_CONFIG_FORM);
string varid = IP6_CONFIG_IFR_NVDATA.ManualAddress,
prompt = STRING_TOKEN(STR_IP6_MANUAL_ADDRESS),
help = STRING_TOKEN(STR_IP6_MANUAL_ADDRESS_HELP),
flags = INTERACTIVE,
key = KEY_MANUAL_ADDRESS,
minsize = ADDRESS_STR_MIN_SIZE,
maxsize = ADDRESS_STR_MAX_SIZE,
endstring;
string varid = IP6_CONFIG_IFR_NVDATA.GatewayAddress,
prompt = STRING_TOKEN(STR_IP6_NEW_GATEWAY_ADDRESS),
help = STRING_TOKEN(STR_IP6_NEW_GATEWAY_ADDR_HELP),
flags = INTERACTIVE,
key = KEY_GATEWAY_ADDRESS,
minsize = ADDRESS_STR_MIN_SIZE,
maxsize = ADDRESS_STR_MAX_SIZE,
endstring;
string varid = IP6_CONFIG_IFR_NVDATA.DnsAddress,
prompt = STRING_TOKEN(STR_IP6_NEW_DNS_ADDRESS),
help = STRING_TOKEN(STR_IP6_NEW_DNS_ADDRESS_HELP),
flags = INTERACTIVE,
key = KEY_DNS_ADDRESS,
minsize = ADDRESS_STR_MIN_SIZE,
maxsize = ADDRESS_STR_MAX_SIZE,
endstring;
goto FORMID_MAIN_FORM,
prompt = STRING_TOKEN (STR_SAVE_AND_EXIT),
help = STRING_TOKEN (STR_SAVE_AND_EXIT),
flags = INTERACTIVE,
key = KEY_SAVE_CONFIG_CHANGES;
goto FORMID_MAIN_FORM,
prompt = STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
help = STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
flags = INTERACTIVE,
key = KEY_IGNORE_CONFIG_CHANGES;
endform;
endformset;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,295 @@
/** @file
Definitions for EFI IPv6 Configuartion Protocol implementation.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __IP6_CONFIG_IMPL_H__
#define __IP6_CONFIG_IMPL_H__
#define IP6_CONFIG_INSTANCE_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'C')
#define IP6_FORM_CALLBACK_INFO_SIGNATURE SIGNATURE_32 ('I', 'F', 'C', 'I')
#define IP6_CONFIG_VARIABLE_ATTRIBUTE (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)
#define IP6_CONFIG_DEFAULT_DAD_XMITS 1
#define IP6_CONFIG_DHCP6_OPTION_ORO 6
#define IP6_CONFIG_DHCP6_OPTION_DNS_SERVERS 23
#define DATA_ATTRIB_SIZE_FIXED 0x1
#define DATA_ATTRIB_VOLATILE 0x2
#define DATA_ATTRIB_SET(Attrib, Bits) (BOOLEAN)((Attrib) & (Bits))
#define SET_DATA_ATTRIB(Attrib, Bits) ((Attrib) |= (Bits))
typedef struct _IP6_CONFIG_INSTANCE IP6_CONFIG_INSTANCE;
#define IP6_CONFIG_INSTANCE_FROM_PROTOCOL(Proto) \
CR ((Proto), \
IP6_CONFIG_INSTANCE, \
Ip6Config, \
IP6_CONFIG_INSTANCE_SIGNATURE \
)
#define IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK(Callback) \
CR ((Callback), \
IP6_CONFIG_INSTANCE, \
CallbackInfo, \
IP6_CONFIG_INSTANCE_SIGNATURE \
)
#define IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE(Instance) \
CR ((Instance), \
IP6_SERVICE, \
Ip6ConfigInstance, \
IP6_SERVICE_SIGNATURE \
)
#define IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(ConfigAccess) \
CR ((ConfigAccess), \
IP6_FORM_CALLBACK_INFO, \
HiiConfigAccess, \
IP6_FORM_CALLBACK_INFO_SIGNATURE \
)
/**
The prototype of work function for EfiIp6ConfigSetData().
@param[in] Instance The pointer to the IP6 config instance data.
@param[in] DataSize In bytes, the size of the buffer pointed to by Data.
@param[in] Data The data buffer to set.
@retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type,
8 bytes.
@retval EFI_SUCCESS The specified configuration data for the EFI IPv6
network stack was set successfully.
**/
typedef
EFI_STATUS
(*IP6_CONFIG_SET_DATA) (
IN IP6_CONFIG_INSTANCE *Instance,
IN UINTN DataSize,
IN VOID *Data
);
/**
The prototype of work function for EfiIp6ConfigGetData().
@param[in] Instance The pointer to the IP6 config instance data.
@param[in, out] DataSize On input, in bytes, the size of Data. On output, in
bytes, the size of buffer required to store the specified
configuration data.
@param[in] Data The data buffer in which the configuration data is returned.
Ignored if DataSize is ZERO.
@retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
configuration data, and the required size is
returned in DataSize.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
**/
typedef
EFI_STATUS
(*IP6_CONFIG_GET_DATA) (
IN IP6_CONFIG_INSTANCE *Instance,
IN OUT UINTN *DataSize,
IN VOID *Data OPTIONAL
);
typedef union {
VOID *Ptr;
EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
EFI_IP6_CONFIG_INTERFACE_ID *AltIfId;
EFI_IP6_CONFIG_POLICY *Policy;
EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS *DadXmits;
EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress;
EFI_IPv6_ADDRESS *Gateway;
EFI_IPv6_ADDRESS *DnsServers;
} IP6_CONFIG_DATA;
typedef struct {
IP6_CONFIG_SET_DATA SetData;
IP6_CONFIG_GET_DATA GetData;
EFI_STATUS Status;
UINT8 Attribute;
NET_MAP EventMap;
IP6_CONFIG_DATA Data;
UINTN DataSize;
} IP6_CONFIG_DATA_ITEM;
typedef struct {
UINT16 Offset;
UINTN DataSize;
EFI_IP6_CONFIG_DATA_TYPE DataType;
} IP6_CONFIG_DATA_RECORD;
#pragma pack(1)
//
// heap data that contains the data for each data record.
//
// BOOLEAN IsAltIfIdSet;
// EFI_IP6_CONFIG_POLICY Policy;
// EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
// UINT32 ManualaddressCount;
// UINT32 GatewayCount;
// UINT32 DnsServersCount;
// EFI_IP6_CONFIG_INTERFACE_ID AltIfId;
// EFI_IP6_CONFIG_MANUAL_ADDRESS ManualAddress[];
// EFI_IPv6_ADDRESS Gateway[];
// EFI_IPv6_ADDRESS DnsServers[];
//
typedef struct {
UINT32 IaId;
UINT16 Checksum;
UINT16 DataRecordCount;
IP6_CONFIG_DATA_RECORD DataRecord[1];
} IP6_CONFIG_VARIABLE;
#pragma pack()
typedef struct {
LIST_ENTRY Link;
EFI_IP6_ADDRESS_INFO AddrInfo;
} IP6_ADDRESS_INFO_ENTRY;
typedef struct {
EFI_IP6_CONFIG_POLICY Policy; ///< manual or automatic
EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadTransmitCount; ///< dad transmits count
EFI_IP6_CONFIG_INTERFACE_ID InterfaceId; ///< alternative interface id
LIST_ENTRY ManualAddress; ///< IP addresses
UINT32 ManualAddressCount; ///< IP addresses count
LIST_ENTRY GatewayAddress; ///< Gateway address
UINT32 GatewayAddressCount; ///< Gateway address count
LIST_ENTRY DnsAddress; ///< DNS server address
UINT32 DnsAddressCount; ///< DNS server address count
} IP6_CONFIG_NVDATA;
typedef struct _IP6_FORM_CALLBACK_INFO {
UINT32 Signature;
EFI_HANDLE ChildHandle;
EFI_HII_CONFIG_ACCESS_PROTOCOL HiiConfigAccess;
EFI_DEVICE_PATH_PROTOCOL *HiiVendorDevicePath;
EFI_HII_HANDLE RegisteredHandle;
} IP6_FORM_CALLBACK_INFO;
struct _IP6_CONFIG_INSTANCE {
UINT32 Signature;
BOOLEAN Configured;
LIST_ENTRY Link;
UINT16 IfIndex;
EFI_IP6_CONFIG_INTERFACE_INFO InterfaceInfo;
EFI_IP6_CONFIG_INTERFACE_ID AltIfId;
EFI_IP6_CONFIG_POLICY Policy;
EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
IP6_CONFIG_DATA_ITEM DataItem[Ip6ConfigDataTypeMaximum];
NET_MAP DadFailedMap;
NET_MAP DadPassedMap;
EFI_IP6_CONFIG_PROTOCOL Ip6Config;
EFI_EVENT Dhcp6SbNotifyEvent;
VOID *Registration;
EFI_HANDLE Dhcp6Handle;
EFI_DHCP6_PROTOCOL *Dhcp6;
BOOLEAN OtherInfoOnly;
UINT32 IaId;
EFI_EVENT Dhcp6Event;
UINT32 FailedIaAddressCount;
EFI_IPv6_ADDRESS *DeclineAddress;
UINT32 DeclineAddressCount;
IP6_FORM_CALLBACK_INFO CallbackInfo;
IP6_CONFIG_NVDATA Ip6NvData;
};
/**
The event process routine when the DHCPv6 server is answered with a reply packet
for an information request.
@param[in] This Points to the EFI_DHCP6_PROTOCOL.
@param[in] Context The pointer to the IP6 configuration instance data.
@param[in] Packet The DHCPv6 reply packet.
@retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
@retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
the DNS server address is not valid.
**/
EFI_STATUS
EFIAPI
Ip6ConfigOnDhcp6Reply (
IN EFI_DHCP6_PROTOCOL *This,
IN VOID *Context,
IN EFI_DHCP6_PACKET *Packet
);
/**
The work function to trigger the DHCPv6 process to perform a stateful autoconfiguration.
@param[in] Instance Pointer to the IP6 config instance data.
@param[in] OtherInfoOnly If FALSE, get stateful address and other information
via DHCPv6. Otherwise, only get the other information.
@retval EFI_SUCCESS The operation finished successfully.
@retval EFI_UNSUPPORTED The DHCP6 driver is not available.
**/
EFI_STATUS
Ip6ConfigStartStatefulAutoConfig (
IN IP6_CONFIG_INSTANCE *Instance,
IN BOOLEAN OtherInfoOnly
);
/**
Initialize an IP6_CONFIG_INSTANCE.
@param[out] Instance The buffer of IP6_CONFIG_INSTANCE to be initialized.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
@retval EFI_SUCCESS The IP6_CONFIG_INSTANCE initialized successfully.
**/
EFI_STATUS
Ip6ConfigInitInstance (
OUT IP6_CONFIG_INSTANCE *Instance
);
/**
Release an IP6_CONFIG_INSTANCE.
@param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
**/
VOID
Ip6ConfigCleanInstance (
IN OUT IP6_CONFIG_INSTANCE *Instance
);
/**
Destory the Dhcp6 child in IP6_CONFIG_INSTANCE and release the resources.
@param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
@retval EFI_SUCCESS The child was successfully destroyed.
@retval Others Failed to destory the child.
**/
EFI_STATUS
Ip6ConfigDestroyDhcp6 (
IN OUT IP6_CONFIG_INSTANCE *Instance
);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
/** @file
The header file of Ip6ConfigNv.c.
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _IP6_CONFIGNV_H_
#define _IP6_CONFIGNV_H_
#include "Ip6NvData.h"
#include "Ip6ConfigImpl.h"
extern UINT8 Ip6ConfigBin[];
extern UINT8 Ip6DxeStrings[];
#define IP6_HII_VENDOR_DEVICE_PATH_GUID \
{ \
0x13288098, 0xb11f, 0x45b9, { 0xbc, 0x4f, 0x91, 0xb5, 0x4b, 0xa3, 0x39, 0xb9 } \
}
#define IP6_ETHERNET L"Ethernet"
#define IP6_EXPERIMENTAL_ETHERNET L"Experimental Ethernet"
#define IP6_ADDRESS_DELIMITER L' '
#define IP6_LINK_LOCAL_PREFIX L"FE80::"
typedef enum {
Ip6InterfaceTypeEthernet = 1,
Ip6InterfaceTypeExperimentalEthernet
} IP6_INTERFACE_TYPE;
typedef enum {
Ip6ConfigNvHostAddress,
Ip6ConfigNvGatewayAddress,
Ip6ConfigNvDnsAddress,
Ip6ConfigNvRouteTable
} IP6_CONFIG_NV_ADDRESS_TYPE;
/**
Install HII Config Access protocol for network device and allocate resources.
@param[in, out] Instance The IP6_CONFIG_INSTANCE to create a form.
@retval EFI_SUCCESS The HII Config Access protocol is installed.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
@retval Others Other errors as indicated.
**/
EFI_STATUS
Ip6ConfigFormInit (
IN OUT IP6_CONFIG_INSTANCE *Instance
);
/**
Uninstall HII Config Access protocol for network device and free resource.
@param[in, out] Instance The IP6_CONFIG_INSTANCE to unload a form.
**/
VOID
Ip6ConfigFormUnload (
IN OUT IP6_CONFIG_INSTANCE *Instance
);
#endif

View File

@@ -0,0 +1,930 @@
/** @file
The driver binding and service binding protocol for IP6 driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ip6Impl.h"
EFI_DRIVER_BINDING_PROTOCOL gIp6DriverBinding = {
Ip6DriverBindingSupported,
Ip6DriverBindingStart,
Ip6DriverBindingStop,
0xa,
NULL,
NULL
};
/**
This is the declaration of an EFI image entry point. This entry point is
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
both device drivers and bus drivers.
The entry point for IP6 driver which installs the driver
binding and component name protocol on its image.
@param[in] ImageHandle The firmware allocated handle for the UEFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
**/
EFI_STATUS
EFIAPI
Ip6DriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gIp6DriverBinding,
ImageHandle,
&gIp6ComponentName,
&gIp6ComponentName2
);
}
/**
Test to see if this driver supports ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to test.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to start.
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_ALREADY_STARTED This driver is already running on this device.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
Ip6DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
//
// Test for the MNP service binding Protocol
//
return gBS->OpenProtocol (
ControllerHandle,
&gEfiManagedNetworkServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
}
/**
Clean up an IP6 service binding instance. It releases all
the resource allocated by the instance. The instance may be
partly initialized, or partly destroyed. If a resource is
destroyed, it is marked as that in case the destory failed and
being called again later.
@param[in] IpSb The IP6 service binding instance to clean up.
@retval EFI_SUCCESS The resource used by the instance are cleaned up.
@retval Others Failed to clean up some of the resources.
**/
EFI_STATUS
Ip6CleanService (
IN IP6_SERVICE *IpSb
)
{
EFI_STATUS Status;
EFI_IPv6_ADDRESS AllNodes;
IP6_NEIGHBOR_ENTRY *NeighborCache;
Ip6ConfigCleanInstance (&IpSb->Ip6ConfigInstance);
//
// Leave link-scope all-nodes multicast address (FF02::1)
//
Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
Status = Ip6LeaveGroup (IpSb, &AllNodes);
if (EFI_ERROR (Status)) {
return Status;
}
if (IpSb->DefaultInterface != NULL) {
Ip6CleanInterface (IpSb->DefaultInterface, NULL);
IpSb->DefaultInterface = NULL;
}
Ip6CleanDefaultRouterList (IpSb);
Ip6CleanPrefixListTable (IpSb, &IpSb->OnlinkPrefix);
Ip6CleanPrefixListTable (IpSb, &IpSb->AutonomousPrefix);
if (IpSb->RouteTable != NULL) {
Ip6CleanRouteTable (IpSb->RouteTable);
IpSb->RouteTable = NULL;
}
if (IpSb->InterfaceId != NULL) {
FreePool (IpSb->InterfaceId);
}
IpSb->InterfaceId = NULL;
Ip6CleanAssembleTable (&IpSb->Assemble);
if (IpSb->MnpChildHandle != NULL) {
if (IpSb->Mnp != NULL) {
IpSb->Mnp->Cancel (IpSb->Mnp, NULL);
IpSb->Mnp->Configure (IpSb->Mnp, NULL);
gBS->CloseProtocol (
IpSb->MnpChildHandle,
&gEfiManagedNetworkProtocolGuid,
IpSb->Image,
IpSb->Controller
);
IpSb->Mnp = NULL;
}
NetLibDestroyServiceChild (
IpSb->Controller,
IpSb->Image,
&gEfiManagedNetworkServiceBindingProtocolGuid,
IpSb->MnpChildHandle
);
IpSb->MnpChildHandle = NULL;
}
if (IpSb->RecvRequest.MnpToken.Event != NULL) {
gBS->CloseEvent (IpSb->RecvRequest.MnpToken.Event);
}
if (IpSb->Timer != NULL) {
gBS->SetTimer (IpSb->Timer, TimerCancel, 0);
gBS->CloseEvent (IpSb->Timer);
IpSb->Timer = NULL;
}
if (IpSb->FasterTimer != NULL) {
gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0);
gBS->CloseEvent (IpSb->FasterTimer);
IpSb->FasterTimer = NULL;
}
//
// Free the Neighbor Discovery resources
//
while (!IsListEmpty (&IpSb->NeighborTable)) {
NeighborCache = NET_LIST_HEAD (&IpSb->NeighborTable, IP6_NEIGHBOR_ENTRY, Link);
Ip6FreeNeighborEntry (IpSb, NeighborCache, FALSE, TRUE, EFI_SUCCESS, NULL, NULL);
}
return EFI_SUCCESS;
}
/**
Create a new IP6 driver service binding protocol.
@param[in] Controller The controller that has MNP service binding
installed.
@param[in] ImageHandle The IP6 driver's image handle.
@param[out] Service The variable to receive the newly created IP6
service.
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
@retval EFI_SUCCESS A new IP6 service binding private is created.
**/
EFI_STATUS
Ip6CreateService (
IN EFI_HANDLE Controller,
IN EFI_HANDLE ImageHandle,
OUT IP6_SERVICE **Service
)
{
IP6_SERVICE *IpSb;
EFI_STATUS Status;
EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
EFI_MANAGED_NETWORK_CONFIG_DATA *Config;
IP6_CONFIG_DATA_ITEM *DataItem;
ASSERT (Service != NULL);
*Service = NULL;
//
// allocate a service private data then initialize all the filed to
// empty resources, so if any thing goes wrong when allocating
// resources, Ip6CleanService can be called to clean it up.
//
IpSb = AllocateZeroPool (sizeof (IP6_SERVICE));
if (IpSb == NULL) {
return EFI_OUT_OF_RESOURCES;
}
IpSb->Signature = IP6_SERVICE_SIGNATURE;
IpSb->ServiceBinding.CreateChild = Ip6ServiceBindingCreateChild;
IpSb->ServiceBinding.DestroyChild = Ip6ServiceBindingDestroyChild;
IpSb->State = IP6_SERVICE_UNSTARTED;
IpSb->InDestroy = FALSE;
IpSb->NumChildren = 0;
InitializeListHead (&IpSb->Children);
InitializeListHead (&IpSb->Interfaces);
IpSb->DefaultInterface = NULL;
IpSb->RouteTable = NULL;
IpSb->RecvRequest.Signature = IP6_LINK_RX_SIGNATURE;
IpSb->RecvRequest.CallBack = NULL;
IpSb->RecvRequest.Context = NULL;
MnpToken = &IpSb->RecvRequest.MnpToken;
MnpToken->Event = NULL;
MnpToken->Status = EFI_NOT_READY;
MnpToken->Packet.RxData = NULL;
Ip6CreateAssembleTable (&IpSb->Assemble);
IpSb->MldCtrl.Mldv1QuerySeen = 0;
InitializeListHead (&IpSb->MldCtrl.Groups);
ZeroMem (&IpSb->LinkLocalAddr, sizeof (EFI_IPv6_ADDRESS));
IpSb->LinkLocalOk = FALSE;
IpSb->LinkLocalDadFail = FALSE;
IpSb->Dhcp6NeedStart = FALSE;
IpSb->Dhcp6NeedInfoRequest = FALSE;
IpSb->CurHopLimit = IP6_HOP_LIMIT;
IpSb->LinkMTU = IP6_MIN_LINK_MTU;
IpSb->BaseReachableTime = IP6_REACHABLE_TIME;
Ip6UpdateReachableTime (IpSb);
//
// RFC4861 RETRANS_TIMER: 1,000 milliseconds
//
IpSb->RetransTimer = IP6_RETRANS_TIMER;
IpSb->RoundRobin = 0;
InitializeListHead (&IpSb->NeighborTable);
InitializeListHead (&IpSb->DefaultRouterList);
InitializeListHead (&IpSb->OnlinkPrefix);
InitializeListHead (&IpSb->AutonomousPrefix);
IpSb->InterfaceIdLen = IP6_IF_ID_LEN;
IpSb->InterfaceId = NULL;
IpSb->RouterAdvertiseReceived = FALSE;
IpSb->SolicitTimer = IP6_MAX_RTR_SOLICITATIONS;
IpSb->Ticks = 0;
IpSb->Image = ImageHandle;
IpSb->Controller = Controller;
IpSb->MnpChildHandle = NULL;
IpSb->Mnp = NULL;
Config = &IpSb->MnpConfigData;
Config->ReceivedQueueTimeoutValue = 0;
Config->TransmitQueueTimeoutValue = 0;
Config->ProtocolTypeFilter = IP6_ETHER_PROTO;
Config->EnableUnicastReceive = TRUE;
Config->EnableMulticastReceive = TRUE;
Config->EnableBroadcastReceive = TRUE;
Config->EnablePromiscuousReceive = FALSE;
Config->FlushQueuesOnReset = TRUE;
Config->EnableReceiveTimestamps = FALSE;
Config->DisableBackgroundPolling = FALSE;
ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));
IpSb->Timer = NULL;
IpSb->FasterTimer = NULL;
ZeroMem (&IpSb->Ip6ConfigInstance, sizeof (IP6_CONFIG_INSTANCE));
IpSb->MacString = NULL;
//
// Create various resources. First create the route table, timer
// event, MNP token event and MNP child.
//
IpSb->RouteTable = Ip6CreateRouteTable ();
if (IpSb->RouteTable == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
}
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL | EVT_TIMER,
TPL_CALLBACK,
Ip6TimerTicking,
IpSb,
&IpSb->Timer
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL | EVT_TIMER,
TPL_CALLBACK,
Ip6NdFasterTimerTicking,
IpSb,
&IpSb->FasterTimer
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = NetLibCreateServiceChild (
Controller,
ImageHandle,
&gEfiManagedNetworkServiceBindingProtocolGuid,
&IpSb->MnpChildHandle
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
IpSb->MnpChildHandle,
&gEfiManagedNetworkProtocolGuid,
(VOID **) (&IpSb->Mnp),
ImageHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = Ip6ServiceConfigMnp (IpSb, TRUE);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &IpSb->SnpMode);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
IpSb->MaxPacketSize = IP6_MIN_LINK_MTU - sizeof (EFI_IP6_HEADER);
if (NetLibGetVlanId (IpSb->Controller) != 0) {
//
// This is a VLAN device, reduce MTU by VLAN tag length
//
IpSb->MaxPacketSize -= NET_VLAN_TAG_LEN;
}
IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;
//
// Currently only ETHERNET is supported in IPv6 stack, since
// link local address requires an IEEE 802 48-bit MACs for
// EUI-64 format interface identifier mapping.
//
if (IpSb->SnpMode.IfType != NET_IFTYPE_ETHERNET) {
Status = EFI_UNSUPPORTED;
goto ON_ERROR;
}
Status = Ip6InitMld (IpSb);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// The timer expires every 100 (IP6_TIMER_INTERVAL_IN_MS) milliseconds.
//
Status = gBS->SetTimer (IpSb->FasterTimer, TimerPeriodic, TICKS_PER_MS * IP6_TIMER_INTERVAL_IN_MS);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// The timer expires every 1000 (IP6_ONE_SECOND_IN_MS) milliseconds.
//
Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_MS * IP6_ONE_SECOND_IN_MS);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
Ip6OnFrameReceived,
&IpSb->RecvRequest,
&MnpToken->Event
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = Ip6ReceiveFrame (Ip6AcceptFrame, IpSb);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = Ip6ConfigInitInstance (&IpSb->Ip6ConfigInstance);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
IpSb->DefaultInterface = Ip6CreateInterface (IpSb, TRUE);
if (IpSb->DefaultInterface == NULL) {
Status = EFI_DEVICE_ERROR;
goto ON_ERROR;
}
//
// If there is any manual address, set it.
//
DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeManualAddress];
if (DataItem->Data.Ptr != NULL) {
DataItem->SetData (
&IpSb->Ip6ConfigInstance,
DataItem->DataSize,
DataItem->Data.Ptr
);
}
InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);
*Service = IpSb;
return EFI_SUCCESS;
ON_ERROR:
Ip6CleanService (IpSb);
FreePool (IpSb);
return Status;
}
/**
Start this driver on ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to bind driver to.
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
device to start.
@retval EFI_SUCCES This driver is added to ControllerHandle.
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
Ip6DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
IP6_SERVICE *IpSb;
EFI_STATUS Status;
//
// Test for the Ip6 service binding protocol
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiIp6ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (Status == EFI_SUCCESS) {
return EFI_ALREADY_STARTED;
}
Status = Ip6CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);
if (EFI_ERROR (Status)) {
return Status;
}
ASSERT (IpSb != NULL);
//
// Install the Ip6ServiceBinding Protocol onto ControlerHandle
//
Status = gBS->InstallMultipleProtocolInterfaces (
&ControllerHandle,
&gEfiIp6ServiceBindingProtocolGuid,
&IpSb->ServiceBinding,
&gEfiIp6ConfigProtocolGuid,
&IpSb->Ip6ConfigInstance.Ip6Config,
NULL
);
if (EFI_ERROR (Status)) {
Ip6CleanService (IpSb);
FreePool (IpSb);
} else {
//
// Initialize the IP6 ID
//
mIp6Id = NET_RANDOM (NetRandomInitSeed ());
Ip6SetVariableData (IpSb);
}
return Status;
}
/**
Stop this driver on ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to stop driver on.
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
of children is zero, stop the entire bus driver.
@param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
if NumberOfChildren is 0.
@retval EFI_SUCCESS The device was stopped.
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
**/
EFI_STATUS
EFIAPI
Ip6DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
)
{
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
IP6_SERVICE *IpSb;
IP6_PROTOCOL *IpInstance;
EFI_HANDLE NicHandle;
EFI_STATUS Status;
BOOLEAN IsDhcp6;
EFI_TPL OldTpl;
INTN State;
IsDhcp6 = FALSE;
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);
if (NicHandle != NULL) {
//
// DriverBindingStop is triggered by the uninstallation of the EFI DHCPv6
// Protocol used by Ip6Config.
//
IsDhcp6 = TRUE;
} else {
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
if (NicHandle == NULL) {
return EFI_DEVICE_ERROR;
}
}
Status = gBS->OpenProtocol (
NicHandle,
&gEfiIp6ServiceBindingProtocolGuid,
(VOID **) &ServiceBinding,
This->DriverBindingHandle,
NicHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
IpSb = IP6_SERVICE_FROM_PROTOCOL (ServiceBinding);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
if (IpSb->InDestroy) {
Status = EFI_SUCCESS;
goto Exit;
}
if (IsDhcp6) {
Status = Ip6ConfigDestroyDhcp6 (&IpSb->Ip6ConfigInstance);
gBS->CloseEvent (IpSb->Ip6ConfigInstance.Dhcp6Event);
IpSb->Ip6ConfigInstance.Dhcp6Event = NULL;
} else if (NumberOfChildren == 0) {
IpSb->InDestroy = TRUE;
State = IpSb->State;
IpSb->State = IP6_SERVICE_DESTROY;
//
// Clear the variable data.
//
Ip6ClearVariableData (IpSb);
Status = Ip6CleanService (IpSb);
if (EFI_ERROR (Status)) {
IpSb->State = State;
goto Exit;
}
Status = gBS->UninstallMultipleProtocolInterfaces (
NicHandle,
&gEfiIp6ServiceBindingProtocolGuid,
ServiceBinding,
&gEfiIp6ConfigProtocolGuid,
&IpSb->Ip6ConfigInstance.Ip6Config,
NULL
);
ASSERT_EFI_ERROR (Status);
FreePool (IpSb);
} else {
//
// NumberOfChildren is not zero, destroy all IP6 children instances.
//
while (!IsListEmpty (&IpSb->Children)) {
IpInstance = NET_LIST_HEAD (&IpSb->Children, IP6_PROTOCOL, Link);
ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);
}
if (IpSb->NumChildren != 0) {
Status = EFI_DEVICE_ERROR;
}
}
Exit:
gBS->RestoreTPL (OldTpl);
return Status;
}
/**
Creates a child handle with a set of I/O services.
@param[in] This Protocol instance pointer.
@param[in] ChildHandle Pointer to the handle of the child to create. If
it is NULL, then a new handle is created. If it
is not NULL, then the I/O services are added to
the existing child handle.
@retval EFI_SUCCES The child handle was created with the I/O services.
@retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
the child.
@retval other The child handle was not created.
**/
EFI_STATUS
EFIAPI
Ip6ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE *ChildHandle
)
{
IP6_SERVICE *IpSb;
IP6_PROTOCOL *IpInstance;
EFI_TPL OldTpl;
EFI_STATUS Status;
VOID *Mnp;
if ((This == NULL) || (ChildHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
IpSb = IP6_SERVICE_FROM_PROTOCOL (This);
if (IpSb->LinkLocalDadFail) {
return EFI_DEVICE_ERROR;
}
IpInstance = AllocatePool (sizeof (IP6_PROTOCOL));
if (IpInstance == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Ip6InitProtocol (IpSb, IpInstance);
//
// Install Ip6 onto ChildHandle
//
Status = gBS->InstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiIp6ProtocolGuid,
&IpInstance->Ip6Proto,
NULL
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
IpInstance->Handle = *ChildHandle;
//
// Open the Managed Network protocol BY_CHILD.
//
Status = gBS->OpenProtocol (
IpSb->MnpChildHandle,
&gEfiManagedNetworkProtocolGuid,
(VOID **) &Mnp,
gIp6DriverBinding.DriverBindingHandle,
IpInstance->Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
gBS->UninstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiIp6ProtocolGuid,
&IpInstance->Ip6Proto,
NULL
);
goto ON_ERROR;
}
//
// Insert it into the service binding instance.
//
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
InsertTailList (&IpSb->Children, &IpInstance->Link);
IpSb->NumChildren++;
gBS->RestoreTPL (OldTpl);
ON_ERROR:
if (EFI_ERROR (Status)) {
Ip6CleanProtocol (IpInstance);
FreePool (IpInstance);
}
return Status;
}
/**
Destroys a child handle with a set of I/O services.
@param[in] This Protocol instance pointer.
@param[in] ChildHandle Handle of the child to destroy.
@retval EFI_SUCCES The I/O services were removed from the child
handle.
@retval EFI_UNSUPPORTED The child handle does not support the I/O services
that are being removed.
@retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
@retval EFI_ACCESS_DENIED The child handle could not be destroyed because
its I/O services are being used.
@retval other The child handle was not destroyed.
**/
EFI_STATUS
EFIAPI
Ip6ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
)
{
EFI_STATUS Status;
IP6_SERVICE *IpSb;
IP6_PROTOCOL *IpInstance;
EFI_IP6_PROTOCOL *Ip6;
EFI_TPL OldTpl;
INTN State;
if ((This == NULL) || (ChildHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Retrieve the private context data structures
//
IpSb = IP6_SERVICE_FROM_PROTOCOL (This);
Status = gBS->OpenProtocol (
ChildHandle,
&gEfiIp6ProtocolGuid,
(VOID **) &Ip6,
gIp6DriverBinding.DriverBindingHandle,
ChildHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
IpInstance = IP6_INSTANCE_FROM_PROTOCOL (Ip6);
if (IpInstance->Service != IpSb) {
return EFI_INVALID_PARAMETER;
}
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
//
// A child can be destroyed more than once. For example,
// Ip6DriverBindingStop will destory all of its children.
// when UDP driver is being stopped, it will destory all
// the IP child it opens.
//
if (IpInstance->State == IP6_STATE_DESTROY) {
gBS->RestoreTPL (OldTpl);
return EFI_SUCCESS;
}
State = IpInstance->State;
IpInstance->State = IP6_STATE_DESTROY;
//
// Close the Managed Network protocol.
//
gBS->CloseProtocol (
IpSb->MnpChildHandle,
&gEfiManagedNetworkProtocolGuid,
gIp6DriverBinding.DriverBindingHandle,
ChildHandle
);
//
// Uninstall the IP6 protocol first. Many thing happens during
// this:
// 1. The consumer of the IP6 protocol will be stopped if it
// opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
// stopped, IP driver's stop function will be called, and uninstall
// EFI_IP6_PROTOCOL will trigger the UDP's stop function. This
// makes it possible to create the network stack bottom up, and
// stop it top down.
// 2. the upper layer will recycle the received packet. The recycle
// event's TPL is higher than this function. The recycle events
// will be called back before preceeding. If any packets not recycled,
// that means there is a resource leak.
//
Status = gBS->UninstallProtocolInterface (
ChildHandle,
&gEfiIp6ProtocolGuid,
&IpInstance->Ip6Proto
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = Ip6CleanProtocol (IpInstance);
Ip6SetVariableData (IpSb);
if (EFI_ERROR (Status)) {
gBS->InstallMultipleProtocolInterfaces (
&ChildHandle,
&gEfiIp6ProtocolGuid,
Ip6,
NULL
);
goto ON_ERROR;
}
RemoveEntryList (&IpInstance->Link);
ASSERT (IpSb->NumChildren > 0);
IpSb->NumChildren--;
gBS->RestoreTPL (OldTpl);
FreePool (IpInstance);
return EFI_SUCCESS;
ON_ERROR:
IpInstance->State = State;
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@@ -0,0 +1,185 @@
/** @file
The driver binding and service binding protocol for IP6 driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6_DRIVER_H__
#define __EFI_IP6_DRIVER_H__
extern EFI_DRIVER_BINDING_PROTOCOL gIp6DriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL gIp6ComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gIp6ComponentName2;
/**
Clean up an IP6 service binding instance. It releases all
the resource allocated by the instance. The instance may be
partly initialized, or partly destroyed. If a resource is
destroyed, it is marked as that in case the destory failed and
being called again later.
@param[in] IpSb The IP6 service binding instance to clean up.
@retval EFI_SUCCESS The resource used by the instance are cleaned up.
@retval Others Failed to clean up some of the resources.
**/
EFI_STATUS
Ip6CleanService (
IN IP6_SERVICE *IpSb
);
//
// Function prototype for the driver's entry point
//
/**
This is the declaration of an EFI image entry point. This entry point is
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
both device drivers and bus drivers.
The entry point for IP6 driver which installs the driver
binding and component name protocol on its image.
@param[in] ImageHandle The firmware allocated handle for the UEFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
**/
EFI_STATUS
EFIAPI
Ip6DriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
//
// Function prototypes for the Drivr Binding Protocol
//
/**
Test to see if this driver supports ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to test.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to start.
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_ALREADY_STARTED This driver is already running on this device.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
Ip6DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
);
/**
Start this driver on ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to bind driver to.
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
device to start.
@retval EFI_SUCCES This driver is added to ControllerHandle.
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
Ip6DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
);
/**
Stop this driver on ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to stop driver on.
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
of children is zero, stop the entire bus driver.
@param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
if NumberOfChildren is 0.
@retval EFI_SUCCESS The device was stopped.
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
**/
EFI_STATUS
EFIAPI
Ip6DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
);
//
// Function ptototypes for the ServiceBinding Prococol
//
/**
Creates a child handle with a set of I/O services.
@param[in] This Protocol instance pointer.
@param[in] ChildHandle Pointer to the handle of the child to create. If
it is NULL, then a new handle is created. If it
is not NULL, then the I/O services are added to
the existing child handle.
@retval EFI_SUCCES The child handle was created with the I/O services.
@retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
the child.
@retval other The child handle was not created.
**/
EFI_STATUS
EFIAPI
Ip6ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE *ChildHandle
);
/**
Destroys a child handle with a set of I/O services.
@param[in] This Protocol instance pointer.
@param[in] ChildHandle Handle of the child to destroy.
@retval EFI_SUCCES The I/O services were removed from the child
handle.
@retval EFI_UNSUPPORTED The child handle does not support the I/O services
that are being removed.
@retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
@retval EFI_ACCESS_DENIED The child handle could not be destroyed because
its I/O services are being used.
@retval other The child handle was not destroyed.
**/
EFI_STATUS
EFIAPI
Ip6ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
);
#endif

View File

@@ -0,0 +1,100 @@
## @file
# Component description file for Ip6 module.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = Ip6Dxe
FILE_GUID = 5BEDB5CC-D830-4eb2-8742-2D4CC9B54F2C
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = Ip6DriverEntryPoint
UNLOAD_IMAGE = NetLibDefaultUnload
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
# DRIVER_BINDING = gIp6DriverBinding
# COMPONENT_NAME = gIp6ComponentName
# COMPONENT_NAME2 = gIp6ComponentName2
#
[Sources]
Ip6Output.h
Ip6Option.h
Ip6Input.h
Ip6Nd.h
Ip6Mld.h
Ip6Impl.c
Ip6Driver.c
ComponentName.c
Ip6Nd.c
Ip6Input.c
Ip6ConfigImpl.c
Ip6ConfigImpl.h
Ip6Impl.h
Ip6Option.c
Ip6If.h
Ip6Icmp.h
Ip6Mld.c
Ip6Common.c
Ip6Route.c
Ip6If.c
Ip6Driver.h
Ip6Output.c
Ip6Icmp.c
Ip6Common.h
Ip6Route.h
Ip6DxeStrings.uni
Ip6NvData.h
Ip6ConfigNv.c
Ip6ConfigNv.h
Ip6Config.vfr
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DevicePathLib
HiiLib
UefiHiiServicesLib
PrintLib
MemoryAllocationLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiRuntimeServicesTableLib
UefiLib
DebugLib
NetLib
DpcLib
[Protocols]
gEfiManagedNetworkServiceBindingProtocolGuid
gEfiManagedNetworkProtocolGuid
gEfiIp6ServiceBindingProtocolGuid
gEfiIp6ProtocolGuid
gEfiIp6ConfigProtocolGuid
gEfiDhcp6ServiceBindingProtocolGuid
gEfiDhcp6ProtocolGuid
gEfiIpSecProtocolGuid
gEfiHiiConfigAccessProtocolGuid
[Guids]
gEfiIfrTianoGuid ## CONSUMES ## GUID

Binary file not shown.

684
NetworkPkg/Ip6Dxe/Ip6Icmp.c Normal file
View File

@@ -0,0 +1,684 @@
/** @file
The ICMPv6 handle routines to process the ICMPv6 control messages.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ip6Impl.h"
EFI_IP6_ICMP_TYPE mIp6SupportedIcmp[23] = {
{
ICMP_V6_DEST_UNREACHABLE,
ICMP_V6_NO_ROUTE_TO_DEST
},
{
ICMP_V6_DEST_UNREACHABLE,
ICMP_V6_COMM_PROHIBITED
},
{
ICMP_V6_DEST_UNREACHABLE,
ICMP_V6_BEYOND_SCOPE
},
{
ICMP_V6_DEST_UNREACHABLE,
ICMP_V6_ADDR_UNREACHABLE
},
{
ICMP_V6_DEST_UNREACHABLE,
ICMP_V6_PORT_UNREACHABLE
},
{
ICMP_V6_DEST_UNREACHABLE,
ICMP_V6_SOURCE_ADDR_FAILED
},
{
ICMP_V6_DEST_UNREACHABLE,
ICMP_V6_ROUTE_REJECTED
},
{
ICMP_V6_PACKET_TOO_BIG,
ICMP_V6_DEFAULT_CODE
},
{
ICMP_V6_TIME_EXCEEDED,
ICMP_V6_TIMEOUT_HOP_LIMIT
},
{
ICMP_V6_TIME_EXCEEDED,
ICMP_V6_TIMEOUT_REASSEMBLE
},
{
ICMP_V6_PARAMETER_PROBLEM,
ICMP_V6_ERRONEOUS_HEADER
},
{
ICMP_V6_PARAMETER_PROBLEM,
ICMP_V6_UNRECOGNIZE_NEXT_HDR
},
{
ICMP_V6_PARAMETER_PROBLEM,
ICMP_V6_UNRECOGNIZE_OPTION
},
{
ICMP_V6_ECHO_REQUEST,
ICMP_V6_DEFAULT_CODE
},
{
ICMP_V6_ECHO_REPLY,
ICMP_V6_DEFAULT_CODE
},
{
ICMP_V6_LISTENER_QUERY,
ICMP_V6_DEFAULT_CODE
},
{
ICMP_V6_LISTENER_REPORT,
ICMP_V6_DEFAULT_CODE
},
{
ICMP_V6_LISTENER_REPORT_2,
ICMP_V6_DEFAULT_CODE
},
{
ICMP_V6_LISTENER_DONE,
ICMP_V6_DEFAULT_CODE
},
{
ICMP_V6_ROUTER_SOLICIT,
ICMP_V6_DEFAULT_CODE
},
{
ICMP_V6_ROUTER_ADVERTISE,
ICMP_V6_DEFAULT_CODE
},
{
ICMP_V6_NEIGHBOR_SOLICIT,
ICMP_V6_DEFAULT_CODE
},
{
ICMP_V6_NEIGHBOR_ADVERTISE,
ICMP_V6_DEFAULT_CODE
},
};
/**
Reply an ICMPv6 echo request.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the ICMPv6 informational message.
@param[in] Packet The content of the ICMPv6 message with the IP head
removed.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
@retval EFI_SUCCESS Successfully answered the ICMPv6 Echo request.
@retval Others Failed to answer the ICMPv6 Echo request.
**/
EFI_STATUS
Ip6IcmpReplyEcho (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
)
{
IP6_ICMP_INFORMATION_HEAD *Icmp;
NET_BUF *Data;
EFI_STATUS Status;
EFI_IP6_HEADER ReplyHead;
Status = EFI_OUT_OF_RESOURCES;
//
// make a copy the packet, it is really a bad idea to
// send the MNP's buffer back to MNP.
//
Data = NetbufDuplicate (Packet, NULL, IP6_MAX_HEADLEN);
if (Data == NULL) {
goto Exit;
}
//
// Change the ICMP type to echo reply, exchange the source
// and destination, then send it. The source is updated to
// use specific destination. See RFC1122. SRR/RR option
// update is omitted.
//
Icmp = (IP6_ICMP_INFORMATION_HEAD *) NetbufGetByte (Data, 0, NULL);
if (Icmp == NULL) {
NetbufFree (Data);
goto Exit;
}
Icmp->Head.Type = ICMP_V6_ECHO_REPLY;
Icmp->Head.Checksum = 0;
//
// Generate the IPv6 basic header
// If the Echo Reply is a response to a Echo Request sent to one of the node's unicast address,
// the Source address of the Echo Reply must be the same address.
//
ZeroMem (&ReplyHead, sizeof (EFI_IP6_HEADER));
ReplyHead.PayloadLength = HTONS ((UINT16) (Packet->TotalSize));
ReplyHead.NextHeader = IP6_ICMP;
ReplyHead.HopLimit = IpSb->CurHopLimit;
IP6_COPY_ADDRESS (&ReplyHead.DestinationAddress, &Head->SourceAddress);
if (Ip6IsOneOfSetAddress (IpSb, &Head->DestinationAddress, NULL, NULL)) {
IP6_COPY_ADDRESS (&ReplyHead.SourceAddress, &Head->DestinationAddress);
}
//
// If source is unspecified, Ip6Output will select a source for us
//
Status = Ip6Output (
IpSb,
NULL,
NULL,
Data,
&ReplyHead,
NULL,
0,
Ip6SysPacketSent,
NULL
);
Exit:
NetbufFree (Packet);
return Status;
}
/**
Process Packet Too Big message sent by a router in response to a packet that
it cannot forward because the packet is larger than the MTU of outgoing link.
Since this driver already uses IPv6 minimum link MTU as the maximum packet size,
if Packet Too Big message is still received, do not reduce the packet size, but
rather include a Fragment header in the subsequent packets.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the ICMPv6 error packet.
@param[in] Packet The content of the ICMPv6 error with the IP head
removed.
@retval EFI_SUCCESS The ICMPv6 error processed successfully.
@retval EFI_OUT_OF_RESOURCES Failed to finish the operation due to lack of
resource.
@retval EFI_NOT_FOUND The packet too big message is not sent to us.
**/
EFI_STATUS
Ip6ProcessPacketTooBig (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
)
{
IP6_ICMP_ERROR_HEAD Icmp;
UINT32 Mtu;
IP6_ROUTE_ENTRY *RouteEntry;
EFI_IPv6_ADDRESS *DestAddress;
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
Mtu = NTOHL (Icmp.Fourth);
DestAddress = &Icmp.IpHead.DestinationAddress;
if (Mtu < IP6_MIN_LINK_MTU) {
//
// Normally the multicast address is considered to be on-link and not recorded
// in route table. Here it is added into the table since the MTU information
// need be recorded.
//
if (IP6_IS_MULTICAST (DestAddress)) {
RouteEntry = Ip6CreateRouteEntry (DestAddress, 128, NULL);
if (RouteEntry == NULL) {
NetbufFree (Packet);
return EFI_OUT_OF_RESOURCES;
}
RouteEntry->Flag = IP6_DIRECT_ROUTE | IP6_PACKET_TOO_BIG;
InsertHeadList (&IpSb->RouteTable->RouteArea[128], &RouteEntry->Link);
IpSb->RouteTable->TotalNum++;
} else {
RouteEntry = Ip6FindRouteEntry (IpSb->RouteTable, DestAddress, NULL);
if (RouteEntry == NULL) {
NetbufFree (Packet);
return EFI_NOT_FOUND;
}
RouteEntry->Flag = RouteEntry->Flag | IP6_PACKET_TOO_BIG;
Ip6FreeRouteEntry (RouteEntry);
}
}
NetbufFree (Packet);
return EFI_SUCCESS;
}
/**
Process the ICMPv6 error packet, and deliver the packet to upper layer.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the ICMPv6 error packet.
@param[in] Packet The content of the ICMPv6 error with the IP head
removed.
@retval EFI_SUCCESS The ICMPv6 error processed successfully.
@retval EFI_INVALID_PARAMETER The packet is invalid.
@retval Others Failed to process the packet.
**/
EFI_STATUS
Ip6ProcessIcmpError (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
)
{
IP6_ICMP_ERROR_HEAD Icmp;
//
// Check the validity of the packet
//
if (Packet->TotalSize < sizeof (Icmp)) {
goto DROP;
}
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
if (Icmp.Head.Type == ICMP_V6_PACKET_TOO_BIG) {
return Ip6ProcessPacketTooBig (IpSb, Head, Packet);
}
//
// Notify the upper-layer process that an ICMPv6 eror message is received.
//
IP6_GET_CLIP_INFO (Packet)->Status = EFI_ICMP_ERROR;
return Ip6Demultiplex (IpSb, Head, Packet);
DROP:
NetbufFree (Packet);
Packet = NULL;
return EFI_INVALID_PARAMETER;
}
/**
Process the ICMPv6 informational messages. If it is an ICMPv6 echo
request, answer it. If it is a MLD message, trigger MLD routines to
process it. If it is a ND message, trigger ND routines to process it.
Otherwise, deliver it to upper layer.
@param[in] IpSb The IP service that receivd the packet.
@param[in] Head The IP head of the ICMPv6 informational packet.
@param[in] Packet The content of the ICMPv6 informational packet
with IP head removed.
@retval EFI_INVALID_PARAMETER The packet is invalid.
@retval EFI_SUCCESS The ICMPv6 informational message processed.
@retval Others Failed to process ICMPv6 informational message.
**/
EFI_STATUS
Ip6ProcessIcmpInformation (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
)
{
IP6_ICMP_INFORMATION_HEAD Icmp;
EFI_STATUS Status;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
NET_CHECK_SIGNATURE (Packet, NET_BUF_SIGNATURE);
ASSERT (Head != NULL);
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
Status = EFI_INVALID_PARAMETER;
switch (Icmp.Head.Type) {
case ICMP_V6_ECHO_REQUEST:
//
// If ICMPv6 echo, reply it
//
if (Icmp.Head.Code == 0) {
Status = Ip6IcmpReplyEcho (IpSb, Head, Packet);
}
break;
case ICMP_V6_LISTENER_QUERY:
Status = Ip6ProcessMldQuery (IpSb, Head, Packet);
break;
case ICMP_V6_LISTENER_REPORT:
case ICMP_V6_LISTENER_REPORT_2:
Status = Ip6ProcessMldReport (IpSb, Head, Packet);
break;
case ICMP_V6_NEIGHBOR_SOLICIT:
Status = Ip6ProcessNeighborSolicit (IpSb, Head, Packet);
break;
case ICMP_V6_NEIGHBOR_ADVERTISE:
Status = Ip6ProcessNeighborAdvertise (IpSb, Head, Packet);
break;
case ICMP_V6_ROUTER_ADVERTISE:
Status = Ip6ProcessRouterAdvertise (IpSb, Head, Packet);
break;
case ICMP_V6_REDIRECT:
Status = Ip6ProcessRedirect (IpSb, Head, Packet);
break;
case ICMP_V6_ECHO_REPLY:
Status = Ip6Demultiplex (IpSb, Head, Packet);
break;
default:
Status = EFI_INVALID_PARAMETER;
break;
}
return Status;
}
/**
Handle the ICMPv6 packet. First validate the message format,
then, according to the message types, process it as an informational packet or
an error packet.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the ICMPv6 packet.
@param[in] Packet The content of the ICMPv6 packet with IP head
removed.
@retval EFI_INVALID_PARAMETER The packet is malformated.
@retval EFI_SUCCESS The ICMPv6 message successfully processed.
@retval Others Failed to handle the ICMPv6 packet.
**/
EFI_STATUS
Ip6IcmpHandle (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
)
{
IP6_ICMP_HEAD Icmp;
UINT16 PseudoCheckSum;
UINT16 CheckSum;
//
// Check the validity of the incoming packet.
//
if (Packet->TotalSize < sizeof (Icmp)) {
goto DROP;
}
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
//
// Make sure checksum is valid.
//
PseudoCheckSum = NetIp6PseudoHeadChecksum (
&Head->SourceAddress,
&Head->DestinationAddress,
IP6_ICMP,
Packet->TotalSize
);
CheckSum = (UINT16) ~NetAddChecksum (PseudoCheckSum, NetbufChecksum (Packet));
if (CheckSum != 0) {
goto DROP;
}
//
// According to the packet type, call corresponding process
//
if (Icmp.Type <= ICMP_V6_ERROR_MAX) {
return Ip6ProcessIcmpError (IpSb, Head, Packet);
} else {
return Ip6ProcessIcmpInformation (IpSb, Head, Packet);
}
DROP:
NetbufFree (Packet);
return EFI_INVALID_PARAMETER;
}
/**
Retrieve the Prefix address according to the PrefixLength by clear the useless
bits.
@param[in] PrefixLength The prefix length of the prefix.
@param[in, out] Prefix On input, points to the original prefix address
with dirty bits; on output, points to the updated
address with useless bit clear.
**/
VOID
Ip6GetPrefix (
IN UINT8 PrefixLength,
IN OUT EFI_IPv6_ADDRESS *Prefix
)
{
UINT8 Byte;
UINT8 Bit;
UINT8 Mask;
UINT8 Value;
ASSERT ((Prefix != NULL) && (PrefixLength < IP6_PREFIX_NUM));
if (PrefixLength == 0) {
ZeroMem (Prefix, sizeof (EFI_IPv6_ADDRESS));
return ;
}
if (PrefixLength == IP6_PREFIX_NUM - 1) {
return ;
}
Byte = (UINT8) (PrefixLength / 8);
Bit = (UINT8) (PrefixLength % 8);
Value = Prefix->Addr[Byte];
if ((Byte > 0) && (Byte < 16)) {
ZeroMem (Prefix->Addr + Byte, 16 - Byte);
}
if (Bit > 0) {
Mask = (UINT8) (0xFF << (8 - Bit));
Prefix->Addr[Byte] = (UINT8) (Value & Mask);
}
}
/**
Check whether the DestinationAddress is an anycast address.
@param[in] IpSb The IP service that received the packet.
@param[in] DestinationAddress Points to the Destination Address of the packet.
@retval TRUE The DestinationAddress is anycast address.
@retval FALSE The DestinationAddress is not anycast address.
**/
BOOLEAN
Ip6IsAnycast (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *DestinationAddress
)
{
IP6_PREFIX_LIST_ENTRY *PrefixEntry;
EFI_IPv6_ADDRESS Prefix;
BOOLEAN Flag;
ZeroMem (&Prefix, sizeof (EFI_IPv6_ADDRESS));
Flag = FALSE;
//
// If the address is known as on-link or autonomous prefix, record it as
// anycast address.
//
do {
PrefixEntry = Ip6FindPrefixListEntry (IpSb, Flag, 255, DestinationAddress);
if (PrefixEntry != NULL) {
IP6_COPY_ADDRESS (&Prefix, &PrefixEntry->Prefix);
Ip6GetPrefix (PrefixEntry->PrefixLength, &Prefix);
if (EFI_IP6_EQUAL (&Prefix, DestinationAddress)) {
return TRUE;
}
}
Flag = (BOOLEAN) !Flag;
} while (Flag);
return FALSE;
}
/**
Generate ICMPv6 error message and send it out to DestinationAddress. Currently
Destination Unreachable message, Time Exceeded message and Parameter Problem
message are supported.
@param[in] IpSb The IP service that received the packet.
@param[in] Packet The packet which invoking ICMPv6 error.
@param[in] SourceAddress If not NULL, points to the SourceAddress.
Otherwise, the IP layer will select a source address
according to the DestinationAddress.
@param[in] DestinationAddress Points to the Destination Address of the ICMPv6
error message.
@param[in] Type The type of the ICMPv6 message.
@param[in] Code The additional level of the ICMPv6 message.
@param[in] Pointer If not NULL, identifies the octet offset within
the invoking packet where the error was detected.
@retval EFI_INVALID_PARAMETER The packet is malformated.
@retval EFI_OUT_OF_RESOURCES There is no sufficient resource to complete the
operation.
@retval EFI_SUCCESS The ICMPv6 message was successfully sent out.
@retval Others Failed to generate the ICMPv6 packet.
**/
EFI_STATUS
Ip6SendIcmpError (
IN IP6_SERVICE *IpSb,
IN NET_BUF *Packet,
IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
IN EFI_IPv6_ADDRESS *DestinationAddress,
IN UINT8 Type,
IN UINT8 Code,
IN UINT32 *Pointer OPTIONAL
)
{
UINT32 PacketLen;
NET_BUF *ErrorMsg;
UINT16 PayloadLen;
EFI_IP6_HEADER Head;
IP6_ICMP_INFORMATION_HEAD *IcmpHead;
UINT8 *ErrorBody;
if (DestinationAddress == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// An ICMPv6 error message must not be originated as a result of receiving
// a packet whose source address does not uniquely identify a single node --
// e.g., the IPv6 Unspecified Address, an IPv6 multicast address, or an address
// known by the ICMP message originator to be an IPv6 anycast address.
//
if (NetIp6IsUnspecifiedAddr (DestinationAddress) ||
IP6_IS_MULTICAST (DestinationAddress) ||
Ip6IsAnycast (IpSb, DestinationAddress)
) {
return EFI_INVALID_PARAMETER;
}
switch (Type) {
case ICMP_V6_DEST_UNREACHABLE:
case ICMP_V6_TIME_EXCEEDED:
break;
case ICMP_V6_PARAMETER_PROBLEM:
if (Pointer == NULL) {
return EFI_INVALID_PARAMETER;
}
break;
default:
return EFI_INVALID_PARAMETER;
}
PacketLen = sizeof (IP6_ICMP_ERROR_HEAD) + Packet->TotalSize;
if (PacketLen > IpSb->MaxPacketSize) {
PacketLen = IpSb->MaxPacketSize;
}
ErrorMsg = NetbufAlloc (PacketLen);
if (ErrorMsg == NULL) {
return EFI_OUT_OF_RESOURCES;
}
PayloadLen = (UINT16) (PacketLen - sizeof (EFI_IP6_HEADER));
//
// Create the basic IPv6 header.
//
ZeroMem (&Head, sizeof (EFI_IP6_HEADER));
Head.PayloadLength = HTONS (PayloadLen);
Head.NextHeader = IP6_ICMP;
Head.HopLimit = IpSb->CurHopLimit;
if (SourceAddress != NULL) {
IP6_COPY_ADDRESS (&Head.SourceAddress, SourceAddress);
} else {
ZeroMem (&Head.SourceAddress, sizeof (EFI_IPv6_ADDRESS));
}
IP6_COPY_ADDRESS (&Head.DestinationAddress, DestinationAddress);
NetbufReserve (ErrorMsg, sizeof (EFI_IP6_HEADER));
//
// Fill in the ICMP error message head
//
IcmpHead = (IP6_ICMP_INFORMATION_HEAD *) NetbufAllocSpace (ErrorMsg, sizeof (IP6_ICMP_INFORMATION_HEAD), FALSE);
if (IcmpHead == NULL) {
NetbufFree (ErrorMsg);
return EFI_OUT_OF_RESOURCES;
}
ZeroMem (IcmpHead, sizeof (IP6_ICMP_INFORMATION_HEAD));
IcmpHead->Head.Type = Type;
IcmpHead->Head.Code = Code;
if (Pointer != NULL) {
IcmpHead->Fourth = HTONL (*Pointer);
}
//
// Fill in the ICMP error message body
//
PayloadLen -= sizeof (IP6_ICMP_INFORMATION_HEAD);
ErrorBody = NetbufAllocSpace (ErrorMsg, PayloadLen, FALSE);
if (ErrorBody != NULL) {
ZeroMem (ErrorBody, PayloadLen);
NetbufCopy (Packet, 0, PayloadLen, ErrorBody);
}
//
// Transmit the packet
//
return Ip6Output (IpSb, NULL, NULL, ErrorMsg, &Head, NULL, 0, Ip6SysPacketSent, NULL);
}

108
NetworkPkg/Ip6Dxe/Ip6Icmp.h Normal file
View File

@@ -0,0 +1,108 @@
/** @file
Header file for ICMPv6 protocol.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6_ICMP_H__
#define __EFI_IP6_ICMP_H__
#define ICMP_V6_DEFAULT_CODE 0
#define ICMP_V6_ERROR_MAX 127
//
// ICMPv6 message classes, each class of ICMPv6 message shares
// a common message format. INVALID_MESSAGE is only a flag.
//
#define ICMP_V6_INVALID_MESSAGE 0
#define ICMP_V6_ERROR_MESSAGE 1
#define ICMP_V6_INFORMATION_MESSAGE 2
extern EFI_IP6_ICMP_TYPE mIp6SupportedIcmp[];
/**
Handle the ICMPv6 packet. First validate the message format,
then, according to the message types, process it as an informational packet or
an error packet.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the ICMPv6 packet.
@param[in] Packet The content of the ICMPv6 packet with IP head
removed.
@retval EFI_INVALID_PARAMETER The packet is malformated.
@retval EFI_SUCCESS The ICMPv6 message successfully processed.
@retval Others Failed to handle the ICMPv6 packet.
**/
EFI_STATUS
Ip6IcmpHandle (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
);
/**
Check whether the DestinationAddress is an anycast address.
@param[in] IpSb The IP service that received the packet.
@param[in] DestinationAddress Points to the Destination Address of the packet.
@retval TRUE The DestinationAddress is anycast address.
@retval FALSE The DestinationAddress is not anycast address.
**/
BOOLEAN
Ip6IsAnycast (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *DestinationAddress
);
/**
Generate ICMPv6 error message and send it out to DestinationAddress. Currently
Destination Unreachable message, Time Exceeded message and Parameter Problem
message are supported.
@param[in] IpSb The IP service that received the packet.
@param[in] Packet The packet which invoking ICMPv6 error.
@param[in] SourceAddress If not NULL, points to the SourceAddress.
Otherwise, the IP layer will select a source address
according to the DestinationAddress.
@param[in] DestinationAddress Points to the Destination Address of the ICMPv6
error message.
@param[in] Type The type of the ICMPv6 message.
@param[in] Code The additional level of the ICMPv6 message.
@param[in] Pointer If not NULL, identifies the octet offset within
the invoking packet where the error was detected.
@retval EFI_INVALID_PARAMETER The packet is malformated.
@retval EFI_OUT_OF_RESOURCES There is no sufficient resource to complete the
operation.
@retval EFI_SUCCESS The ICMPv6 message was successfully sent out.
@retval Others Failed to generate the ICMPv6 packet.
**/
EFI_STATUS
Ip6SendIcmpError (
IN IP6_SERVICE *IpSb,
IN NET_BUF *Packet,
IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
IN EFI_IPv6_ADDRESS *DestinationAddress,
IN UINT8 Type,
IN UINT8 Code,
IN UINT32 *Pointer OPTIONAL
);
#endif

802
NetworkPkg/Ip6Dxe/Ip6If.c Normal file
View File

@@ -0,0 +1,802 @@
/** @file
Implement IP6 pesudo interface.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ip6Impl.h"
/**
Request Ip6OnFrameSentDpc as a DPC at TPL_CALLBACK.
@param[in] Event The transmit token's event.
@param[in] Context The Context which is pointed to the token.
**/
VOID
EFIAPI
Ip6OnFrameSent (
IN EFI_EVENT Event,
IN VOID *Context
);
/**
Fileter function to cancel all the frame related to an IP instance.
@param[in] Frame The transmit request to test whether to cancel.
@param[in] Context The context which is the Ip instance that issued
the transmit.
@retval TRUE The frame belongs to this instance and is to be
removed.
@retval FALSE The frame doesn't belong to this instance.
**/
BOOLEAN
Ip6CancelInstanceFrame (
IN IP6_LINK_TX_TOKEN *Frame,
IN VOID *Context
)
{
if (Frame->IpInstance == (IP6_PROTOCOL *) Context) {
return TRUE;
}
return FALSE;
}
/**
Set the interface's address. This will trigger the DAD process for the
address to set. To set an already set address, the lifetimes wil be
updated to the new value passed in.
@param[in] Interface The interface to set the address.
@param[in] Ip6Addr The interface's to be assigned IPv6 address.
@param[in] IsAnycast If TRUE, the unicast IPv6 address is anycast.
Otherwise, it is not anycast.
@param[in] PrefixLength The prefix length of the Ip6Addr.
@param[in] ValidLifetime The valid lifetime for this address.
@param[in] PreferredLifetime The preferred lifetime for this address.
@param[in] DadCallback The caller's callback to trigger when DAD finishes.
This is an optional parameter that may be NULL.
@param[in] Context The context that will be passed to DadCallback.
This is an optional parameter that may be NULL.
@retval EFI_SUCCESS The interface is scheduled to be configured with
the specified address.
@retval EFI_OUT_OF_RESOURCES Failed to set the interface's address due to
lack of resources.
**/
EFI_STATUS
Ip6SetAddress (
IN IP6_INTERFACE *Interface,
IN EFI_IPv6_ADDRESS *Ip6Addr,
IN BOOLEAN IsAnycast,
IN UINT8 PrefixLength,
IN UINT32 ValidLifetime,
IN UINT32 PreferredLifetime,
IN IP6_DAD_CALLBACK DadCallback OPTIONAL,
IN VOID *Context OPTIONAL
)
{
IP6_SERVICE *IpSb;
IP6_ADDRESS_INFO *AddressInfo;
LIST_ENTRY *Entry;
IP6_PREFIX_LIST_ENTRY *PrefixEntry;
UINT64 Delay;
IP6_DELAY_JOIN_LIST *DelayNode;
NET_CHECK_SIGNATURE (Interface, IP6_INTERFACE_SIGNATURE);
IpSb = Interface->Service;
if (Ip6IsOneOfSetAddress (IpSb, Ip6Addr, NULL, &AddressInfo)) {
ASSERT (AddressInfo != NULL);
//
// Update the lifetime.
//
AddressInfo->ValidLifetime = ValidLifetime;
AddressInfo->PreferredLifetime = PreferredLifetime;
if (DadCallback != NULL) {
DadCallback (TRUE, Ip6Addr, Context);
}
return EFI_SUCCESS;
}
AddressInfo = (IP6_ADDRESS_INFO *) AllocatePool (sizeof (IP6_ADDRESS_INFO));
if (AddressInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
AddressInfo->Signature = IP6_ADDR_INFO_SIGNATURE;
IP6_COPY_ADDRESS (&AddressInfo->Address, Ip6Addr);
AddressInfo->IsAnycast = IsAnycast;
AddressInfo->PrefixLength = PrefixLength;
AddressInfo->ValidLifetime = ValidLifetime;
AddressInfo->PreferredLifetime = PreferredLifetime;
if (AddressInfo->PrefixLength == 0) {
//
// Find an appropriate prefix from on-link prefixes and update the prefixlength.
// Longest prefix match is used here.
//
NET_LIST_FOR_EACH (Entry, &IpSb->OnlinkPrefix) {
PrefixEntry = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
if (NetIp6IsNetEqual (&PrefixEntry->Prefix, &AddressInfo->Address, PrefixEntry->PrefixLength)) {
AddressInfo->PrefixLength = PrefixEntry->PrefixLength;
break;
}
}
}
if (AddressInfo->PrefixLength == 0) {
//
// If the prefix length is still zero, try the autonomous prefixes.
// Longest prefix match is used here.
//
NET_LIST_FOR_EACH (Entry, &IpSb->AutonomousPrefix) {
PrefixEntry = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
if (NetIp6IsNetEqual (&PrefixEntry->Prefix, &AddressInfo->Address, PrefixEntry->PrefixLength)) {
AddressInfo->PrefixLength = PrefixEntry->PrefixLength;
break;
}
}
}
if (AddressInfo->PrefixLength == 0) {
//
// BUGBUG: Stil fail, use 64 as the default prefix length.
//
AddressInfo->PrefixLength = IP6_LINK_LOCAL_PREFIX_LENGTH;
}
//
// Node should delay joining the solicited-node mulitcast address by a random delay
// between 0 and MAX_RTR_SOLICITATION_DELAY (1 second).
// Thus queue the address to be processed in Duplicate Address Detection module
// after the delay time (in milliseconds).
//
Delay = (UINT64) NET_RANDOM (NetRandomInitSeed ());
Delay = MultU64x32 (Delay, IP6_ONE_SECOND_IN_MS);
Delay = RShiftU64 (Delay, 32);
DelayNode = (IP6_DELAY_JOIN_LIST *) AllocatePool (sizeof (IP6_DELAY_JOIN_LIST));
if (DelayNode == NULL) {
FreePool (AddressInfo);
return EFI_OUT_OF_RESOURCES;
}
DelayNode->DelayTime = (UINT32) (DivU64x32 (Delay, IP6_TIMER_INTERVAL_IN_MS));
DelayNode->Interface = Interface;
DelayNode->AddressInfo = AddressInfo;
DelayNode->DadCallback = DadCallback;
DelayNode->Context = Context;
InsertTailList (&Interface->DelayJoinList, &DelayNode->Link);
return EFI_SUCCESS;
}
/**
Create an IP6_INTERFACE.
@param[in] IpSb The IP6 service binding instance.
@param[in] LinkLocal If TRUE, the instance is created for link-local address.
Otherwise, it is not for a link-local address.
@return Point to the created IP6_INTERFACE, otherwise NULL.
**/
IP6_INTERFACE *
Ip6CreateInterface (
IN IP6_SERVICE *IpSb,
IN BOOLEAN LinkLocal
)
{
EFI_STATUS Status;
IP6_INTERFACE *Interface;
EFI_IPv6_ADDRESS *Ip6Addr;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
Interface = AllocatePool (sizeof (IP6_INTERFACE));
if (Interface == NULL) {
return NULL;
}
Interface->Signature = IP6_INTERFACE_SIGNATURE;
Interface->RefCnt = 1;
InitializeListHead (&Interface->AddressList);
Interface->AddressCount = 0;
Interface->Configured = FALSE;
Interface->Service = IpSb;
Interface->Controller = IpSb->Controller;
Interface->Image = IpSb->Image;
InitializeListHead (&Interface->ArpQues);
InitializeListHead (&Interface->SentFrames);
Interface->DupAddrDetect = IpSb->Ip6ConfigInstance.DadXmits.DupAddrDetectTransmits;
InitializeListHead (&Interface->DupAddrDetectList);
InitializeListHead (&Interface->DelayJoinList);
InitializeListHead (&Interface->IpInstances);
Interface->PromiscRecv = FALSE;
if (!LinkLocal) {
return Interface;
}
//
// Get the link local addr
//
Ip6Addr = Ip6CreateLinkLocalAddr (IpSb);
if (Ip6Addr == NULL) {
goto ON_ERROR;
}
//
// Perform DAD - Duplicate Address Detection.
//
Status = Ip6SetAddress (
Interface,
Ip6Addr,
FALSE,
IP6_LINK_LOCAL_PREFIX_LENGTH,
(UINT32) IP6_INFINIT_LIFETIME,
(UINT32) IP6_INFINIT_LIFETIME,
NULL,
NULL
);
FreePool (Ip6Addr);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
return Interface;
ON_ERROR:
FreePool (Interface);
return NULL;
}
/**
Free the interface used by IpInstance. All the IP instance with
the same Ip/prefix pair share the same interface. It is reference
counted. All the frames that haven't been sent will be cancelled.
Because the IpInstance is optional, the caller must remove
IpInstance from the interface's instance list.
@param[in] Interface The interface used by the IpInstance.
@param[in] IpInstance The IP instance that free the interface. NULL if
the IP driver is releasing the default interface.
**/
VOID
Ip6CleanInterface (
IN IP6_INTERFACE *Interface,
IN IP6_PROTOCOL *IpInstance OPTIONAL
)
{
IP6_DAD_ENTRY *Duplicate;
IP6_DELAY_JOIN_LIST *Delay;
NET_CHECK_SIGNATURE (Interface, IP6_INTERFACE_SIGNATURE);
ASSERT (Interface->RefCnt > 0);
//
// Remove all the pending transmit token related to this IP instance.
//
Ip6CancelFrames (Interface, EFI_ABORTED, Ip6CancelInstanceFrame, IpInstance);
if (--Interface->RefCnt > 0) {
return;
}
//
// Destory the interface if this is the last IP instance.
// Remove all the system transmitted packets
// from this interface, cancel the receive request if exists.
//
Ip6CancelFrames (Interface, EFI_ABORTED, Ip6CancelInstanceFrame, NULL);
ASSERT (IsListEmpty (&Interface->IpInstances));
ASSERT (IsListEmpty (&Interface->ArpQues));
ASSERT (IsListEmpty (&Interface->SentFrames));
while (!IsListEmpty (&Interface->DupAddrDetectList)) {
Duplicate = NET_LIST_HEAD (&Interface->DupAddrDetectList, IP6_DAD_ENTRY, Link);
NetListRemoveHead (&Interface->DupAddrDetectList);
FreePool (Duplicate);
}
while (!IsListEmpty (&Interface->DelayJoinList)) {
Delay = NET_LIST_HEAD (&Interface->DelayJoinList, IP6_DELAY_JOIN_LIST, Link);
NetListRemoveHead (&Interface->DelayJoinList);
FreePool (Delay);
}
Ip6RemoveAddr (Interface->Service, &Interface->AddressList, &Interface->AddressCount, NULL, 0);
RemoveEntryList (&Interface->Link);
FreePool (Interface);
}
/**
Create and wrap a transmit request into a newly allocated IP6_LINK_TX_TOKEN.
@param[in] Interface The interface to send out from.
@param[in] IpInstance The IpInstance that transmit the packet. NULL if
the packet is sent by the IP6 driver itself.
@param[in] Packet The packet to transmit
@param[in] CallBack Call back function to execute if transmission
finished.
@param[in] Context Opaque parameter to the callback.
@return The wrapped token if succeed or NULL.
**/
IP6_LINK_TX_TOKEN *
Ip6CreateLinkTxToken (
IN IP6_INTERFACE *Interface,
IN IP6_PROTOCOL *IpInstance OPTIONAL,
IN NET_BUF *Packet,
IN IP6_FRAME_CALLBACK CallBack,
IN VOID *Context
)
{
EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
EFI_MANAGED_NETWORK_TRANSMIT_DATA *MnpTxData;
IP6_LINK_TX_TOKEN *Token;
EFI_STATUS Status;
UINT32 Count;
Token = AllocatePool (sizeof (IP6_LINK_TX_TOKEN) + (Packet->BlockOpNum - 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA));
if (Token == NULL) {
return NULL;
}
Token->Signature = IP6_LINK_TX_SIGNATURE;
InitializeListHead (&Token->Link);
Token->IpInstance = IpInstance;
Token->CallBack = CallBack;
Token->Packet = Packet;
Token->Context = Context;
ZeroMem (&Token->DstMac, sizeof (EFI_MAC_ADDRESS));
IP6_COPY_LINK_ADDRESS (&Token->SrcMac, &Interface->Service->SnpMode.CurrentAddress);
MnpToken = &(Token->MnpToken);
MnpToken->Status = EFI_NOT_READY;
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
Ip6OnFrameSent,
Token,
&MnpToken->Event
);
if (EFI_ERROR (Status)) {
FreePool (Token);
return NULL;
}
MnpTxData = &Token->MnpTxData;
MnpToken->Packet.TxData = MnpTxData;
MnpTxData->DestinationAddress = &Token->DstMac;
MnpTxData->SourceAddress = &Token->SrcMac;
MnpTxData->ProtocolType = IP6_ETHER_PROTO;
MnpTxData->DataLength = Packet->TotalSize;
MnpTxData->HeaderLength = 0;
Count = Packet->BlockOpNum;
NetbufBuildExt (Packet, (NET_FRAGMENT *) MnpTxData->FragmentTable, &Count);
MnpTxData->FragmentCount = (UINT16)Count;
return Token;
}
/**
Free the link layer transmit token. It will close the event,
then free the memory used.
@param[in] Token Token to free.
**/
VOID
Ip6FreeLinkTxToken (
IN IP6_LINK_TX_TOKEN *Token
)
{
NET_CHECK_SIGNATURE (Token, IP6_LINK_TX_SIGNATURE);
gBS->CloseEvent (Token->MnpToken.Event);
FreePool (Token);
}
/**
Callback function when the received packet is freed.
Check Ip6OnFrameReceived for information.
@param[in] Context Points to EFI_MANAGED_NETWORK_RECEIVE_DATA.
**/
VOID
EFIAPI
Ip6RecycleFrame (
IN VOID *Context
)
{
EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData;
RxData = (EFI_MANAGED_NETWORK_RECEIVE_DATA *) Context;
gBS->SignalEvent (RxData->RecycleEvent);
}
/**
Received a frame from MNP. Wrap it in net buffer then deliver
it to IP's input function. The ownship of the packet also
is transferred to IP. When Ip is finished with this packet, it
will call NetbufFree to release the packet, NetbufFree will
again call the Ip6RecycleFrame to signal MNP's event and free
the token used.
@param[in] Context Context for the callback.
**/
VOID
EFIAPI
Ip6OnFrameReceivedDpc (
IN VOID *Context
)
{
EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
EFI_MANAGED_NETWORK_RECEIVE_DATA *MnpRxData;
IP6_LINK_RX_TOKEN *Token;
NET_FRAGMENT Netfrag;
NET_BUF *Packet;
UINT32 Flag;
IP6_SERVICE *IpSb;
Token = (IP6_LINK_RX_TOKEN *) Context;
NET_CHECK_SIGNATURE (Token, IP6_LINK_RX_SIGNATURE);
//
// First clear the interface's receive request in case the
// caller wants to call Ip6ReceiveFrame in the callback.
//
IpSb = (IP6_SERVICE *) Token->Context;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
MnpToken = &Token->MnpToken;
MnpRxData = MnpToken->Packet.RxData;
if (EFI_ERROR (MnpToken->Status) || (MnpRxData == NULL)) {
Token->CallBack (NULL, MnpToken->Status, 0, Token->Context);
return ;
}
//
// Wrap the frame in a net buffer then deliever it to IP input.
// IP will reassemble the packet, and deliver it to upper layer
//
Netfrag.Len = MnpRxData->DataLength;
Netfrag.Bulk = MnpRxData->PacketData;
Packet = NetbufFromExt (&Netfrag, 1, IP6_MAX_HEADLEN, 0, Ip6RecycleFrame, Token->MnpToken.Packet.RxData);
if (Packet == NULL) {
gBS->SignalEvent (MnpRxData->RecycleEvent);
Token->CallBack (NULL, EFI_OUT_OF_RESOURCES, 0, Token->Context);
return ;
}
Flag = (MnpRxData->BroadcastFlag ? IP6_LINK_BROADCAST : 0);
Flag |= (MnpRxData->MulticastFlag ? IP6_LINK_MULTICAST : 0);
Flag |= (MnpRxData->PromiscuousFlag ? IP6_LINK_PROMISC : 0);
Token->CallBack (Packet, EFI_SUCCESS, Flag, Token->Context);
}
/**
Request Ip6OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
@param Event The receive event delivered to MNP for receive.
@param Context Context for the callback.
**/
VOID
EFIAPI
Ip6OnFrameReceived (
IN EFI_EVENT Event,
IN VOID *Context
)
{
//
// Request Ip6OnFrameReceivedDpc as a DPC at TPL_CALLBACK
//
QueueDpc (TPL_CALLBACK, Ip6OnFrameReceivedDpc, Context);
}
/**
Request to receive the packet from the interface.
@param[in] CallBack Function to call when receive finished.
@param[in] IpSb Points to IP6 service binding instance.
@retval EFI_ALREADY_STARTED There is already a pending receive request.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.
@retval EFI_SUCCESS The recieve request has been started.
**/
EFI_STATUS
Ip6ReceiveFrame (
IN IP6_FRAME_CALLBACK CallBack,
IN IP6_SERVICE *IpSb
)
{
EFI_STATUS Status;
IP6_LINK_RX_TOKEN *Token;
if (IpSb->InDestroy) {
return EFI_INVALID_PARAMETER;
}
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
Token = &IpSb->RecvRequest;
Token->CallBack = CallBack;
Token->Context = (VOID *) IpSb;
Status = IpSb->Mnp->Receive (IpSb->Mnp, &Token->MnpToken);
if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS;
}
/**
Callback funtion when frame transmission is finished. It will
call the frame owner's callback function to tell it the result.
@param[in] Context Context which points to the token.
**/
VOID
EFIAPI
Ip6OnFrameSentDpc (
IN VOID *Context
)
{
IP6_LINK_TX_TOKEN *Token;
Token = (IP6_LINK_TX_TOKEN *) Context;
NET_CHECK_SIGNATURE (Token, IP6_LINK_TX_SIGNATURE);
RemoveEntryList (&Token->Link);
Token->CallBack (
Token->Packet,
Token->MnpToken.Status,
0,
Token->Context
);
Ip6FreeLinkTxToken (Token);
}
/**
Request Ip6OnFrameSentDpc as a DPC at TPL_CALLBACK.
@param[in] Event The transmit token's event.
@param[in] Context Context which points to the token.
**/
VOID
EFIAPI
Ip6OnFrameSent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
//
// Request Ip6OnFrameSentDpc as a DPC at TPL_CALLBACK
//
QueueDpc (TPL_CALLBACK, Ip6OnFrameSentDpc, Context);
}
/**
Send a frame from the interface. If the next hop is a multicast address,
it is transmitted immediately. If the next hop is a unicast,
and the NextHop's MAC is not known, it will perform address resolution.
If an error occurred, the CallBack won't be called. So, the caller
must test the return value, and take action when there is an error.
@param[in] Interface The interface to send the frame from
@param[in] IpInstance The IP child that request the transmission.
NULL if it is the IP6 driver itself.
@param[in] Packet The packet to transmit.
@param[in] NextHop The immediate destination to transmit the packet to.
@param[in] CallBack Function to call back when transmit finished.
@param[in] Context Opaque parameter to the callback.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame.
@retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop.
@retval EFI_SUCCESS The packet successfully transmitted.
**/
EFI_STATUS
Ip6SendFrame (
IN IP6_INTERFACE *Interface,
IN IP6_PROTOCOL *IpInstance OPTIONAL,
IN NET_BUF *Packet,
IN EFI_IPv6_ADDRESS *NextHop,
IN IP6_FRAME_CALLBACK CallBack,
IN VOID *Context
)
{
IP6_SERVICE *IpSb;
IP6_LINK_TX_TOKEN *Token;
EFI_STATUS Status;
IP6_NEIGHBOR_ENTRY *NeighborCache;
LIST_ENTRY *Entry;
IP6_NEIGHBOR_ENTRY *ArpQue;
IpSb = Interface->Service;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
//
// Only when link local address is performing DAD, the interface could be used in unconfigured.
//
if (IpSb->LinkLocalOk) {
ASSERT (Interface->Configured);
}
Token = Ip6CreateLinkTxToken (Interface, IpInstance, Packet, CallBack, Context);
if (Token == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (IP6_IS_MULTICAST (NextHop)) {
Status = Ip6GetMulticastMac (IpSb->Mnp, NextHop, &Token->DstMac);
if (EFI_ERROR (Status)) {
goto Error;
}
goto SendNow;
}
//
// If send to itself, directly send out
//
if (EFI_IP6_EQUAL (&Packet->Ip.Ip6->DestinationAddress, &Packet->Ip.Ip6->SourceAddress)) {
IP6_COPY_LINK_ADDRESS (&Token->DstMac, &IpSb->SnpMode.CurrentAddress);
goto SendNow;
}
//
// If unicast, check the neighbor state.
//
NeighborCache = Ip6FindNeighborEntry (IpSb, NextHop);
ASSERT (NeighborCache != NULL);
if (NeighborCache->Interface == NULL) {
NeighborCache->Interface = Interface;
}
switch (NeighborCache->State) {
case EfiNeighborStale:
NeighborCache->State = EfiNeighborDelay;
NeighborCache->Ticks = (UINT32) IP6_GET_TICKS (IP6_DELAY_FIRST_PROBE_TIME);
//
// Fall through
//
case EfiNeighborReachable:
case EfiNeighborDelay:
case EfiNeighborProbe:
IP6_COPY_LINK_ADDRESS (&Token->DstMac, &NeighborCache->LinkAddress);
goto SendNow;
break;
default:
break;
}
//
// Have to do asynchronous ARP resolution. First check whether there is
// already a pending request.
//
NET_LIST_FOR_EACH (Entry, &Interface->ArpQues) {
ArpQue = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, ArpList);
if (ArpQue == NeighborCache) {
InsertTailList (&NeighborCache->Frames, &Token->Link);
NeighborCache->ArpFree = TRUE;
return EFI_SUCCESS;
}
}
//
// First frame requires ARP.
//
InsertTailList (&NeighborCache->Frames, &Token->Link);
InsertTailList (&Interface->ArpQues, &NeighborCache->ArpList);
NeighborCache->ArpFree = TRUE;
return EFI_SUCCESS;
SendNow:
//
// Insert the tx token into the SentFrames list before calling Mnp->Transmit.
// Remove it if the returned status is not EFI_SUCCESS.
//
InsertTailList (&Interface->SentFrames, &Token->Link);
Status = IpSb->Mnp->Transmit (IpSb->Mnp, &Token->MnpToken);
if (EFI_ERROR (Status)) {
RemoveEntryList (&Token->Link);
goto Error;
}
return EFI_SUCCESS;
Error:
Ip6FreeLinkTxToken (Token);
return Status;
}
/**
The heartbeat timer of IP6 service instance. It times out
all of its IP6 children's received-but-not-delivered and
transmitted-but-not-recycle packets.
@param[in] Event The IP6 service instance's heartbeat timer.
@param[in] Context The IP6 service instance.
**/
VOID
EFIAPI
Ip6TimerTicking (
IN EFI_EVENT Event,
IN VOID *Context
)
{
IP6_SERVICE *IpSb;
IpSb = (IP6_SERVICE *) Context;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
Ip6PacketTimerTicking (IpSb);
Ip6NdTimerTicking (IpSb);
Ip6MldTimerTicking (IpSb);
}

267
NetworkPkg/Ip6Dxe/Ip6If.h Normal file
View File

@@ -0,0 +1,267 @@
/** @file
Definition for IP6 pesudo interface structure.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6_IF_H__
#define __EFI_IP6_IF_H__
#define IP6_LINK_RX_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'R')
#define IP6_LINK_TX_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'T')
#define IP6_INTERFACE_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'I')
#define IP6_ADDR_INFO_SIGNATURE SIGNATURE_32 ('I', 'P', 'A', 'I')
//
// This prototype is used by both receive and transmission.
// When receiving Netbuf is allocated by IP6_INTERFACE, and
// released by IP6. Flag shows whether the frame is received
// as unicast/multicast/anycast...
//
// When transmitting, the Netbuf is from IP6, and provided
// to the callback as a reference. Flag isn't used.
//
// IpInstance can be NULL which means that it is the IP6 driver
// itself sending the packets. IP6 driver may send packets that
// don't belong to any instance, such as ICMP errors, ICMP
// informational packets. IpInstance is used as a tag in
// this module.
//
typedef
VOID
(*IP6_FRAME_CALLBACK) (
NET_BUF *Packet,
EFI_STATUS IoStatus,
UINT32 LinkFlag,
VOID *Context
);
//
// Each receive request is wrapped in an IP6_LINK_RX_TOKEN.
// Upon completion, the Callback will be called. Only one
// receive request is send to MNP. IpInstance is always NULL.
// Reference MNP's spec for information.
//
typedef struct {
UINT32 Signature;
IP6_FRAME_CALLBACK CallBack;
VOID *Context;
EFI_MANAGED_NETWORK_COMPLETION_TOKEN MnpToken;
} IP6_LINK_RX_TOKEN;
//
// Each transmit request is wrapped in an IP6_LINK_TX_TOKEN.
// Upon completion, the Callback will be called.
//
typedef struct {
UINT32 Signature;
LIST_ENTRY Link;
IP6_PROTOCOL *IpInstance;
IP6_FRAME_CALLBACK CallBack;
NET_BUF *Packet;
VOID *Context;
EFI_MAC_ADDRESS DstMac;
EFI_MAC_ADDRESS SrcMac;
EFI_MANAGED_NETWORK_COMPLETION_TOKEN MnpToken;
EFI_MANAGED_NETWORK_TRANSMIT_DATA MnpTxData;
} IP6_LINK_TX_TOKEN;
struct _IP6_ADDRESS_INFO {
UINT32 Signature;
LIST_ENTRY Link;
EFI_IPv6_ADDRESS Address;
BOOLEAN IsAnycast;
UINT8 PrefixLength;
UINT32 ValidLifetime;
UINT32 PreferredLifetime;
};
//
// Callback to select which frame to cancel. Caller can cancel a
// single frame, or all the frame from an IP instance.
//
typedef
BOOLEAN
(*IP6_FRAME_TO_CANCEL) (
IP6_LINK_TX_TOKEN *Frame,
VOID *Context
);
struct _IP6_INTERFACE {
UINT32 Signature;
LIST_ENTRY Link;
INTN RefCnt;
//
// IP address and prefix length of the interface. The fileds
// are invalid if (Configured == FALSE)
//
LIST_ENTRY AddressList;
UINT32 AddressCount;
BOOLEAN Configured;
IP6_SERVICE *Service;
EFI_HANDLE Controller;
EFI_HANDLE Image;
//
// Queues to keep the frames sent and waiting ARP request.
//
LIST_ENTRY ArpQues;
LIST_ENTRY SentFrames;
//
// The interface's configuration variables
//
UINT32 DupAddrDetect;
LIST_ENTRY DupAddrDetectList;
LIST_ENTRY DelayJoinList;
//
// All the IP instances that have the same IP/SubnetMask are linked
// together through IpInstances. If any of the instance enables
// promiscuous receive, PromiscRecv is true.
//
LIST_ENTRY IpInstances;
BOOLEAN PromiscRecv;
};
/**
Create an IP6_INTERFACE.
@param[in] IpSb The IP6 service binding instance.
@param[in] LinkLocal If TRUE, the instance is created for link-local address.
Otherwise, it is not for a link-local address.
@return Point to the created IP6_INTERFACE, otherwise NULL.
**/
IP6_INTERFACE *
Ip6CreateInterface (
IN IP6_SERVICE *IpSb,
IN BOOLEAN LinkLocal
);
/**
Free the interface used by IpInstance. All the IP instance with
the same Ip/prefix pair share the same interface. It is reference
counted. All the frames that haven't been sent will be cancelled.
Because the IpInstance is optional, the caller must remove
IpInstance from the interface's instance list.
@param[in] Interface The interface used by the IpInstance.
@param[in] IpInstance The IP instance that free the interface. NULL if
the IP driver is releasing the default interface.
**/
VOID
Ip6CleanInterface (
IN IP6_INTERFACE *Interface,
IN IP6_PROTOCOL *IpInstance OPTIONAL
);
/**
Free the link layer transmit token. It will close the event
then free the memory used.
@param[in] Token Token to free.
**/
VOID
Ip6FreeLinkTxToken (
IN IP6_LINK_TX_TOKEN *Token
);
/**
Request Ip6OnFrameReceivedDpc as a DPC at TPL_CALLBACK
@param Event The receive event delivered to MNP for receive.
@param Context Context for the callback.
**/
VOID
EFIAPI
Ip6OnFrameReceived (
IN EFI_EVENT Event,
IN VOID *Context
);
/**
Request to receive the packet from the interface.
@param[in] CallBack Function to call when the receive finished.
@param[in] IpSb Points to the IP6 service binding instance.
@retval EFI_ALREADY_STARTED There is already a pending receive request.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources to receive.
@retval EFI_SUCCESS The recieve request has been started.
**/
EFI_STATUS
Ip6ReceiveFrame (
IN IP6_FRAME_CALLBACK CallBack,
IN IP6_SERVICE *IpSb
);
/**
Send a frame from the interface. If the next hop is multicast address,
it is transmitted immediately. If the next hop is a unicast,
and the NextHop's MAC is not known, it will perform address resolution.
If some error happened, the CallBack won't be called. So, the caller
must test the return value, and take action when there is an error.
@param[in] Interface The interface to send the frame from
@param[in] IpInstance The IP child that request the transmission.
NULL if it is the IP6 driver itself.
@param[in] Packet The packet to transmit.
@param[in] NextHop The immediate destination to transmit the packet to.
@param[in] CallBack Function to call back when transmit finished.
@param[in] Context Opaque parameter to the call back.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame.
@retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop.
@retval EFI_SUCCESS The packet successfully transmitted.
**/
EFI_STATUS
Ip6SendFrame (
IN IP6_INTERFACE *Interface,
IN IP6_PROTOCOL *IpInstance OPTIONAL,
IN NET_BUF *Packet,
IN EFI_IPv6_ADDRESS *NextHop,
IN IP6_FRAME_CALLBACK CallBack,
IN VOID *Context
);
/**
The heartbeat timer of IP6 service instance. It times out
all of its IP6 children's received-but-not-delivered and
transmitted-but-not-recycle packets.
@param[in] Event The IP6 service instance's heart beat timer.
@param[in] Context The IP6 service instance.
**/
VOID
EFIAPI
Ip6TimerTicking (
IN EFI_EVENT Event,
IN VOID *Context
);
#endif

1857
NetworkPkg/Ip6Dxe/Ip6Impl.c Normal file

File diff suppressed because it is too large Load Diff

751
NetworkPkg/Ip6Dxe/Ip6Impl.h Normal file
View File

@@ -0,0 +1,751 @@
/** @file
Implementation of EFI_IP6_PROTOCOL protocol interfaces and type definitions.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6_IMPL_H__
#define __EFI_IP6_IMPL_H__
#include <Uefi.h>
#include <Protocol/ServiceBinding.h>
#include <Protocol/ManagedNetwork.h>
#include <Protocol/IpSec.h>
#include <Protocol/Ip6.h>
#include <Protocol/Ip6Config.h>
#include <Protocol/Dhcp6.h>
#include <Protocol/DevicePath.h>
#include <Protocol/HiiConfigRouting.h>
#include <Protocol/HiiConfigAccess.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/UefiLib.h>
#include <Library/NetLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DpcLib.h>
#include <Library/HiiLib.h>
#include <Library/UefiHiiServicesLib.h>
#include <Library/DevicePathLib.h>
#include <Library/PrintLib.h>
#include <Guid/MdeModuleHii.h>
#include "Ip6Common.h"
#include "Ip6Driver.h"
#include "Ip6Icmp.h"
#include "Ip6If.h"
#include "Ip6Input.h"
#include "Ip6Mld.h"
#include "Ip6Nd.h"
#include "Ip6Option.h"
#include "Ip6Output.h"
#include "Ip6Route.h"
#include "Ip6ConfigNv.h"
#include "Ip6ConfigImpl.h"
#define IP6_PROTOCOL_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'P')
#define IP6_SERVICE_SIGNATURE SIGNATURE_32 ('I', 'P', '6', 'S')
//
// The state of IP6 protocol. It starts from UNCONFIGED. if it is
// successfully configured, it goes to CONFIGED. if configure NULL
// is called, it becomes UNCONFIGED again. If (partly) destroyed, it
// becomes DESTROY.
//
#define IP6_STATE_UNCONFIGED 0
#define IP6_STATE_CONFIGED 1
#define IP6_STATE_DESTROY 2
//
// The state of IP6 service. It starts from UNSTARTED. It transits
// to STARTED if autoconfigure is started. If default address is
// configured, it becomes CONFIGED. and if partly destroyed, it goes
// to DESTROY.
//
#define IP6_SERVICE_UNSTARTED 0
#define IP6_SERVICE_STARTED 1
#define IP6_SERVICE_CONFIGED 2
#define IP6_SERVICE_DESTROY 3
#define IP6_INSTANCE_FROM_PROTOCOL(Ip6) \
CR ((Ip6), IP6_PROTOCOL, Ip6Proto, IP6_PROTOCOL_SIGNATURE)
#define IP6_SERVICE_FROM_PROTOCOL(Sb) \
CR ((Sb), IP6_SERVICE, ServiceBinding, IP6_SERVICE_SIGNATURE)
#define IP6_NO_MAPPING(IpInstance) (!(IpInstance)->Interface->Configured)
extern EFI_IPSEC_PROTOCOL *mIpSec;
//
// IP6_TXTOKEN_WRAP wraps the upper layer's transmit token.
// The user's data is kept in the Packet. When fragment is
// needed, each fragment of the Packet has a reference to the
// Packet, no data is actually copied. The Packet will be
// released when all the fragments of it have been recycled by
// MNP. Upon then, the IP6_TXTOKEN_WRAP will be released, and
// user's event signalled.
//
typedef struct {
IP6_PROTOCOL *IpInstance;
EFI_IP6_COMPLETION_TOKEN *Token;
EFI_EVENT IpSecRecycleSignal;
NET_BUF *Packet;
BOOLEAN Sent;
INTN Life;
} IP6_TXTOKEN_WRAP;
typedef struct {
EFI_EVENT IpSecRecycleSignal;
NET_BUF *Packet;
} IP6_IPSEC_WRAP;
//
// IP6_RXDATA_WRAP wraps the data IP6 child delivers to the
// upper layers. The received packet is kept in the Packet.
// The Packet itself may be constructured from some fragments.
// All the fragments of the Packet is organized by a
// IP6_ASSEMBLE_ENTRY structure. If the Packet is recycled by
// the upper layer, the assemble entry and its associated
// fragments will be freed at last.
//
typedef struct {
LIST_ENTRY Link;
IP6_PROTOCOL *IpInstance;
NET_BUF *Packet;
EFI_IP6_RECEIVE_DATA RxData;
} IP6_RXDATA_WRAP;
struct _IP6_PROTOCOL {
UINT32 Signature;
EFI_IP6_PROTOCOL Ip6Proto;
EFI_HANDLE Handle;
INTN State;
IP6_SERVICE *Service;
LIST_ENTRY Link; // Link to all the IP protocol from the service
UINT8 PrefixLength; // PrefixLength of the configured station address.
//
// User's transmit/receive tokens, and received/deliverd packets
//
NET_MAP RxTokens;
NET_MAP TxTokens; // map between (User's Token, IP6_TXTOKE_WRAP)
LIST_ENTRY Received; // Received but not delivered packet
LIST_ENTRY Delivered; // Delivered and to be recycled packets
EFI_LOCK RecycleLock;
IP6_INTERFACE *Interface;
LIST_ENTRY AddrLink; // Ip instances with the same IP address.
EFI_IPv6_ADDRESS *GroupList; // stored in network order.
UINT32 GroupCount;
EFI_IP6_CONFIG_DATA ConfigData;
};
struct _IP6_SERVICE {
UINT32 Signature;
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
INTN State;
BOOLEAN InDestroy;
//
// List of all the IP instances and interfaces, and default
// interface and route table and caches.
//
UINTN NumChildren;
LIST_ENTRY Children;
LIST_ENTRY Interfaces;
IP6_INTERFACE *DefaultInterface;
IP6_ROUTE_TABLE *RouteTable;
IP6_LINK_RX_TOKEN RecvRequest;
//
// Ip reassemble utilities and MLD data
//
IP6_ASSEMBLE_TABLE Assemble;
IP6_MLD_SERVICE_DATA MldCtrl;
EFI_IPv6_ADDRESS LinkLocalAddr;
BOOLEAN LinkLocalOk;
BOOLEAN LinkLocalDadFail;
BOOLEAN Dhcp6NeedStart;
BOOLEAN Dhcp6NeedInfoRequest;
//
// ND data
//
UINT8 CurHopLimit;
UINT32 LinkMTU;
UINT32 BaseReachableTime;
UINT32 ReachableTime;
UINT32 RetransTimer;
LIST_ENTRY NeighborTable;
LIST_ENTRY OnlinkPrefix;
LIST_ENTRY AutonomousPrefix;
LIST_ENTRY DefaultRouterList;
UINT32 RoundRobin;
UINT8 InterfaceIdLen;
UINT8 *InterfaceId;
BOOLEAN RouterAdvertiseReceived;
UINT8 SolicitTimer;
UINT32 Ticks;
//
// Low level protocol used by this service instance
//
EFI_HANDLE Image;
EFI_HANDLE Controller;
EFI_HANDLE MnpChildHandle;
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData;
EFI_SIMPLE_NETWORK_MODE SnpMode;
EFI_EVENT Timer;
EFI_EVENT FasterTimer;
//
// IPv6 Configuration Protocol instance
//
IP6_CONFIG_INSTANCE Ip6ConfigInstance;
//
// The string representation of the current mac address of the
// NIC this IP6_SERVICE works on.
//
CHAR16 *MacString;
UINT32 MaxPacketSize;
UINT32 OldMaxPacketSize;
};
/**
The callback function for the net buffer which wraps the user's
transmit token. Although this function seems simple,
there are some subtle aspects.
When a user requests the IP to transmit a packet by passing it a
token, the token is wrapped in an IP6_TXTOKEN_WRAP and the data
is wrapped in a net buffer. The net buffer's Free function is
set to Ip6FreeTxToken. The Token and token wrap are added to the
IP child's TxToken map. Then the buffer is passed to Ip6Output for
transmission. If an error occurs before that, the buffer
is freed, which in turn frees the token wrap. The wrap may
have been added to the TxToken map or not, and the user's event
shouldn't be signaled because we are still in the EfiIp6Transmit. If
the buffer has been sent by Ip6Output, it should be removed from
the TxToken map and the user's event signaled. The token wrap and buffer
are bound together. Refer to the comments in Ip6Output for information
about IP fragmentation.
@param[in] Context The token's wrap.
**/
VOID
EFIAPI
Ip6FreeTxToken (
IN VOID *Context
);
/**
Config the MNP parameter used by IP. The IP driver use one MNP
child to transmit/receive frames. By default, it configures MNP
to receive unicast/multicast/broadcast. And it will enable/disable
the promiscuous receive according to whether there is IP child
enable that or not. If Force is FALSE, it will iterate through
all the IP children to check whether the promiscuous receive
setting has been changed. If it hasn't been changed, it won't
reconfigure the MNP. If Force is TRUE, the MNP is configured
whether that is changed or not.
@param[in] IpSb The IP6 service instance that is to be changed.
@param[in] Force Force the configuration or not.
@retval EFI_SUCCESS The MNP successfully configured/reconfigured.
@retval Others The configuration failed.
**/
EFI_STATUS
Ip6ServiceConfigMnp (
IN IP6_SERVICE *IpSb,
IN BOOLEAN Force
);
/**
Cancel the user's receive/transmit request. It is the worker function of
EfiIp6Cancel API.
@param[in] IpInstance The IP6 child.
@param[in] Token The token to cancel. If NULL, all tokens will be
cancelled.
@retval EFI_SUCCESS The token was cancelled.
@retval EFI_NOT_FOUND The token isn't found on either the
transmit or receive queue.
@retval EFI_DEVICE_ERROR Not all tokens are cancelled when Token is NULL.
**/
EFI_STATUS
Ip6Cancel (
IN IP6_PROTOCOL *IpInstance,
IN EFI_IP6_COMPLETION_TOKEN *Token OPTIONAL
);
/**
Initialize the IP6_PROTOCOL structure to the unconfigured states.
@param[in] IpSb The IP6 service instance.
@param[in, out] IpInstance The IP6 child instance.
**/
VOID
Ip6InitProtocol (
IN IP6_SERVICE *IpSb,
IN OUT IP6_PROTOCOL *IpInstance
);
/**
Clean up the IP6 child, release all the resources used by it.
@param[in, out] IpInstance The IP6 child to clean up.
@retval EFI_SUCCESS The IP6 child was cleaned up
@retval EFI_DEVICE_ERROR Some resources failed to be released.
**/
EFI_STATUS
Ip6CleanProtocol (
IN OUT IP6_PROTOCOL *IpInstance
);
//
// EFI_IP6_PROTOCOL interface prototypes
//
/**
Gets the current operational settings for this instance of the EFI IPv6 Protocol driver.
The GetModeData() function returns the current operational mode data for this driver instance.
The data fields in EFI_IP6_MODE_DATA are read only. This function is used optionally to
retrieve the operational mode data of underlying networks or drivers.
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
@param[out] Ip6ModeData The pointer to the EFI IPv6 Protocol mode data structure.
@param[out] MnpConfigData The pointer to the managed network configuration data structure.
@param[out] SnpModeData The pointer to the simple network mode data structure.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.
**/
EFI_STATUS
EFIAPI
EfiIp6GetModeData (
IN EFI_IP6_PROTOCOL *This,
OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL,
OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
);
/**
Assigns an IPv6 address and subnet mask to this EFI IPv6 Protocol driver instance.
The Configure() function is used to set, change, or reset the operational parameters and filter
settings for this EFI IPv6 Protocol instance. Until these parameters have been set, no network traffic
can be sent or received by this instance. Once the parameters have been reset (by calling this
function with Ip6ConfigData set to NULL), no more traffic can be sent or received until these
parameters have been set again. Each EFI IPv6 Protocol instance can be started and stopped
independently of each other by enabling or disabling their receive filter settings with the
Configure() function.
If Ip6ConfigData.StationAddress is a valid non-zero IPv6 unicast address, it is required
to be one of the currently configured IPv6 addresses list in the EFI IPv6 drivers, or else
EFI_INVALID_PARAMETER will be returned. If Ip6ConfigData.StationAddress is
unspecified, the IPv6 driver will bind a source address according to the source address selection
algorithm. Clients could frequently call GetModeData() to check get a currently configured IPv6.
If both Ip6ConfigData.StationAddress and Ip6ConfigData.Destination are unspecified, when
transmitting the packet afterwards, the source address filled in each outgoing IPv6 packet
is decided based on the destination of this packet.
If operational parameters are reset or changed, any pending transmit and receive requests will be
cancelled. Their completion token status will be set to EFI_ABORTED, and their events will be
signaled.
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
@param[in] Ip6ConfigData The pointer to the EFI IPv6 Protocol configuration data structure.
If NULL, reset the configuration data.
@retval EFI_SUCCESS The driver instance was successfully opened.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- This is NULL.
- Ip6ConfigData.StationAddress is neither zero nor
a unicast IPv6 address.
- Ip6ConfigData.StationAddress is neither zero nor
one of the configured IP addresses in the EFI IPv6 driver.
- Ip6ConfigData.DefaultProtocol is illegal.
@retval EFI_OUT_OF_RESOURCES The EFI IPv6 Protocol driver instance data could not be allocated.
@retval EFI_NO_MAPPING The IPv6 driver was responsible for choosing a source address for
this instance, but no source address was available for use.
@retval EFI_ALREADY_STARTED The interface is already open and must be stopped before the IPv6
address or prefix length can be changed.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI IPv6
Protocol driver instance was not opened.
@retval EFI_UNSUPPORTED Default protocol specified through
Ip6ConfigData.DefaulProtocol isn't supported.
**/
EFI_STATUS
EFIAPI
EfiIp6Configure (
IN EFI_IP6_PROTOCOL *This,
IN EFI_IP6_CONFIG_DATA *Ip6ConfigData OPTIONAL
);
/**
Joins and leaves multicast groups.
The Groups() function is used to join and leave multicast group sessions. Joining a group will
enable reception of matching multicast packets. Leaving a group will disable reception of matching
multicast packets. Source-Specific Multicast isn't required to be supported.
If JoinFlag is FALSE and GroupAddress is NULL, all joined groups will be left.
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
@param[in] JoinFlag Set to TRUE to join the multicast group session and FALSE to leave.
@param[in] GroupAddress The pointer to the IPv6 multicast address.
This is an optional parameter that may be NULL.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER One or more of the following is TRUE:
- This is NULL.
- JoinFlag is TRUE and GroupAddress is NULL.
- GroupAddress is not NULL and *GroupAddress is
not a multicast IPv6 address.
- GroupAddress is not NULL and *GroupAddress is in the
range of SSM destination address.
@retval EFI_NOT_STARTED This instance has not been started.
@retval EFI_OUT_OF_RESOURCES System resources could not be allocated.
@retval EFI_UNSUPPORTED This EFI IPv6 Protocol implementation does not support multicast groups.
@retval EFI_ALREADY_STARTED The group address is already in the group table (when
JoinFlag is TRUE).
@retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE).
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
EfiIp6Groups (
IN EFI_IP6_PROTOCOL *This,
IN BOOLEAN JoinFlag,
IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL
);
/**
Adds and deletes routing table entries.
The Routes() function adds a route to or deletes a route from the routing table.
Routes are determined by comparing the leftmost PrefixLength bits of Destination with
the destination IPv6 address arithmetically. The gateway address must be on the same subnet as the
configured station address.
The default route is added with Destination and PrefixLegth both set to all zeros. The
default route matches all destination IPv6 addresses that do not match any other routes.
All EFI IPv6 Protocol instances share a routing table.
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
@param[in] DeleteRoute Set to TRUE to delete this route from the routing table. Set to
FALSE to add this route to the routing table. Destination,
PrefixLength and Gateway are used as the key to each
route entry.
@param[in] Destination The address prefix of the subnet that needs to be routed.
This is an optional parameter that may be NULL.
@param[in] PrefixLength The prefix length of Destination. Ignored if Destination
is NULL.
@param[in] GatewayAddress The unicast gateway IPv6 address for this route.
This is an optional parameter that may be NULL.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_STARTED The driver instance has not been started.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- This is NULL.
- When DeleteRoute is TRUE, both Destination and
GatewayAddress are NULL.
- When DeleteRoute is FALSE, either Destination or
GatewayAddress is NULL.
- *GatewayAddress is not a valid unicast IPv6 address.
- *GatewayAddress is one of the local configured IPv6
addresses.
@retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
@retval EFI_NOT_FOUND This route is not in the routing table (when DeleteRoute is TRUE).
@retval EFI_ACCESS_DENIED The route is already defined in the routing table (when
DeleteRoute is FALSE).
**/
EFI_STATUS
EFIAPI
EfiIp6Routes (
IN EFI_IP6_PROTOCOL *This,
IN BOOLEAN DeleteRoute,
IN EFI_IPv6_ADDRESS *Destination OPTIONAL,
IN UINT8 PrefixLength,
IN EFI_IPv6_ADDRESS *GatewayAddress OPTIONAL
);
/**
Add or delete Neighbor cache entries.
The Neighbors() function is used to add, update, or delete an entry from a neighbor cache.
IPv6 neighbor cache entries are typically inserted and updated by the network protocol driver as
network traffic is processed. Most neighbor cache entries will timeout and be deleted if the network
traffic stops. Neighbor cache entries that were inserted by Neighbors() may be static (will not
timeout) or dynamic (will timeout).
The implementation should follow the neighbor cache timeout mechanism defined in
RFC4861. The default neighbor cache timeout value should be tuned for the expected network
environment.
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
@param[in] DeleteFlag Set to TRUE to delete the specified cache entry. Set to FALSE to
add (or update, if it already exists and Override is TRUE) the
specified cache entry. TargetIp6Address is used as the key
to find the requested cache entry.
@param[in] TargetIp6Address The pointer to the Target IPv6 address.
@param[in] TargetLinkAddress The pointer to link-layer address of the target. Ignored if NULL.
@param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor
cache, it will be deleted after Timeout. A value of zero means that
the entry is permanent. A non-zero value means that the entry is
dynamic.
@param[in] Override If TRUE, the cached link-layer address of the matching entry will
be overridden and updated; if FALSE, EFI_ACCESS_DENIED
will be returned if a corresponding cache entry already exists.
@retval EFI_SUCCESS The data has been queued for transmission.
@retval EFI_NOT_STARTED This instance has not been started.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- This is NULL.
- TargetIpAddress is NULL.
- *TargetLinkAddress is invalid when not NULL.
- *TargetIpAddress is not a valid unicast IPv6 address.
- *TargetIpAddress is one of the local configured IPv6
addresses.
@retval EFI_OUT_OF_RESOURCES Could not add the entry to the neighbor cache.
@retval EFI_NOT_FOUND This entry is not in the neighbor cache (when DeleteFlag is
TRUE or when DeleteFlag is FALSE while
TargetLinkAddress is NULL.).
@retval EFI_ACCESS_DENIED The to-be-added entry is already defined in the neighbor cache,
and that entry is tagged as un-overridden (when Override
is FALSE).
**/
EFI_STATUS
EFIAPI
EfiIp6Neighbors (
IN EFI_IP6_PROTOCOL *This,
IN BOOLEAN DeleteFlag,
IN EFI_IPv6_ADDRESS *TargetIp6Address,
IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
IN UINT32 Timeout,
IN BOOLEAN Override
);
/**
Places outgoing data packets into the transmit queue.
The Transmit() function places a sending request in the transmit queue of this
EFI IPv6 Protocol instance. Whenever the packet in the token is sent out or some
errors occur, the event in the token will be signaled and the status is updated.
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
@param[in] Token The pointer to the transmit token.
@retval EFI_SUCCESS The data has been queued for transmission.
@retval EFI_NOT_STARTED This instance has not been started.
@retval EFI_NO_MAPPING The IPv6 driver was responsible for choosing
a source address for this transmission,
but no source address was available for use.
@retval EFI_INVALID_PARAMETER One or more of the following is TRUE:
- This is NULL.
- Token is NULL.
- Token.Event is NULL.
- Token.Packet.TxData is NULL.
- Token.Packet.ExtHdrsLength is not zero and
Token.Packet.ExtHdrs is NULL.
- Token.Packet.FragmentCount is zero.
- One or more of the Token.Packet.TxData.
FragmentTable[].FragmentLength fields is zero.
- One or more of the Token.Packet.TxData.
FragmentTable[].FragmentBuffer fields is NULL.
- Token.Packet.TxData.DataLength is zero or not
equal to the sum of fragment lengths.
- Token.Packet.TxData.DestinationAddress is non-
zero when DestinationAddress is configured as
non-zero when doing Configure() for this
EFI IPv6 protocol instance.
- Token.Packet.TxData.DestinationAddress is
unspecified when DestinationAddress is unspecified
when doing Configure() for this EFI IPv6 protocol
instance.
@retval EFI_ACCESS_DENIED The transmit completion token with the same Token.
The event was already in the transmit queue.
@retval EFI_NOT_READY The completion token could not be queued because
the transmit queue is full.
@retval EFI_NOT_FOUND Not route is found to the destination address.
@retval EFI_OUT_OF_RESOURCES Could not queue the transmit data.
@retval EFI_BUFFER_TOO_SMALL Token.Packet.TxData.TotalDataLength is too
short to transmit.
@retval EFI_BAD_BUFFER_SIZE If Token.Packet.TxData.DataLength is beyond the
maximum that which can be described through the
Fragment Offset field in Fragment header when
performing fragmentation.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
EfiIp6Transmit (
IN EFI_IP6_PROTOCOL *This,
IN EFI_IP6_COMPLETION_TOKEN *Token
);
/**
Places a receiving request into the receiving queue.
The Receive() function places a completion token into the receive packet queue.
This function is always asynchronous.
The Token.Event field in the completion token must be filled in by the caller
and cannot be NULL. When the receive operation completes, the EFI IPv6 Protocol
driver updates the Token.Status and Token.Packet.RxData fields and the Token.Event
is signaled.
Current Udp implementation creates an IP child for each Udp child.
It initates a asynchronous receive immediately whether or not
there is no mapping. Therefore, disable the returning EFI_NO_MAPPING for now.
To enable it, the following check must be performed:
if (NetIp6IsUnspecifiedAddr (&Config->StationAddress) && IP6_NO_MAPPING (IpInstance)) {
Status = EFI_NO_MAPPING;
goto Exit;
}
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
@param[in] Token The pointer to a token that is associated with the
receive data descriptor.
@retval EFI_SUCCESS The receive completion token was cached.
@retval EFI_NOT_STARTED This EFI IPv6 Protocol instance has not been started.
@retval EFI_NO_MAPPING When IP6 driver responsible for binding source address to this instance,
while no source address is available for use.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- This is NULL.
- Token is NULL.
- Token.Event is NULL.
@retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system
resources (usually memory).
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
The EFI IPv6 Protocol instance has been reset to startup defaults.
@retval EFI_ACCESS_DENIED The receive completion token with the same Token.Event was already
in the receive queue.
@retval EFI_NOT_READY The receive request could not be queued because the receive queue is full.
**/
EFI_STATUS
EFIAPI
EfiIp6Receive (
IN EFI_IP6_PROTOCOL *This,
IN EFI_IP6_COMPLETION_TOKEN *Token
);
/**
Abort an asynchronous transmit or receive request.
The Cancel() function is used to abort a pending transmit or receive request.
If the token is in the transmit or receive request queues, after calling this
function, Token->Status will be set to EFI_ABORTED, and then Token->Event will
be signaled. If the token is not in one of the queues, which usually means the
asynchronous operation has completed, this function will not signal the token,
and EFI_NOT_FOUND is returned.
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
@param[in] Token The pointer to a token that has been issued by
EFI_IP6_PROTOCOL.Transmit() or
EFI_IP6_PROTOCOL.Receive(). If NULL, all pending
tokens are aborted. Type EFI_IP6_COMPLETION_TOKEN is
defined in EFI_IP6_PROTOCOL.Transmit().
@retval EFI_SUCCESS The asynchronous I/O request was aborted and
Token->Event was signaled. When Token is NULL, all
pending requests were aborted, and their events were signaled.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_NOT_STARTED This instance has not been started.
@retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was
not found in the transmit or receive queue. It has either completed
or was not issued by Transmit() and Receive().
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
EfiIp6Cancel (
IN EFI_IP6_PROTOCOL *This,
IN EFI_IP6_COMPLETION_TOKEN *Token OPTIONAL
);
/**
Polls for incoming data packets and processes outgoing data packets.
The Poll() function polls for incoming data packets and processes outgoing data
packets. Network drivers and applications can call the EFI_IP6_PROTOCOL.Poll()
function to increase the rate that data packets are moved between the communications
device and the transmit and receive queues.
In some systems the periodic timer event may not poll the underlying communications
device fast enough to transmit and/or receive all data packets without missing
incoming packets or dropping outgoing packets. Drivers and applications that are
experiencing packet loss should try calling the EFI_IP6_PROTOCOL.Poll() function
more often.
@param[in] This The pointer to the EFI_IP6_PROTOCOL instance.
@retval EFI_SUCCESS Incoming or outgoing data was processed.
@retval EFI_NOT_STARTED This EFI IPv6 Protocol instance has not been started.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval EFI_NOT_READY No incoming or outgoing data was processed.
@retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.
Consider increasing the polling rate.
**/
EFI_STATUS
EFIAPI
EfiIp6Poll (
IN EFI_IP6_PROTOCOL *This
);
#endif

1710
NetworkPkg/Ip6Dxe/Ip6Input.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
/** @file
IP6 internal functions and definitions to process the incoming packets.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6_INPUT_H__
#define __EFI_IP6_INPUT_H__
#define IP6_MIN_HEADLEN 40
#define IP6_MAX_HEADLEN 120
///
/// 8(ESP header) + 16(max IV) + 16(max padding) + 2(ESP tail) + 12(max ICV) = 54
///
#define IP6_MAX_IPSEC_HEADLEN 54
#define IP6_ASSEMLE_HASH_SIZE 127
///
/// Lift time in seconds.
///
#define IP6_FRAGMENT_LIFE 60
#define IP6_MAX_PACKET_SIZE 65535
#define IP6_GET_CLIP_INFO(Packet) ((IP6_CLIP_INFO *) ((Packet)->ProtoData))
#define IP6_ASSEMBLE_HASH(Dst, Src, Id) \
((*((UINT32 *) (Dst)) + *((UINT32 *) (Src)) + (Id)) % IP6_ASSEMLE_HASH_SIZE)
#define IP6_RXDATA_WRAP_SIZE(NumFrag) \
(sizeof (IP6_RXDATA_WRAP) + sizeof (EFI_IP6_FRAGMENT_DATA) * ((NumFrag) - 1))
//
// Per packet information for input process. LinkFlag specifies whether
// the packet is received as Link layer unicast, multicast or broadcast.
// The CastType is the IP layer cast type, such as IP multicast or unicast.
// Start, End and Length are staffs used to assemble the packets. Start
// is the sequence number of the first byte of data in the packet. Length
// is the number of bytes of data. End = Start + Length, that is, the
// sequence number of last byte + 1. Each assembled packet has a count down
// life. If it isn't consumed before Life reaches zero, the packet is released.
//
typedef struct {
UINT32 LinkFlag;
INT32 CastType;
INT32 Start;
INT32 End;
INT32 Length;
UINT32 Life;
EFI_STATUS Status;
UINT32 Id;
UINT16 HeadLen;
UINT8 NextHeader;
UINT8 LastFrag;
UINT32 FormerNextHeader;
} IP6_CLIP_INFO;
//
// Structure used to assemble IP packets.
//
typedef struct {
LIST_ENTRY Link;
LIST_ENTRY Fragments; // List of all the fragments of this packet
//
// Identity of one IP6 packet. Each fragment of a packet has
// the same (Dst, Src, Id).
//
EFI_IPv6_ADDRESS Dst;
EFI_IPv6_ADDRESS Src;
UINT32 Id;
UINT32 TotalLen;
UINT32 CurLen;
UINT32 Life; // Count down life for the packet.
EFI_IP6_HEADER *Head; // IP head of the first fragment
IP6_CLIP_INFO *Info; // Per packet information of the first fragment
NET_BUF *Packet; // The first fragment of the packet
} IP6_ASSEMBLE_ENTRY;
//
// Each Ip service instance has an assemble table to reassemble
// the packets before delivery to its children. It is organized
// as hash table.
//
typedef struct {
LIST_ENTRY Bucket[IP6_ASSEMLE_HASH_SIZE];
} IP6_ASSEMBLE_TABLE;
/**
The IP6 input routine. It is called by the IP6_INTERFACE when an
IP6 fragment is received from MNP.
@param[in] Packet The IP6 packet received.
@param[in] IoStatus The return status of receive request.
@param[in] Flag The link layer flag for the packet received, such
as multicast.
@param[in] Context The IP6 service instance that own the MNP.
**/
VOID
Ip6AcceptFrame (
IN NET_BUF *Packet,
IN EFI_STATUS IoStatus,
IN UINT32 Flag,
IN VOID *Context
);
/**
Deliver the received packets to upper layer if there are both received
requests and enqueued packets. If the enqueued packet is shared, it will
duplicate it to a non-shared packet, release the shared packet, then
deliver the non-shared packet up.
@param[in] IpInstance The IP child to deliver the packet up.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources to deliver the
packets.
@retval EFI_SUCCESS All the enqueued packets that can be delivered
are delivered up.
**/
EFI_STATUS
Ip6InstanceDeliverPacket (
IN IP6_PROTOCOL *IpInstance
);
/**
The work function to locate IPsec protocol to process the inbound or
outbound IP packets. The process routine handls the packet with the following
actions: bypass the packet, discard the packet, or protect the packet.
@param[in] IpSb The IP6 service instance.
@param[in] Head The caller supplied IP6 header.
@param[in, out] LastHead The next header field of last IP header.
@param[in, out] Netbuf The IP6 packet to be processed by IPsec.
@param[in] ExtHdrs The caller supplied options.
@param[in] ExtHdrsLen The length of the option.
@param[in] Direction The directionality in an SPD entry,
EfiIPsecInBound or EfiIPsecOutBound.
@param[in] Context The token's wrap.
@retval EFI_SUCCESS The IPsec protocol is not available or disabled.
@retval EFI_SUCCESS The packet was bypassed and all buffers remain the same.
@retval EFI_SUCCESS The packet was protected.
@retval EFI_ACCESS_DENIED The packet was discarded.
@retval EFI_OUT_OF_RESOURCES There are not suffcient resources to complete the operation.
@retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than the
number of input data blocks when building a fragment table.
**/
EFI_STATUS
Ip6IpSecProcessPacket (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN OUT UINT8 *LastHead,
IN OUT NET_BUF **Netbuf,
IN VOID *ExtHdrs,
IN UINT32 ExtHdrsLen,
IN EFI_IPSEC_TRAFFIC_DIR Direction,
IN VOID *Context
);
/**
Initialize an already allocated assemble table. This is generally
the assemble table embedded in the IP6 service instance.
@param[in, out] Table The assemble table to initialize.
**/
VOID
Ip6CreateAssembleTable (
IN OUT IP6_ASSEMBLE_TABLE *Table
);
/**
Clean up the assemble table: remove all the fragments
and assemble entries.
@param[in, out] Table The assemble table to clean up.
**/
VOID
Ip6CleanAssembleTable (
IN OUT IP6_ASSEMBLE_TABLE *Table
);
/**
Demultiple the packet. the packet delivery is processed in two
passes. The first pass will enque a shared copy of the packet
to each IP6 child that accepts the packet. The second pass will
deliver a non-shared copy of the packet to each IP6 child that
has pending receive requests. Data is copied if more than one
child wants to consume the packet bacause each IP child need
its own copy of the packet to make changes.
@param[in] IpSb The IP6 service instance that received the packet.
@param[in] Head The header of the received packet.
@param[in] Packet The data of the received packet.
@retval EFI_NOT_FOUND No IP child accepts the packet.
@retval EFI_SUCCESS The packet is enqueued or delivered to some IP
children.
**/
EFI_STATUS
Ip6Demultiplex (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
);
/**
Timeout the fragmented, enqueued, and transmitted packets.
@param[in] IpSb The IP6 service instance to timeout.
**/
VOID
Ip6PacketTimerTicking (
IN IP6_SERVICE *IpSb
);
#endif

908
NetworkPkg/Ip6Dxe/Ip6Mld.c Normal file
View File

@@ -0,0 +1,908 @@
/** @file
Multicast Listener Discovery support routines.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ip6Impl.h"
/**
Create a IP6_MLD_GROUP list entry node and record to IP6 service binding data.
@param[in, out] IpSb Points to IP6 service binding instance.
@param[in] MulticastAddr The IPv6 multicast address to be recorded.
@param[in] DelayTimer The maximum allowed delay before sending a responding
report, in units of milliseconds.
@return The created IP6_ML_GROUP list entry or NULL.
**/
IP6_MLD_GROUP *
Ip6CreateMldEntry (
IN OUT IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *MulticastAddr,
IN UINT32 DelayTimer
)
{
IP6_MLD_GROUP *Entry;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
Entry = AllocatePool (sizeof (IP6_MLD_GROUP));
if (Entry != NULL) {
Entry->RefCnt = 1;
Entry->DelayTimer = DelayTimer;
Entry->SendByUs = FALSE;
IP6_COPY_ADDRESS (&Entry->Address, MulticastAddr);
InsertTailList (&IpSb->MldCtrl.Groups, &Entry->Link);
}
return Entry;
}
/**
Search a IP6_MLD_GROUP list entry node from a list array.
@param[in] IpSb Points to IP6 service binding instance.
@param[in] MulticastAddr The IPv6 multicast address to be searched.
@return The found IP6_ML_GROUP list entry or NULL.
**/
IP6_MLD_GROUP *
Ip6FindMldEntry (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *MulticastAddr
)
{
LIST_ENTRY *Entry;
IP6_MLD_GROUP *Group;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
if (EFI_IP6_EQUAL (MulticastAddr, &Group->Address)) {
return Group;
}
}
return NULL;
}
/**
Count the number of IP6 multicast groups that are mapped to the
same MAC address. Several IP6 multicast address may be mapped to
the same MAC address.
@param[in] MldCtrl The MLD control block to search in.
@param[in] Mac The MAC address to search.
@return The number of the IP6 multicast group that mapped to the same
multicast group Mac.
**/
INTN
Ip6FindMac (
IN IP6_MLD_SERVICE_DATA *MldCtrl,
IN EFI_MAC_ADDRESS *Mac
)
{
LIST_ENTRY *Entry;
IP6_MLD_GROUP *Group;
INTN Count;
Count = 0;
NET_LIST_FOR_EACH (Entry, &MldCtrl->Groups) {
Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
if (NET_MAC_EQUAL (&Group->Mac, Mac, sizeof (EFI_MAC_ADDRESS))) {
Count++;
}
}
return Count;
}
/**
Generate MLD report message and send it out to MulticastAddr.
@param[in] IpSb The IP service to send the packet.
@param[in] Interface The IP interface to send the packet.
If NULL, a system interface will be selected.
@param[in] MulticastAddr The specific IPv6 multicast address to which
the message sender is listening.
@retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete the
operation.
@retval EFI_SUCCESS The MLD report message was successfully sent out.
**/
EFI_STATUS
Ip6SendMldReport (
IN IP6_SERVICE *IpSb,
IN IP6_INTERFACE *Interface OPTIONAL,
IN EFI_IPv6_ADDRESS *MulticastAddr
)
{
IP6_MLD_HEAD *MldHead;
NET_BUF *Packet;
EFI_IP6_HEADER Head;
UINT16 PayloadLen;
UINTN OptionLen;
UINT8 *Options;
EFI_STATUS Status;
UINT16 HeadChecksum;
UINT16 PseudoChecksum;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
//
// Generate the packet to be sent
// IPv6 basic header + Hop by Hop option + MLD message
//
OptionLen = 0;
Status = Ip6FillHopByHop (NULL, &OptionLen, IP6_ICMP);
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
PayloadLen = (UINT16) (OptionLen + sizeof (IP6_MLD_HEAD));
Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32) PayloadLen);
if (Packet == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Create the basic IPv6 header.
// RFC3590: Use link-local address as source address if it is available,
// otherwise use the unspecified address.
//
Head.FlowLabelL = 0;
Head.FlowLabelH = 0;
Head.PayloadLength = HTONS (PayloadLen);
Head.NextHeader = IP6_HOP_BY_HOP;
Head.HopLimit = 1;
IP6_COPY_ADDRESS (&Head.DestinationAddress, MulticastAddr);
//
// If Link-Local address is not ready, we use unspecified address.
//
IP6_COPY_ADDRESS (&Head.SourceAddress, &IpSb->LinkLocalAddr);
NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
//
// Fill a IPv6 Router Alert option in a Hop-by-Hop Options Header
//
Options = NetbufAllocSpace (Packet, (UINT32) OptionLen, FALSE);
ASSERT (Options != NULL);
Status = Ip6FillHopByHop (Options, &OptionLen, IP6_ICMP);
if (EFI_ERROR (Status)) {
NetbufFree (Packet);
Packet = NULL;
return Status;
}
//
// Fill in MLD message - Report
//
MldHead = (IP6_MLD_HEAD *) NetbufAllocSpace (Packet, sizeof (IP6_MLD_HEAD), FALSE);
ASSERT (MldHead != NULL);
ZeroMem (MldHead, sizeof (IP6_MLD_HEAD));
MldHead->Head.Type = ICMP_V6_LISTENER_REPORT;
MldHead->Head.Code = 0;
IP6_COPY_ADDRESS (&MldHead->Group, MulticastAddr);
HeadChecksum = NetblockChecksum ((UINT8 *) MldHead, sizeof (IP6_MLD_HEAD));
PseudoChecksum = NetIp6PseudoHeadChecksum (
&Head.SourceAddress,
&Head.DestinationAddress,
IP6_ICMP,
sizeof (IP6_MLD_HEAD)
);
MldHead->Head.Checksum = (UINT16) ~NetAddChecksum (HeadChecksum, PseudoChecksum);
//
// Transmit the packet
//
return Ip6Output (IpSb, Interface, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
}
/**
Generate MLD Done message and send it out to MulticastAddr.
@param[in] IpSb The IP service to send the packet.
@param[in] MulticastAddr The specific IPv6 multicast address to which
the message sender is ceasing to listen.
@retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete the
operation.
@retval EFI_SUCCESS The MLD report message was successfully sent out.
**/
EFI_STATUS
Ip6SendMldDone (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *MulticastAddr
)
{
IP6_MLD_HEAD *MldHead;
NET_BUF *Packet;
EFI_IP6_HEADER Head;
UINT16 PayloadLen;
UINTN OptionLen;
UINT8 *Options;
EFI_STATUS Status;
EFI_IPv6_ADDRESS Destination;
UINT16 HeadChecksum;
UINT16 PseudoChecksum;
NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
//
// Generate the packet to be sent
// IPv6 basic header + Hop by Hop option + MLD message
//
OptionLen = 0;
Status = Ip6FillHopByHop (NULL, &OptionLen, IP6_ICMP);
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
PayloadLen = (UINT16) (OptionLen + sizeof (IP6_MLD_HEAD));
Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32) PayloadLen);
if (Packet == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Create the basic IPv6 header.
//
Head.FlowLabelL = 0;
Head.FlowLabelH = 0;
Head.PayloadLength = HTONS (PayloadLen);
Head.NextHeader = IP6_HOP_BY_HOP;
Head.HopLimit = 1;
//
// If Link-Local address is not ready, we use unspecified address.
//
IP6_COPY_ADDRESS (&Head.SourceAddress, &IpSb->LinkLocalAddr);
Ip6SetToAllNodeMulticast (TRUE, IP6_LINK_LOCAL_SCOPE, &Destination);
IP6_COPY_ADDRESS (&Head.DestinationAddress, &Destination);
NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
//
// Fill a IPv6 Router Alert option in a Hop-by-Hop Options Header
//
Options = NetbufAllocSpace (Packet, (UINT32) OptionLen, FALSE);
ASSERT (Options != NULL);
Status = Ip6FillHopByHop (Options, &OptionLen, IP6_ICMP);
if (EFI_ERROR (Status)) {
NetbufFree (Packet);
Packet = NULL;
return Status;
}
//
// Fill in MLD message - Done
//
MldHead = (IP6_MLD_HEAD *) NetbufAllocSpace (Packet, sizeof (IP6_MLD_HEAD), FALSE);
ASSERT (MldHead != NULL);
ZeroMem (MldHead, sizeof (IP6_MLD_HEAD));
MldHead->Head.Type = ICMP_V6_LISTENER_DONE;
MldHead->Head.Code = 0;
IP6_COPY_ADDRESS (&MldHead->Group, MulticastAddr);
HeadChecksum = NetblockChecksum ((UINT8 *) MldHead, sizeof (IP6_MLD_HEAD));
PseudoChecksum = NetIp6PseudoHeadChecksum (
&Head.SourceAddress,
&Head.DestinationAddress,
IP6_ICMP,
sizeof (IP6_MLD_HEAD)
);
MldHead->Head.Checksum = (UINT16) ~NetAddChecksum (HeadChecksum, PseudoChecksum);
//
// Transmit the packet
//
return Ip6Output (IpSb, NULL, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
}
/**
Init the MLD data of the IP6 service instance. Configure
MNP to receive ALL SYSTEM multicast.
@param[in] IpSb The IP6 service whose MLD is to be initialized.
@retval EFI_OUT_OF_RESOURCES There are not sufficient resourcet to complete the
operation.
@retval EFI_SUCCESS The MLD module successfully initialized.
**/
EFI_STATUS
Ip6InitMld (
IN IP6_SERVICE *IpSb
)
{
EFI_IPv6_ADDRESS AllNodes;
IP6_MLD_GROUP *Group;
EFI_STATUS Status;
//
// Join the link-scope all-nodes multicast address (FF02::1).
// This address is started in Idle Listener state and never transitions to
// another state, and never sends a Report or Done for that address.
//
Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
Group = Ip6CreateMldEntry (IpSb, &AllNodes, (UINT32) IP6_INFINIT_LIFETIME);
if (Group == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = Ip6GetMulticastMac (IpSb->Mnp, &AllNodes, &Group->Mac);
if (EFI_ERROR (Status)) {
goto ERROR;
}
//
// Configure MNP to receive all-nodes multicast
//
Status = IpSb->Mnp->Groups (IpSb->Mnp, TRUE, &Group->Mac);
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
goto ERROR;
}
return EFI_SUCCESS;
ERROR:
RemoveEntryList (&Group->Link);
FreePool (Group);
return Status;
}
/**
Add a group address to the array of group addresses.
The caller should make sure that no duplicated address
existed in the array.
@param[in, out] IpInstance Points to an IP6_PROTOCOL instance.
@param[in] Group The IP6 multicast address to add.
@retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete
the operation.
@retval EFI_SUCESS The address is added to the group address array.
**/
EFI_STATUS
Ip6CombineGroups (
IN OUT IP6_PROTOCOL *IpInstance,
IN EFI_IPv6_ADDRESS *Group
)
{
EFI_IPv6_ADDRESS *GroupList;
NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
ASSERT (Group != NULL && IP6_IS_MULTICAST (Group));
IpInstance->GroupCount++;
GroupList = AllocatePool (IpInstance->GroupCount * sizeof (EFI_IPv6_ADDRESS));
if (GroupList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (IpInstance->GroupCount > 1) {
ASSERT (IpInstance->GroupList != NULL);
CopyMem (
GroupList,
IpInstance->GroupList,
(IpInstance->GroupCount - 1) * sizeof (EFI_IPv6_ADDRESS)
);
FreePool (IpInstance->GroupList);
}
IP6_COPY_ADDRESS (GroupList + (IpInstance->GroupCount - 1), Group);
IpInstance->GroupList = GroupList;
return EFI_SUCCESS;
}
/**
Remove a group address from the array of group addresses.
Although the function doesn't assume the byte order of Group,
the network byte order is used by the caller.
@param[in, out] IpInstance Points to an IP6_PROTOCOL instance.
@param[in] Group The IP6 multicast address to remove.
@retval EFI_NOT_FOUND Cannot find the to be removed group address.
@retval EFI_SUCCESS The group address was successfully removed.
**/
EFI_STATUS
Ip6RemoveGroup (
IN OUT IP6_PROTOCOL *IpInstance,
IN EFI_IPv6_ADDRESS *Group
)
{
UINT32 Index;
UINT32 Count;
Count = IpInstance->GroupCount;
for (Index = 0; Index < Count; Index++) {
if (EFI_IP6_EQUAL (IpInstance->GroupList + Index, Group)) {
break;
}
}
if (Index == Count) {
return EFI_NOT_FOUND;
}
while (Index < Count - 1) {
IP6_COPY_ADDRESS (IpInstance->GroupList + Index, IpInstance->GroupList + Index + 1);
Index++;
}
ASSERT (IpInstance->GroupCount > 0);
IpInstance->GroupCount--;
return EFI_SUCCESS;
}
/**
Join the multicast group on behalf of this IP6 service binding instance.
@param[in] IpSb The IP6 service binding instance.
@param[in] Interface Points to an IP6_INTERFACE structure.
@param[in] Address The group address to join.
@retval EFI_SUCCESS Successfully join the multicast group.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
@retval Others Failed to join the multicast group.
**/
EFI_STATUS
Ip6JoinGroup (
IN IP6_SERVICE *IpSb,
IN IP6_INTERFACE *Interface,
IN EFI_IPv6_ADDRESS *Address
)
{
IP6_MLD_GROUP *Group;
EFI_STATUS Status;
Group = Ip6FindMldEntry (IpSb, Address);
if (Group != NULL) {
Group->RefCnt++;
return EFI_SUCCESS;
}
//
// Repeat the report once or twcie after short delays [Unsolicited Report Interval] (default:10s)
// Simulate this operation as a Multicast-Address-Specific Query was received for that addresss.
//
Group = Ip6CreateMldEntry (IpSb, Address, IP6_UNSOLICITED_REPORT_INTERVAL);
if (Group == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Group->SendByUs = TRUE;
Status = Ip6GetMulticastMac (IpSb->Mnp, Address, &Group->Mac);
if (EFI_ERROR (Status)) {
return Status;
}
Status = IpSb->Mnp->Groups (IpSb->Mnp, TRUE, &Group->Mac);
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
goto ERROR;
}
//
// Send unsolicited report when a node starts listening to a multicast address
//
Status = Ip6SendMldReport (IpSb, Interface, Address);
if (EFI_ERROR (Status)) {
goto ERROR;
}
return EFI_SUCCESS;
ERROR:
RemoveEntryList (&Group->Link);
FreePool (Group);
return Status;
}
/**
Leave the IP6 multicast group.
@param[in] IpSb The IP6 service binding instance.
@param[in] Address The group address to leave.
@retval EFI_NOT_FOUND The IP6 service instance isn't in the group.
@retval EFI_SUCCESS Successfully leave the multicast group..
@retval Others Failed to leave the multicast group.
**/
EFI_STATUS
Ip6LeaveGroup (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Address
)
{
IP6_MLD_GROUP *Group;
EFI_STATUS Status;
Group = Ip6FindMldEntry (IpSb, Address);
if (Group == NULL) {
return EFI_NOT_FOUND;
}
//
// If more than one instance is in the group, decrease
// the RefCnt then return.
//
if ((Group->RefCnt > 0) && (--Group->RefCnt > 0)) {
return EFI_SUCCESS;
}
//
// If multiple IP6 group addresses are mapped to the same
// multicast MAC address, don't configure the MNP to leave
// the MAC.
//
if (Ip6FindMac (&IpSb->MldCtrl, &Group->Mac) == 1) {
Status = IpSb->Mnp->Groups (IpSb->Mnp, FALSE, &Group->Mac);
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
return Status;
}
}
//
// Send a leave report if we are the last node to report
//
if (Group->SendByUs) {
Status = Ip6SendMldDone (IpSb, Address);
if (EFI_ERROR (Status)) {
return Status;
}
}
RemoveEntryList (&Group->Link);
FreePool (Group);
return EFI_SUCCESS;
}
/**
Worker function for EfiIp6Groups(). The caller
should make sure that the parameters are valid.
@param[in] IpInstance The IP6 child to change the setting.
@param[in] JoinFlag TRUE to join the group, otherwise leave it.
@param[in] GroupAddress The target group address. If NULL, leave all
the group addresses.
@retval EFI_ALREADY_STARTED Wants to join the group, but is already a member of it
@retval EFI_OUT_OF_RESOURCES Failed to allocate sufficient resources.
@retval EFI_DEVICE_ERROR Failed to set the group configuraton.
@retval EFI_SUCCESS Successfully updated the group setting.
@retval EFI_NOT_FOUND Try to leave the group which it isn't a member.
**/
EFI_STATUS
Ip6Groups (
IN IP6_PROTOCOL *IpInstance,
IN BOOLEAN JoinFlag,
IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL
)
{
EFI_STATUS Status;
IP6_SERVICE *IpSb;
UINT32 Index;
EFI_IPv6_ADDRESS *Group;
IpSb = IpInstance->Service;
if (JoinFlag) {
ASSERT (GroupAddress != NULL);
for (Index = 0; Index < IpInstance->GroupCount; Index++) {
if (EFI_IP6_EQUAL (IpInstance->GroupList + Index, GroupAddress)) {
return EFI_ALREADY_STARTED;
}
}
Status = Ip6JoinGroup (IpSb, IpInstance->Interface, GroupAddress);
if (!EFI_ERROR (Status)) {
return Ip6CombineGroups (IpInstance, GroupAddress);
}
return Status;
}
//
// Leave the group. Leave all the groups if GroupAddress is NULL.
//
for (Index = IpInstance->GroupCount; Index > 0; Index--) {
Group = IpInstance->GroupList + (Index - 1);
if ((GroupAddress == NULL) || EFI_IP6_EQUAL (Group, GroupAddress)) {
Status = Ip6LeaveGroup (IpInstance->Service, Group);
if (EFI_ERROR (Status)) {
return Status;
}
Ip6RemoveGroup (IpInstance, Group);
if (IpInstance->GroupCount == 0) {
ASSERT (Index == 1);
FreePool (IpInstance->GroupList);
IpInstance->GroupList = NULL;
}
if (GroupAddress != NULL) {
return EFI_SUCCESS;
}
}
}
return ((GroupAddress != NULL) ? EFI_NOT_FOUND : EFI_SUCCESS);
}
/**
Set a random value of the delay timer for the multicast address from the range
[0, Maximum Response Delay]. If a timer for any address is already
running, it is reset to the new random value only if the requested
Maximum Response Delay is less than the remaining value of the
running timer. If the Query packet specifies a Maximum Response
Delay of zero, each timer is effectively set to zero, and the action
specified below for timer expiration is performed immediately.
@param[in] IpSb The IP6 service binding instance.
@param[in] MaxRespDelay The Maximum Response Delay, in milliseconds.
@param[in] MulticastAddr The multicast address.
@param[in, out] Group Points to a IP6_MLD_GROUP list entry node.
@retval EFI_SUCCESS The delay timer is successfully updated or
timer expiration is performed immediately.
@retval Others Failed to send out MLD report message.
**/
EFI_STATUS
Ip6UpdateDelayTimer (
IN IP6_SERVICE *IpSb,
IN UINT16 MaxRespDelay,
IN EFI_IPv6_ADDRESS *MulticastAddr,
IN OUT IP6_MLD_GROUP *Group
)
{
UINT32 Delay;
//
// If the Query packet specifies a Maximum Response Delay of zero, perform timer
// expiration immediately.
//
if (MaxRespDelay == 0) {
Group->DelayTimer = 0;
return Ip6SendMldReport (IpSb, NULL, MulticastAddr);
}
Delay = (UINT32) (MaxRespDelay / 1000);
//
// Sets a delay timer to a random value selected from the range [0, Maximum Response Delay]
// If a timer is already running, resets it if the request Maximum Response Delay
// is less than the remaining value of the running timer.
//
if (Group->DelayTimer == 0 || Delay < Group->DelayTimer) {
Group->DelayTimer = Delay / 4294967295UL * NET_RANDOM (NetRandomInitSeed ());
}
return EFI_SUCCESS;
}
/**
Process the Multicast Listener Query message.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the MLD query packet.
@param[in] Packet The content of the MLD query packet with IP head
removed.
@retval EFI_SUCCESS The MLD query packet processed successfully.
@retval EFI_INVALID_PARAMETER The packet is invalid.
@retval Others Failed to process the packet.
**/
EFI_STATUS
Ip6ProcessMldQuery (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
)
{
EFI_IPv6_ADDRESS AllNodes;
IP6_MLD_GROUP *Group;
IP6_MLD_HEAD MldPacket;
LIST_ENTRY *Entry;
EFI_STATUS Status;
Status = EFI_INVALID_PARAMETER;
//
// Check the validity of the packet, generic query or specific query
//
if (!NetIp6IsUnspecifiedAddr (&Head->SourceAddress) && !NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
goto Exit;
}
if (Head->HopLimit != 1 || !IP6_IS_MULTICAST (&Head->DestinationAddress)) {
goto Exit;
}
//
// The Packet points to MLD report raw data without Hop-By-Hop option.
//
NetbufCopy (Packet, 0, sizeof (IP6_MLD_HEAD), (UINT8 *) &MldPacket);
MldPacket.MaxRespDelay = NTOHS (MldPacket.MaxRespDelay);
Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &AllNodes)) {
//
// Receives a Multicast-Address-Specific Query, check it firstly
//
if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &MldPacket.Group)) {
goto Exit;
}
//
// The node is not listening but it receives the specific query. Just return.
//
Group = Ip6FindMldEntry (IpSb, &MldPacket.Group);
if (Group == NULL) {
Status = EFI_SUCCESS;
goto Exit;
}
Status = Ip6UpdateDelayTimer (
IpSb,
MldPacket.MaxRespDelay,
&MldPacket.Group,
Group
);
goto Exit;
}
//
// Receives a General Query, sets a delay timer for each multicast address it is listening
//
NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
Status = Ip6UpdateDelayTimer (IpSb, MldPacket.MaxRespDelay, &Group->Address, Group);
if (EFI_ERROR (Status)) {
goto Exit;
}
}
Status = EFI_SUCCESS;
Exit:
NetbufFree (Packet);
return Status;
}
/**
Process the Multicast Listener Report message.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the MLD report packet.
@param[in] Packet The content of the MLD report packet with IP head
removed.
@retval EFI_SUCCESS The MLD report packet processed successfully.
@retval EFI_INVALID_PARAMETER The packet is invalid.
**/
EFI_STATUS
Ip6ProcessMldReport (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
)
{
IP6_MLD_HEAD MldPacket;
IP6_MLD_GROUP *Group;
EFI_STATUS Status;
Status = EFI_INVALID_PARAMETER;
//
// Validate the incoming message, if invalid, drop it.
//
if (!NetIp6IsUnspecifiedAddr (&Head->SourceAddress) && !NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
goto Exit;
}
if (Head->HopLimit != 1 || !IP6_IS_MULTICAST (&Head->DestinationAddress)) {
goto Exit;
}
//
// The Packet points to MLD report raw data without Hop-By-Hop option.
//
NetbufCopy (Packet, 0, sizeof (IP6_MLD_HEAD), (UINT8 *) &MldPacket);
if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &MldPacket.Group)) {
goto Exit;
}
Group = Ip6FindMldEntry (IpSb, &MldPacket.Group);
if (Group == NULL) {
goto Exit;
}
//
// The report is sent by another node, stop its own timer relates to the multicast address and clear
//
if (!Group->SendByUs) {
Group->DelayTimer = 0;
}
Status = EFI_SUCCESS;
Exit:
NetbufFree (Packet);
return Status;
}
/**
The heartbeat timer of MLD module. It sends out a solicited MLD report when
DelayTimer expires.
@param[in] IpSb The IP6 service binding instance.
**/
VOID
Ip6MldTimerTicking (
IN IP6_SERVICE *IpSb
)
{
IP6_MLD_GROUP *Group;
LIST_ENTRY *Entry;
//
// Send solicited report when timer expires
//
NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
if ((Group->DelayTimer > 0) && (--Group->DelayTimer == 0)) {
Ip6SendMldReport (IpSb, NULL, &Group->Address);
}
}
}

198
NetworkPkg/Ip6Dxe/Ip6Mld.h Normal file
View File

@@ -0,0 +1,198 @@
/** @file
Multicast Listener Discovery support routines.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6_MLD_H__
#define __EFI_IP6_MLD_H__
#define IP6_UNSOLICITED_REPORT_INTERVAL 10
#pragma pack(1)
typedef struct {
IP6_ICMP_HEAD Head;
UINT16 MaxRespDelay;
UINT16 Reserved;
EFI_IPv6_ADDRESS Group;
} IP6_MLD_HEAD;
#pragma pack()
//
// The status of multicast group. It isn't necessary to maintain
// explicit state of host state diagram. A group with finity
// DelayTime (less than 0xffffffff) is in "delaying listener" state. otherwise, it is in
// "idle listener" state.
//
typedef struct {
LIST_ENTRY Link;
INTN RefCnt;
EFI_IPv6_ADDRESS Address;
UINT32 DelayTimer;
BOOLEAN SendByUs;
EFI_MAC_ADDRESS Mac;
} IP6_MLD_GROUP;
//
// The MLD status. Each IP6 service instance has a MLD_SERVICE_DATA
// attached. The Mldv1QuerySeen remember whether the server on this
// connected network is v1 or v2.
//
typedef struct {
INTN Mldv1QuerySeen;
LIST_ENTRY Groups;
} IP6_MLD_SERVICE_DATA;
/**
Search a IP6_MLD_GROUP list entry node from a list array.
@param[in] IpSb Points to an IP6 service binding instance.
@param[in] MulticastAddr The IPv6 multicast address to be searched.
@return The found IP6_ML_GROUP list entry or NULL.
**/
IP6_MLD_GROUP *
Ip6FindMldEntry (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *MulticastAddr
);
/**
Init the MLD data of the IP6 service instance, configure
MNP to receive ALL SYSTEM multicasts.
@param[in] IpSb The IP6 service whose MLD is to be initialized.
@retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete the
operation.
@retval EFI_SUCCESS The MLD module successfully initialized.
**/
EFI_STATUS
Ip6InitMld (
IN IP6_SERVICE *IpSb
);
/**
Join the multicast group on behalf of this IP6 service binding instance.
@param[in] IpSb The IP6 service binding instance.
@param[in] Interface Points to an IP6_INTERFACE structure.
@param[in] Address The group address to join.
@retval EFI_SUCCESS Successfully joined the multicast group.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
@retval Others Failed to join the multicast group.
**/
EFI_STATUS
Ip6JoinGroup (
IN IP6_SERVICE *IpSb,
IN IP6_INTERFACE *Interface,
IN EFI_IPv6_ADDRESS *Address
);
/**
Leave the IP6 multicast group.
@param[in] IpSb The IP6 service binding instance.
@param[in] Address The group address to leave.
@retval EFI_NOT_FOUND The IP6 service instance isn't in the group.
@retval EFI_SUCCESS Successfully left the multicast group.
@retval Others Failed to leave the multicast group.
**/
EFI_STATUS
Ip6LeaveGroup (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Address
);
/**
Worker function for EfiIp6Groups(). The caller
should verify that the parameters are valid.
@param[in] IpInstance The IP6 child to change the setting.
@param[in] JoinFlag TRUE to join the group, otherwise leave it.
@param[in] GroupAddress The target group address. If NULL, leave all
the group addresses.
@retval EFI_ALREADY_STARTED Wants to join the group, but is already a member of it.
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
@retval EFI_DEVICE_ERROR Failed to set the group configuraton.
@retval EFI_SUCCESS Successfully updated the group setting.
@retval EFI_NOT_FOUND Tried to leave a group of whom it isn't a member.
**/
EFI_STATUS
Ip6Groups (
IN IP6_PROTOCOL *IpInstance,
IN BOOLEAN JoinFlag,
IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL
);
/**
Process the Multicast Listener Query message.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the MLD query packet.
@param[in] Packet The content of the MLD query packet with IP head
removed.
@retval EFI_SUCCESS The MLD query packet processed successfully.
@retval EFI_INVALID_PARAMETER The packet is invalid.
@retval Others Failed to process the packet.
**/
EFI_STATUS
Ip6ProcessMldQuery (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
);
/**
Process the Multicast Listener Report message.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the MLD report packet.
@param[in] Packet The content of the MLD report packet with IP head
removed.
@retval EFI_SUCCESS The MLD report packet processed successfully.
@retval EFI_INVALID_PARAMETER The packet is invalid.
**/
EFI_STATUS
Ip6ProcessMldReport (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
);
/**
The heartbeat timer of the MLD module. It sends out solicited MLD report when
DelayTimer expires.
@param[in] IpSb The IP6 service binding instance.
**/
VOID
Ip6MldTimerTicking (
IN IP6_SERVICE *IpSb
);
#endif

3141
NetworkPkg/Ip6Dxe/Ip6Nd.c Normal file

File diff suppressed because it is too large Load Diff

750
NetworkPkg/Ip6Dxe/Ip6Nd.h Normal file
View File

@@ -0,0 +1,750 @@
/** @file
Definition of Neighbor Discovery support routines.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6_ND_H__
#define __EFI_IP6_ND_H__
#define IP6_GET_TICKS(Ms) (((Ms) + IP6_TIMER_INTERVAL_IN_MS - 1) / IP6_TIMER_INTERVAL_IN_MS)
enum {
IP6_INF_ROUTER_LIFETIME = 0xFFFF,
IP6_MAX_RTR_SOLICITATION_DELAY = 1000, ///< 1000 milliseconds
IP6_MAX_RTR_SOLICITATIONS = 3,
IP6_RTR_SOLICITATION_INTERVAL = 4000,
IP6_MIN_RANDOM_FACTOR_SCALED = 1,
IP6_MAX_RANDOM_FACTOR_SCALED = 3,
IP6_RANDOM_FACTOR_SCALE = 2,
IP6_MAX_MULTICAST_SOLICIT = 3,
IP6_MAX_UNICAST_SOLICIT = 3,
IP6_MAX_ANYCAST_DELAY_TIME = 1,
IP6_MAX_NEIGHBOR_ADV = 3,
IP6_REACHABLE_TIME = 30000,
IP6_RETRANS_TIMER = 1000,
IP6_DELAY_FIRST_PROBE_TIME = 5000,
IP6_MIN_LINK_MTU = 1280,
IP6_MAX_LINK_MTU = 1500,
IP6_IS_ROUTER_FLAG = 0x80,
IP6_SOLICITED_FLAG = 0x40,
IP6_OVERRIDE_FLAG = 0x20,
IP6_M_ADDR_CONFIG_FLAG = 0x80,
IP6_O_CONFIG_FLAG = 0x40,
IP6_ON_LINK_FLAG = 0x80,
IP6_AUTO_CONFIG_FLAG = 0x40,
IP6_ND_LENGTH = 24,
IP6_RA_LENGTH = 16,
IP6_REDITECT_LENGTH = 40,
IP6_DAD_ENTRY_SIGNATURE = SIGNATURE_32 ('I', 'P', 'D', 'E')
};
typedef
VOID
(*IP6_ARP_CALLBACK) (
VOID *Context
);
typedef struct _IP6_ETHE_ADDR_OPTION {
UINT8 Type;
UINT8 Length;
UINT8 EtherAddr[6];
} IP6_ETHER_ADDR_OPTION;
typedef struct _IP6_MTU_OPTION {
UINT8 Type;
UINT8 Length;
UINT16 Reserved;
UINT32 Mtu;
} IP6_MTU_OPTION;
typedef struct _IP6_PREFIX_INFO_OPTION {
UINT8 Type;
UINT8 Length;
UINT8 PrefixLength;
UINT8 Reserved1;
UINT32 ValidLifetime;
UINT32 PreferredLifetime;
UINT32 Reserved2;
EFI_IPv6_ADDRESS Prefix;
} IP6_PREFIX_INFO_OPTION;
typedef
VOID
(*IP6_DAD_CALLBACK) (
IN BOOLEAN IsDadPassed,
IN EFI_IPv6_ADDRESS *TargetAddress,
IN VOID *Context
);
typedef struct _IP6_DAD_ENTRY {
UINT32 Signature;
LIST_ENTRY Link;
UINT32 MaxTransmit;
UINT32 Transmit;
UINT32 Receive;
UINT32 RetransTick;
IP6_ADDRESS_INFO *AddressInfo;
EFI_IPv6_ADDRESS Destination;
IP6_DAD_CALLBACK Callback;
VOID *Context;
} IP6_DAD_ENTRY;
typedef struct _IP6_DELAY_JOIN_LIST {
LIST_ENTRY Link;
UINT32 DelayTime; ///< in tick per 50 milliseconds
IP6_INTERFACE *Interface;
IP6_ADDRESS_INFO *AddressInfo;
IP6_DAD_CALLBACK DadCallback;
VOID *Context;
} IP6_DELAY_JOIN_LIST;
typedef struct _IP6_NEIGHBOR_ENTRY {
LIST_ENTRY Link;
LIST_ENTRY ArpList;
INTN RefCnt;
BOOLEAN IsRouter;
BOOLEAN ArpFree;
BOOLEAN Dynamic;
EFI_IPv6_ADDRESS Neighbor;
EFI_MAC_ADDRESS LinkAddress;
EFI_IP6_NEIGHBOR_STATE State;
UINT32 Transmit;
UINT32 Ticks;
LIST_ENTRY Frames;
IP6_INTERFACE *Interface;
IP6_ARP_CALLBACK CallBack;
} IP6_NEIGHBOR_ENTRY;
typedef struct _IP6_DEFAULT_ROUTER {
LIST_ENTRY Link;
INTN RefCnt;
UINT16 Lifetime;
EFI_IPv6_ADDRESS Router;
IP6_NEIGHBOR_ENTRY *NeighborCache;
} IP6_DEFAULT_ROUTER;
typedef struct _IP6_PREFIX_LIST_ENTRY {
LIST_ENTRY Link;
INTN RefCnt;
UINT32 ValidLifetime;
UINT32 PreferredLifetime;
UINT8 PrefixLength;
EFI_IPv6_ADDRESS Prefix;
} IP6_PREFIX_LIST_ENTRY;
/**
Build a array of EFI_IP6_NEIGHBOR_CACHE to be returned to the caller. The number
of EFI_IP6_NEIGHBOR_CACHE is also returned.
@param[in] IpInstance The pointer to IP6_PROTOCOL instance.
@param[out] NeighborCount The number of returned neighbor cache entries.
@param[out] NeighborCache The pointer to the array of EFI_IP6_NEIGHBOR_CACHE.
@retval EFI_SUCCESS The EFI_IP6_NEIGHBOR_CACHE successfully built.
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the route table.
**/
EFI_STATUS
Ip6BuildEfiNeighborCache (
IN IP6_PROTOCOL *IpInstance,
OUT UINT32 *NeighborCount,
OUT EFI_IP6_NEIGHBOR_CACHE **NeighborCache
);
/**
Build a array of EFI_IP6_ADDRESS_INFO to be returned to the caller. The number
of prefix entries is also returned.
@param[in] IpInstance The pointer to IP6_PROTOCOL instance.
@param[out] PrefixCount The number of returned prefix entries.
@param[out] PrefixTable The pointer to the array of PrefixTable.
@retval EFI_SUCCESS The prefix table successfully built.
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the prefix table.
**/
EFI_STATUS
Ip6BuildPrefixTable (
IN IP6_PROTOCOL *IpInstance,
OUT UINT32 *PrefixCount,
OUT EFI_IP6_ADDRESS_INFO **PrefixTable
);
/**
Allocate and initialize an IP6 default router entry.
@param[in] IpSb The pointer to the IP6_SERVICE instance.
@param[in] Ip6Address The IPv6 address of the default router.
@param[in] RouterLifetime The lifetime associated with the default
router, in units of seconds.
@return NULL if it failed to allocate memory for the default router node.
Otherwise, point to the created default router node.
**/
IP6_DEFAULT_ROUTER *
Ip6CreateDefaultRouter (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Ip6Address,
IN UINT16 RouterLifetime
);
/**
Destroy an IP6 default router entry.
@param[in] IpSb The pointer to the IP6_SERVICE instance.
@param[in] DefaultRouter The to be destroyed IP6_DEFAULT_ROUTER.
**/
VOID
Ip6DestroyDefaultRouter (
IN IP6_SERVICE *IpSb,
IN IP6_DEFAULT_ROUTER *DefaultRouter
);
/**
Clean an IP6 default router list.
@param[in] IpSb The pointer to the IP6_SERVICE instance.
@param[in] DefaultRouter The to be destroyed IP6_DEFAULT_ROUTER.
**/
VOID
Ip6CleanDefaultRouterList (
IN IP6_SERVICE *IpSb
);
/**
Search a default router node from an IP6 default router list.
@param[in] IpSb The pointer to the IP6_SERVICE instance.
@param[in] Ip6Address The IPv6 address of the to be searched default router node.
@return NULL if it failed to find the matching default router node.
Otherwise, point to the found default router node.
**/
IP6_DEFAULT_ROUTER *
Ip6FindDefaultRouter (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Ip6Address
);
/**
The function to be called after DAD (Duplicate Address Detection) is performed.
@param[in] IsDadPassed If TRUE, the DAD operation succeed. Otherwise, the DAD operation failed.
@param[in] IpIf Points to the IP6_INTERFACE.
@param[in] DadEntry The DAD entry which already performed DAD.
**/
VOID
Ip6OnDADFinished (
IN BOOLEAN IsDadPassed,
IN IP6_INTERFACE *IpIf,
IN IP6_DAD_ENTRY *DadEntry
);
/**
Create a DAD (Duplicate Address Detection) entry and queue it to be performed.
@param[in] IpIf Points to the IP6_INTERFACE.
@param[in] AddressInfo The address information which needs DAD performed.
@param[in] Callback The callback routine that will be called after DAD
is performed. This is an optional parameter that
may be NULL.
@param[in] Context The opaque parameter for a DAD callback routine.
This is an optional parameter that may be NULL.
@retval EFI_SUCCESS The DAD entry was created and queued.
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory to complete the
operation.
**/
EFI_STATUS
Ip6InitDADProcess (
IN IP6_INTERFACE *IpIf,
IN IP6_ADDRESS_INFO *AddressInfo,
IN IP6_DAD_CALLBACK Callback OPTIONAL,
IN VOID *Context OPTIONAL
);
/**
Search IP6_DAD_ENTRY from the Duplicate Address Detection List.
@param[in] IpSb The pointer to the IP6_SERVICE instance.
@param[in] Target The address information which needs DAD performed .
@param[out] Interface If not NULL, output the IP6 interface that configures
the tentative address.
@return NULL if failed to find the matching DAD entry.
Otherwise, point to the found DAD entry.
**/
IP6_DAD_ENTRY *
Ip6FindDADEntry (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Target,
OUT IP6_INTERFACE **Interface OPTIONAL
);
/**
Allocate and initialize a IP6 prefix list entry.
@param[in] IpSb The pointer to IP6_SERVICE instance.
@param[in] OnLinkOrAuto If TRUE, the entry is created for the on link prefix list.
Otherwise, it is created for the autoconfiguration prefix list.
@param[in] ValidLifetime The length of time in seconds that the prefix
is valid for the purpose of on-link determination.
@param[in] PreferredLifetime The length of time in seconds that addresses
generated from the prefix via stateless address
autoconfiguration remain preferred.
@param[in] PrefixLength The prefix length of the Prefix.
@param[in] Prefix The prefix address.
@return NULL if it failed to allocate memory for the prefix node. Otherwise, point
to the created or existing prefix list entry.
**/
IP6_PREFIX_LIST_ENTRY *
Ip6CreatePrefixListEntry (
IN IP6_SERVICE *IpSb,
IN BOOLEAN OnLinkOrAuto,
IN UINT32 ValidLifetime,
IN UINT32 PreferredLifetime,
IN UINT8 PrefixLength,
IN EFI_IPv6_ADDRESS *Prefix
);
/**
Destory a IP6 prefix list entry.
@param[in] IpSb The pointer to IP6_SERVICE instance.
@param[in] PrefixEntry The to be destroyed prefix list entry.
@param[in] OnLinkOrAuto If TRUE, the entry is removed from on link prefix list.
Otherwise remove from autoconfiguration prefix list.
@param[in] ImmediateDelete If TRUE, remove the entry directly.
Otherwise, check the reference count to see whether
it should be removed.
**/
VOID
Ip6DestroyPrefixListEntry (
IN IP6_SERVICE *IpSb,
IN IP6_PREFIX_LIST_ENTRY *PrefixEntry,
IN BOOLEAN OnLinkOrAuto,
IN BOOLEAN ImmediateDelete
);
/**
Search the list array to find an IP6 prefix list entry.
@param[in] IpSb The pointer to IP6_SERVICE instance.
@param[in] OnLinkOrAuto If TRUE, the search the link prefix list,
Otherwise search the autoconfiguration prefix list.
@param[in] PrefixLength The prefix length of the Prefix
@param[in] Prefix The prefix address.
@return NULL if cannot find the IP6 prefix list entry. Otherwise, return the
pointer to the IP6 prefix list entry.
**/
IP6_PREFIX_LIST_ENTRY *
Ip6FindPrefixListEntry (
IN IP6_SERVICE *IpSb,
IN BOOLEAN OnLinkOrAuto,
IN UINT8 PrefixLength,
IN EFI_IPv6_ADDRESS *Prefix
);
/**
Release the resource in prefix list table, and destroy the list entry and
corresponding addresses or route entries.
@param[in] IpSb The pointer to the IP6_SERVICE instance.
@param[in] ListHead The list entry head of the prefix list table.
**/
VOID
Ip6CleanPrefixListTable (
IN IP6_SERVICE *IpSb,
IN LIST_ENTRY *ListHead
);
/**
Allocate and initialize an IP6 neighbor cache entry.
@param[in] IpSb The pointer to the IP6_SERVICE instance.
@param[in] CallBack The callback function to be called when
address resolution is finished.
@param[in] Ip6Address Points to the IPv6 address of the neighbor.
@param[in] LinkAddress Points to the MAC address of the neighbor.
Ignored if NULL.
@return NULL if failed to allocate memory for the neighbor cache entry.
Otherwise, point to the created neighbor cache entry.
**/
IP6_NEIGHBOR_ENTRY *
Ip6CreateNeighborEntry (
IN IP6_SERVICE *IpSb,
IN IP6_ARP_CALLBACK CallBack,
IN EFI_IPv6_ADDRESS *Ip6Address,
IN EFI_MAC_ADDRESS *LinkAddress OPTIONAL
);
/**
Search a IP6 neighbor cache entry.
@param[in] IpSb The pointer to the IP6_SERVICE instance.
@param[in] Ip6Address Points to the IPv6 address of the neighbor.
@return NULL if it failed to find the matching neighbor cache entry.
Otherwise, point to the found neighbor cache entry.
**/
IP6_NEIGHBOR_ENTRY *
Ip6FindNeighborEntry (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Ip6Address
);
/**
Free a IP6 neighbor cache entry and remove all the frames on the address
resolution queue that pass the FrameToCancel. That is, either FrameToCancel
is NULL, or it returns true for the frame.
@param[in] IpSb The pointer to the IP6_SERVICE instance.
@param[in] NeighborCache The to be free neighbor cache entry.
@param[in] SendIcmpError If TRUE, send out ICMP error.
@param[in] FullFree If TRUE, remove the neighbor cache entry.
Otherwise remove the pending frames.
@param[in] IoStatus The status returned to the cancelled frames'
callback function.
@param[in] FrameToCancel Function to select which frame to cancel.
This is an optional parameter that may be NULL.
@param[in] Context Opaque parameter to the FrameToCancel.
Ignored if FrameToCancel is NULL.
@retval EFI_INVALID_PARAMETER The input parameter is invalid.
@retval EFI_SUCCESS The operation finished successfully.
**/
EFI_STATUS
Ip6FreeNeighborEntry (
IN IP6_SERVICE *IpSb,
IN IP6_NEIGHBOR_ENTRY *NeighborCache,
IN BOOLEAN SendIcmpError,
IN BOOLEAN FullFree,
IN EFI_STATUS IoStatus,
IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
IN VOID *Context OPTIONAL
);
/**
Add Neighbor cache entries. It is a work function for EfiIp6Neighbors().
@param[in] IpSb The IP6 service binding instance.
@param[in] TargetIp6Address Pointer to Target IPv6 address.
@param[in] TargetLinkAddress Pointer to link-layer address of the target. Ignored if NULL.
@param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor
cache. It will be deleted after Timeout. A value of zero means that
the entry is permanent. A non-zero value means that the entry is
dynamic.
@param[in] Override If TRUE, the cached link-layer address of the matching entry will
be overridden and updated; if FALSE, and if a
corresponding cache entry already existed, EFI_ACCESS_DENIED
will be returned.
@retval EFI_SUCCESS The neighbor cache entry has been added.
@retval EFI_OUT_OF_RESOURCES Could not add the entry to the neighbor cache
due to insufficient resources.
@retval EFI_NOT_FOUND TargetLinkAddress is NULL.
@retval EFI_ACCESS_DENIED The to-be-added entry is already defined in the neighbor cache,
and that entry is tagged as un-overridden (when DeleteFlag
is FALSE).
**/
EFI_STATUS
Ip6AddNeighbor (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *TargetIp6Address,
IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
IN UINT32 Timeout,
IN BOOLEAN Override
);
/**
Delete or update Neighbor cache entries. It is a work function for EfiIp6Neighbors().
@param[in] IpSb The IP6 service binding instance.
@param[in] TargetIp6Address Pointer to Target IPv6 address.
@param[in] TargetLinkAddress Pointer to link-layer address of the target. Ignored if NULL.
@param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor
cache. It will be deleted after Timeout. A value of zero means that
the entry is permanent. A non-zero value means that the entry is
dynamic.
@param[in] Override If TRUE, the cached link-layer address of the matching entry will
be overridden and updated; if FALSE, and if a
corresponding cache entry already existed, EFI_ACCESS_DENIED
will be returned.
@retval EFI_SUCCESS The neighbor cache entry has been updated or deleted.
@retval EFI_NOT_FOUND This entry is not in the neighbor cache.
**/
EFI_STATUS
Ip6DelNeighbor (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *TargetIp6Address,
IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
IN UINT32 Timeout,
IN BOOLEAN Override
);
/**
Process the Neighbor Solicitation message. The message may be sent for Duplicate
Address Detection or Address Resolution.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the message.
@param[in] Packet The content of the message with IP head removed.
@retval EFI_SUCCESS The packet processed successfully.
@retval EFI_INVALID_PARAMETER The packet is invalid.
@retval EFI_ICMP_ERROR The packet indicates that DAD is failed.
@retval Others Failed to process the packet.
**/
EFI_STATUS
Ip6ProcessNeighborSolicit (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
);
/**
Process the Neighbor Advertisement message.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the message.
@param[in] Packet The content of the message with IP head removed.
@retval EFI_SUCCESS The packet processed successfully.
@retval EFI_INVALID_PARAMETER The packet is invalid.
@retval EFI_ICMP_ERROR The packet indicates that DAD is failed.
@retval Others Failed to process the packet.
**/
EFI_STATUS
Ip6ProcessNeighborAdvertise (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
);
/**
Process the Router Advertisement message according to RFC4861.
@param[in] IpSb The IP service that received the packet.
@param[in] Head The IP head of the message.
@param[in] Packet The content of the message with the IP head removed.
@retval EFI_SUCCESS The packet processed successfully.
@retval EFI_INVALID_PARAMETER The packet is invalid.
@retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the operation.
@retval Others Failed to process the packet.
**/
EFI_STATUS
Ip6ProcessRouterAdvertise (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
);
/**
Process the ICMPv6 redirect message. Find the instance, then update
its route cache.
@param[in] IpSb The IP6 service binding instance that received
the packet.
@param[in] Head The IP head of the received ICMPv6 packet.
@param[in] Packet The content of the ICMPv6 redirect packet with
the IP head removed.
@retval EFI_INVALID_PARAMETER The parameter is invalid.
@retval EFI_OUT_OF_RESOURCES Insuffcient resources to complete the
operation.
@retval EFI_SUCCESS Successfully updated the route caches.
**/
EFI_STATUS
Ip6ProcessRedirect (
IN IP6_SERVICE *IpSb,
IN EFI_IP6_HEADER *Head,
IN NET_BUF *Packet
);
/**
Generate router solicit message and send it out to Destination Address or
All Router Link Local scope multicast address.
@param[in] IpSb The IP service to send the packet.
@param[in] Interface If not NULL, points to the IP6 interface to send
the packet.
@param[in] SourceAddress If not NULL, the source address of the message.
@param[in] DestinationAddress If not NULL, the destination address of the message.
@param[in] SourceLinkAddress If not NULL, the MAC address of the source.
A source link-layer address option will be appended
to the message.
@retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the operation.
@retval EFI_SUCCESS The router solicit message was successfully sent.
**/
EFI_STATUS
Ip6SendRouterSolicit (
IN IP6_SERVICE *IpSb,
IN IP6_INTERFACE *Interface OPTIONAL,
IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
IN EFI_IPv6_ADDRESS *DestinationAddress OPTIONAL,
IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL
);
/**
Generate the Neighbor Solicitation message and send it to the Destination Address.
@param[in] IpSb The IP service to send the packet
@param[in] SourceAddress The source address of the message.
@param[in] DestinationAddress The destination address of the message.
@param[in] TargetIp6Address The IP address of the target of the solicitation.
It must not be a multicast address.
@param[in] SourceLinkAddress The MAC address for the sender. If not NULL,
a source link-layer address option will be appended
to the message.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
@retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the
operation.
@retval EFI_SUCCESS The Neighbor Advertise message was successfully sent.
**/
EFI_STATUS
Ip6SendNeighborSolicit (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *SourceAddress,
IN EFI_IPv6_ADDRESS *DestinationAddress,
IN EFI_IPv6_ADDRESS *TargetIp6Address,
IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL
);
/**
Set the interface's address. This will trigger the DAD process for the
address to set. To set an already set address, the lifetimes wil be
updated to the new value passed in.
@param[in] Interface The interface to set the address.
@param[in] Ip6Addr The interface's to be assigned IPv6 address.
@param[in] IsAnycast If TRUE, the unicast IPv6 address is anycast.
Otherwise, it is not anycast.
@param[in] PrefixLength The prefix length of the Ip6Addr.
@param[in] ValidLifetime The valid lifetime for this address.
@param[in] PreferredLifetime The preferred lifetime for this address.
@param[in] DadCallback The caller's callback to trigger when DAD finishes.
This is an optional parameter that may be NULL.
@param[in] Context The context that will be passed to DadCallback.
This is an optional parameter that may be NULL.
@retval EFI_SUCCESS The interface is scheduled to be configured with
the specified address.
@retval EFI_OUT_OF_RESOURCES Failed to set the interface's address due to
lack of resources.
**/
EFI_STATUS
Ip6SetAddress (
IN IP6_INTERFACE *Interface,
IN EFI_IPv6_ADDRESS *Ip6Addr,
IN BOOLEAN IsAnycast,
IN UINT8 PrefixLength,
IN UINT32 ValidLifetime,
IN UINT32 PreferredLifetime,
IN IP6_DAD_CALLBACK DadCallback OPTIONAL,
IN VOID *Context OPTIONAL
);
/**
The heartbeat timer of ND module in IP6_TIMER_INTERVAL_IN_MS milliseconds.
This time routine handles DAD module and neighbor state transition.
It is also responsible for sending out router solicitations.
@param[in] Event The IP6 service instance's heartbeat timer.
@param[in] Context The IP6 service instance.
**/
VOID
EFIAPI
Ip6NdFasterTimerTicking (
IN EFI_EVENT Event,
IN VOID *Context
);
/**
The heartbeat timer of ND module in 1 second. This time routine handles following
things: 1) maitain default router list; 2) maintain prefix options;
3) maintain route caches.
@param[in] IpSb The IP6 service binding instance.
**/
VOID
Ip6NdTimerTicking (
IN IP6_SERVICE *IpSb
);
/**
Callback function when address resolution is finished. It will cancel
all the queued frames if the address resolution failed, or transmit them
if the request succeeded.
@param[in] Context The context of the callback, a pointer to IP6_NEIGHBOR_ENTRY.
**/
VOID
Ip6OnArpResolved (
IN VOID *Context
);
/**
Update the ReachableTime in IP6 service binding instance data, in milliseconds.
@param[in, out] IpSb Points to the IP6_SERVICE.
**/
VOID
Ip6UpdateReachableTime (
IN OUT IP6_SERVICE *IpSb
);
#endif

View File

@@ -0,0 +1,70 @@
/** @file
NVData structure used by the IP6 configuration component.
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _IP6_NV_DATA_H_
#define _IP6_NV_DATA_H_
#define IP6_CONFIG_NVDATA_GUID \
{ \
0x2eea107, 0x98db, 0x400e, { 0x98, 0x30, 0x46, 0xa, 0x15, 0x42, 0xd7, 0x99 } \
}
#define FORMID_MAIN_FORM 1
#define FORMID_MANUAL_CONFIG_FORM 2
#define IP6_POLICY_AUTO 0
#define IP6_POLICY_MANUAL 1
#define DAD_MAX_TRANSMIT_COUNT 10
#define KEY_INTERFACE_ID 0x101
#define KEY_MANUAL_ADDRESS 0x102
#define KEY_GATEWAY_ADDRESS 0x103
#define KEY_DNS_ADDRESS 0x104
#define KEY_SAVE_CHANGES 0x105
#define KEY_SAVE_CONFIG_CHANGES 0x106
#define KEY_IGNORE_CONFIG_CHANGES 0x107
#define HOST_ADDRESS_LABEL 0x9000
#define ROUTE_TABLE_LABEL 0xa000
#define GATEWAY_ADDRESS_LABEL 0xb000
#define DNS_ADDRESS_LABEL 0xc000
#define LABEL_END 0xffff
#define INTERFACE_ID_STR_MIN_SIZE 1
#define INTERFACE_ID_STR_MAX_SIZE 23
#define INTERFACE_ID_STR_STORAGE 24
#define IP6_STR_MAX_SIZE 40
#define ADDRESS_STR_MIN_SIZE 2
#define ADDRESS_STR_MAX_SIZE 255
///
/// IP6_CONFIG_IFR_NVDATA contains the IP6 configure
/// parameters for that NIC.
///
#pragma pack(1)
typedef struct {
UINT8 IfType; ///< interface type
UINT8 Padding[3];
UINT32 Policy; ///< manual or automatic
UINT32 DadTransmitCount; ///< dad transmits count
CHAR16 InterfaceId[INTERFACE_ID_STR_STORAGE]; ///< alternative interface id
CHAR16 ManualAddress[ADDRESS_STR_MAX_SIZE]; ///< IP addresses
CHAR16 GatewayAddress[ADDRESS_STR_MAX_SIZE]; ///< Gateway address
CHAR16 DnsAddress[ADDRESS_STR_MAX_SIZE]; ///< DNS server address
} IP6_CONFIG_IFR_NVDATA;
#pragma pack()
#endif

View File

@@ -0,0 +1,758 @@
/** @file
IP6 option support functions and routines.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ip6Impl.h"
/**
Validate the IP6 option format for both the packets we received
and that we will transmit. It will compute the ICMPv6 error message fields
if the option is malformated.
@param[in] IpSb The IP6 service data.
@param[in] Packet The to be validated packet.
@param[in] Option The first byte of the option.
@param[in] OptionLen The length of the whole option.
@param[in] Pointer Identifies the octet offset within
the invoking packet where the error was detected.
@retval TRUE The option is properly formatted.
@retval FALSE The option is malformated.
**/
BOOLEAN
Ip6IsOptionValid (
IN IP6_SERVICE *IpSb,
IN NET_BUF *Packet,
IN UINT8 *Option,
IN UINT8 OptionLen,
IN UINT32 Pointer
)
{
UINT8 Offset;
UINT8 OptionType;
Offset = 0;
while (Offset < OptionLen) {
OptionType = *(Option + Offset);
switch (OptionType) {
case Ip6OptionPad1:
//
// It is a Pad1 option
//
Offset++;
break;
case Ip6OptionPadN:
//
// It is a PadN option
//
Offset = (UINT8) (Offset + *(Option + Offset + 1) + 2);
break;
case Ip6OptionRouterAlert:
//
// It is a Router Alert Option
//
Offset += 4;
break;
default:
//
// The highest-order two bits specify the action must be taken if
// the processing IPv6 node does not recognize the option type.
//
switch (OptionType & Ip6OptionMask) {
case Ip6OptionSkip:
Offset = (UINT8) (Offset + *(Option + Offset + 1));
break;
case Ip6OptionDiscard:
return FALSE;
case Ip6OptionParameterProblem:
Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER);
Ip6SendIcmpError (
IpSb,
Packet,
NULL,
&Packet->Ip.Ip6->SourceAddress,
ICMP_V6_PARAMETER_PROBLEM,
2,
&Pointer
);
return FALSE;
case Ip6OptionMask:
if (!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER);
Ip6SendIcmpError (
IpSb,
Packet,
NULL,
&Packet->Ip.Ip6->SourceAddress,
ICMP_V6_PARAMETER_PROBLEM,
2,
&Pointer
);
}
return FALSE;
break;
}
break;
}
}
return TRUE;
}
/**
Validate the IP6 option format for both the packets we received
and that we will transmit. It supports the defined options in Neighbor
Discovery messages.
@param[in] Option The first byte of the option.
@param[in] OptionLen The length of the whole option.
@retval TRUE The option is properly formatted.
@retval FALSE The option is malformated.
**/
BOOLEAN
Ip6IsNDOptionValid (
IN UINT8 *Option,
IN UINT16 OptionLen
)
{
UINT16 Offset;
UINT8 OptionType;
UINT16 Length;
Offset = 0;
while (Offset < OptionLen) {
OptionType = *(Option + Offset);
Length = (UINT16) (*(Option + Offset + 1) * 8);
switch (OptionType) {
case Ip6OptionPrefixInfo:
if (Length != 32) {
return FALSE;
}
break;
case Ip6OptionMtu:
if (Length != 8) {
return FALSE;
}
break;
default:
//
// Check the length of Ip6OptionEtherSource, Ip6OptionEtherTarget, and
// Ip6OptionRedirected here. For unrecognized options, silently ignore
// and continue processsing the message.
//
if (Length == 0) {
return FALSE;
}
break;
}
Offset = (UINT16) (Offset + Length);
}
return TRUE;
}
/**
Validate whether the NextHeader is a known valid protocol or one of the user configured
protocols from the upper layer.
@param[in] IpSb The IP6 service instance.
@param[in] NextHeader The next header field.
@retval TRUE The NextHeader is a known valid protocol or user configured.
@retval FALSE The NextHeader is not a known valid protocol.
**/
BOOLEAN
Ip6IsValidProtocol (
IN IP6_SERVICE *IpSb,
IN UINT8 NextHeader
)
{
LIST_ENTRY *Entry;
IP6_PROTOCOL *IpInstance;
if (NextHeader == EFI_IP_PROTO_TCP ||
NextHeader == EFI_IP_PROTO_UDP ||
NextHeader == IP6_ICMP ||
NextHeader == IP6_ESP
) {
return TRUE;
}
if (IpSb == NULL) {
return FALSE;
}
if (IpSb->Signature != IP6_SERVICE_SIGNATURE) {
return FALSE;
}
NET_LIST_FOR_EACH (Entry, &IpSb->Children) {
IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);
if (IpInstance->State == IP6_STATE_CONFIGED) {
if (IpInstance->ConfigData.DefaultProtocol == NextHeader) {
return TRUE;
}
}
}
return FALSE;
}
/**
Validate the IP6 extension header format for both the packets we received
and that we will transmit. It will compute the ICMPv6 error message fields
if the option is mal-formated.
@param[in] IpSb The IP6 service instance. This is an optional parameter.
@param[in] Packet The data of the packet. Ignored if NULL.
@param[in] NextHeader The next header field in IPv6 basic header.
@param[in] ExtHdrs The first byte of the option.
@param[in] ExtHdrsLen The length of the whole option.
@param[in] Rcvd The option is from the packet we received if TRUE,
otherwise, the option we want to transmit.
@param[out] FormerHeader The offset of NextHeader which points to Fragment
Header when we received, of the ExtHdrs.
Ignored if we transmit.
@param[out] LastHeader The pointer of NextHeader of the last extension
header processed by IP6.
@param[out] RealExtsLen The length of extension headers processed by IP6 layer.
This is an optional parameter that may be NULL.
@param[out] UnFragmentLen The length of unfragmented length of extension headers.
This is an optional parameter that may be NULL.
@param[out] Fragmented Indicate whether the packet is fragmented.
This is an optional parameter that may be NULL.
@retval TRUE The option is properly formated.
@retval FALSE The option is malformated.
**/
BOOLEAN
Ip6IsExtsValid (
IN IP6_SERVICE *IpSb OPTIONAL,
IN NET_BUF *Packet OPTIONAL,
IN UINT8 *NextHeader,
IN UINT8 *ExtHdrs,
IN UINT32 ExtHdrsLen,
IN BOOLEAN Rcvd,
OUT UINT32 *FormerHeader OPTIONAL,
OUT UINT8 **LastHeader,
OUT UINT32 *RealExtsLen OPTIONAL,
OUT UINT32 *UnFragmentLen OPTIONAL,
OUT BOOLEAN *Fragmented OPTIONAL
)
{
UINT32 Pointer;
UINT32 Offset;
UINT8 *Option;
UINT8 OptionLen;
BOOLEAN Flag;
UINT8 CountD;
UINT8 CountA;
IP6_FRAGMENT_HEADER *FragmentHead;
UINT16 FragmentOffset;
IP6_ROUTING_HEADER *RoutingHead;
if (RealExtsLen != NULL) {
*RealExtsLen = 0;
}
if (UnFragmentLen != NULL) {
*UnFragmentLen = 0;
}
if (Fragmented != NULL) {
*Fragmented = FALSE;
}
*LastHeader = NextHeader;
if (ExtHdrs == NULL && ExtHdrsLen == 0) {
return TRUE;
}
if ((ExtHdrs == NULL && ExtHdrsLen != 0) || (ExtHdrs != NULL && ExtHdrsLen == 0)) {
return FALSE;
}
Pointer = 0;
Offset = 0;
Flag = FALSE;
CountD = 0;
CountA = 0;
while (Offset <= ExtHdrsLen) {
switch (*NextHeader) {
case IP6_HOP_BY_HOP:
if (Offset != 0) {
if (!Rcvd) {
return FALSE;
}
//
// Hop-by-Hop Options header is restricted to appear immediately after an IPv6 header only.
// If not, generate a ICMP parameter problem message with code value of 1.
//
if (Pointer == 0) {
Pointer = sizeof (EFI_IP6_HEADER);
} else {
Pointer = Offset + sizeof (EFI_IP6_HEADER);
}
if ((IpSb != NULL) && (Packet != NULL) &&
!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
Ip6SendIcmpError (
IpSb,
Packet,
NULL,
&Packet->Ip.Ip6->SourceAddress,
ICMP_V6_PARAMETER_PROBLEM,
1,
&Pointer
);
}
return FALSE;
}
Flag = TRUE;
//
// Fall through
//
case IP6_DESTINATION:
if (*NextHeader == IP6_DESTINATION) {
CountD++;
}
if (CountD > 2) {
return FALSE;
}
NextHeader = ExtHdrs + Offset;
Pointer = Offset;
Offset++;
Option = ExtHdrs + Offset;
OptionLen = (UINT8) ((*Option + 1) * 8 - 2);
Option++;
Offset++;
if (IpSb != NULL && Packet != NULL && !Ip6IsOptionValid (IpSb, Packet, Option, OptionLen, Offset)) {
return FALSE;
}
Offset = Offset + OptionLen;
if (Flag) {
if (UnFragmentLen != NULL) {
*UnFragmentLen = Offset;
}
Flag = FALSE;
}
break;
case IP6_ROUTING:
NextHeader = ExtHdrs + Offset;
RoutingHead = (IP6_ROUTING_HEADER *) NextHeader;
//
// Type 0 routing header is defined in RFC2460 and deprecated in RFC5095.
// Thus all routing types are processed as unrecognized.
//
if (RoutingHead->SegmentsLeft == 0) {
//
// Ignore the routing header and proceed to process the next header.
//
Offset = Offset + (RoutingHead->HeaderLen + 1) * 8;
if (UnFragmentLen != NULL) {
*UnFragmentLen = Offset;
}
} else {
//
// Discard the packet and send an ICMP Parameter Problem, Code 0, message
// to the packet's source address, pointing to the unrecognized routing
// type.
//
Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER);
if ((IpSb != NULL) && (Packet != NULL) &&
!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
Ip6SendIcmpError (
IpSb,
Packet,
NULL,
&Packet->Ip.Ip6->SourceAddress,
ICMP_V6_PARAMETER_PROBLEM,
0,
&Pointer
);
}
return FALSE;
}
break;
case IP6_FRAGMENT:
//
// RFC2402, AH header should after fragment header.
//
if (CountA > 1) {
return FALSE;
}
//
// RFC2460, ICMP Parameter Problem message with code 0 should be sent
// if the length of a fragment is not a multiple of 8 octects and the M
// flag of that fragment is 1, pointing to the Payload length field of the
// fragment packet.
//
if (IpSb != NULL && Packet != NULL && (ExtHdrsLen % 8) != 0) {
//
// Check whether it is the last fragment.
//
FragmentHead = (IP6_FRAGMENT_HEADER *) (ExtHdrs + Offset);
if (FragmentHead == NULL) {
return FALSE;
}
FragmentOffset = NTOHS (FragmentHead->FragmentOffset);
if (((FragmentOffset & 0x1) == 0x1) &&
!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
Pointer = sizeof (UINT32);
Ip6SendIcmpError (
IpSb,
Packet,
NULL,
&Packet->Ip.Ip6->SourceAddress,
ICMP_V6_PARAMETER_PROBLEM,
0,
&Pointer
);
return FALSE;
}
}
if (Fragmented != NULL) {
*Fragmented = TRUE;
}
if (Rcvd && FormerHeader != NULL) {
*FormerHeader = (UINT32) (NextHeader - ExtHdrs);
}
NextHeader = ExtHdrs + Offset;
Offset = Offset + 8;
break;
case IP6_AH:
if (++CountA > 1) {
return FALSE;
}
Option = ExtHdrs + Offset;
NextHeader = Option;
Option++;
//
// RFC2402, Payload length is specified in 32-bit words, minus "2".
//
OptionLen = (UINT8) ((*Option + 2) * 4);
Offset = Offset + OptionLen;
break;
case IP6_NO_NEXT_HEADER:
*LastHeader = NextHeader;
return FALSE;
break;
default:
if (Ip6IsValidProtocol (IpSb, *NextHeader)) {
*LastHeader = NextHeader;
if (RealExtsLen != NULL) {
*RealExtsLen = Offset;
}
return TRUE;
}
//
// The Next Header value is unrecognized by the node, discard the packet and
// send an ICMP parameter problem message with code value of 1.
//
if (Offset == 0) {
//
// The Next Header directly follows IPv6 basic header.
//
Pointer = 6;
} else {
if (Pointer == 0) {
Pointer = sizeof (EFI_IP6_HEADER);
} else {
Pointer = Offset + sizeof (EFI_IP6_HEADER);
}
}
if ((IpSb != NULL) && (Packet != NULL) &&
!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
Ip6SendIcmpError (
IpSb,
Packet,
NULL,
&Packet->Ip.Ip6->SourceAddress,
ICMP_V6_PARAMETER_PROBLEM,
1,
&Pointer
);
}
return FALSE;
}
}
*LastHeader = NextHeader;
if (RealExtsLen != NULL) {
*RealExtsLen = Offset;
}
return TRUE;
}
/**
Generate an IPv6 router alert option in network order and output it through Buffer.
@param[out] Buffer Points to a buffer to record the generated option.
@param[in, out] BufferLen The length of Buffer, in bytes.
@param[in] NextHeader The 8-bit selector indicates the type of header
immediately following the Hop-by-Hop Options header.
@retval EFI_BUFFER_TOO_SMALL The Buffer is too small to contain the generated
option. BufferLen is updated for the required size.
@retval EFI_SUCCESS The option is generated and filled in to Buffer.
**/
EFI_STATUS
Ip6FillHopByHop (
OUT UINT8 *Buffer,
IN OUT UINTN *BufferLen,
IN UINT8 NextHeader
)
{
UINT8 BufferArray[8];
if (*BufferLen < 8) {
*BufferLen = 8;
return EFI_BUFFER_TOO_SMALL;
}
//
// Form the Hop-By-Hop option in network order.
// NextHeader (1 octet) + HdrExtLen (1 octet) + RouterAlertOption(4 octets) + PadN
// The Hdr Ext Len is the length in 8-octet units, and does not including the first 8 octets.
//
ZeroMem (BufferArray, sizeof (BufferArray));
BufferArray[0] = NextHeader;
BufferArray[2] = 0x5;
BufferArray[3] = 0x2;
BufferArray[6] = 1;
CopyMem (Buffer, BufferArray, sizeof (BufferArray));
return EFI_SUCCESS;
}
/**
Insert a Fragment Header to the Extension headers and output it in UpdatedExtHdrs.
@param[in] IpSb The IP6 service instance to transmit the packet.
@param[in] NextHeader The extension header type of first extension header.
@param[in] LastHeader The extension header type of last extension header.
@param[in] ExtHdrs The length of the original extension header.
@param[in] ExtHdrsLen The length of the extension headers.
@param[in] FragmentOffset The fragment offset of the data following the header.
@param[out] UpdatedExtHdrs The updated ExtHdrs with Fragment header inserted.
It's caller's responsiblity to free this buffer.
@retval EFI_OUT_OF_RESOURCES Failed to finish the operation due to lake of
resource.
@retval EFI_UNSUPPORTED The extension header specified in ExtHdrs is not
supported currently.
@retval EFI_SUCCESS The operation performed successfully.
**/
EFI_STATUS
Ip6FillFragmentHeader (
IN IP6_SERVICE *IpSb,
IN UINT8 NextHeader,
IN UINT8 LastHeader,
IN UINT8 *ExtHdrs,
IN UINT32 ExtHdrsLen,
IN UINT16 FragmentOffset,
OUT UINT8 **UpdatedExtHdrs
)
{
UINT32 Length;
UINT8 *Buffer;
UINT32 FormerHeader;
UINT32 Offset;
UINT32 Part1Len;
UINT32 HeaderLen;
UINT8 Current;
IP6_FRAGMENT_HEADER FragmentHead;
if (UpdatedExtHdrs == NULL) {
return EFI_INVALID_PARAMETER;
}
Length = ExtHdrsLen + sizeof (IP6_FRAGMENT_HEADER);
Buffer = AllocatePool (Length);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Offset = 0;
Part1Len = 0;
FormerHeader = 0;
Current = NextHeader;
while ((ExtHdrs != NULL) && (Offset <= ExtHdrsLen)) {
switch (NextHeader) {
case IP6_ROUTING:
case IP6_HOP_BY_HOP:
case IP6_DESTINATION:
Current = NextHeader;
NextHeader = *(ExtHdrs + Offset);
if ((Current == IP6_DESTINATION) && (NextHeader != IP6_ROUTING)) {
//
// Destination Options header should occur at most twice, once before
// a Routing header and once before the upper-layer header. Here we
// find the one before the upper-layer header. Insert the Fragment
// Header before it.
//
CopyMem (Buffer, ExtHdrs, Part1Len);
*(Buffer + FormerHeader) = IP6_FRAGMENT;
//
// Exit the loop.
//
Offset = ExtHdrsLen + 1;
break;
}
FormerHeader = Offset;
HeaderLen = (*(ExtHdrs + Offset + 1) + 1) * 8;
Part1Len = Part1Len + HeaderLen;
Offset = Offset + HeaderLen;
break;
case IP6_FRAGMENT:
Current = NextHeader;
if (Part1Len != 0) {
CopyMem (Buffer, ExtHdrs, Part1Len);
}
*(Buffer + FormerHeader) = IP6_FRAGMENT;
//
// Exit the loop.
//
Offset = ExtHdrsLen + 1;
break;
case IP6_AH:
Current = NextHeader;
NextHeader = *(ExtHdrs + Offset);
//
// RFC2402, Payload length is specified in 32-bit words, minus "2".
//
HeaderLen = (*(ExtHdrs + Offset + 1) + 2) * 4;
Part1Len = Part1Len + HeaderLen;
Offset = Offset + HeaderLen;
break;
default:
if (Ip6IsValidProtocol (IpSb, NextHeader)) {
Current = NextHeader;
CopyMem (Buffer, ExtHdrs, Part1Len);
*(Buffer + FormerHeader) = IP6_FRAGMENT;
//
// Exit the loop.
//
Offset = ExtHdrsLen + 1;
break;
}
FreePool (Buffer);
return EFI_UNSUPPORTED;
}
}
//
// Append the Fragment header. If the fragment offset indicates the fragment
// is the first fragment.
//
if ((FragmentOffset & IP6_FRAGMENT_OFFSET_MASK) == 0) {
FragmentHead.NextHeader = Current;
} else {
FragmentHead.NextHeader = LastHeader;
}
FragmentHead.Reserved = 0;
FragmentHead.FragmentOffset = HTONS (FragmentOffset);
FragmentHead.Identification = mIp6Id;
CopyMem (Buffer + Part1Len, &FragmentHead, sizeof (IP6_FRAGMENT_HEADER));
if ((ExtHdrs != NULL) && (Part1Len < ExtHdrsLen)) {
//
// Append the part2 (fragmentable part) of Extension headers
//
CopyMem (
Buffer + Part1Len + sizeof (IP6_FRAGMENT_HEADER),
ExtHdrs + Part1Len,
ExtHdrsLen - Part1Len
);
}
*UpdatedExtHdrs = Buffer;
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,191 @@
/** @file
Definition of IP6 option process routines.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6_OPTION_H__
#define __EFI_IP6_OPTION_H__
#define IP6_FRAGMENT_OFFSET_MASK (~0x3)
typedef struct _IP6_FRAGMENT_HEADER {
UINT8 NextHeader;
UINT8 Reserved;
UINT16 FragmentOffset;
UINT32 Identification;
} IP6_FRAGMENT_HEADER;
typedef struct _IP6_ROUTING_HEADER {
UINT8 NextHeader;
UINT8 HeaderLen;
UINT8 RoutingType;
UINT8 SegmentsLeft;
} IP6_ROUTING_HEADER;
typedef enum {
Ip6OptionPad1 = 0,
Ip6OptionPadN = 1,
Ip6OptionRouterAlert = 5,
Ip6OptionSkip = 0,
Ip6OptionDiscard = 0x40,
Ip6OptionParameterProblem = 0x80,
Ip6OptionMask = 0xc0,
Ip6OptionEtherSource = 1,
Ip6OptionEtherTarget = 2,
Ip6OptionPrefixInfo = 3,
Ip6OptionRedirected = 4,
Ip6OptionMtu = 5
} IP6_OPTION_TYPE;
/**
Validate the IP6 extension header format for both the packets we received
and that we will transmit. It will compute the ICMPv6 error message fields
if the option is mal-formated.
@param[in] IpSb The IP6 service instance. This is an optional parameter.
@param[in] Packet The data of the packet. Ignored if NULL.
@param[in] NextHeader The next header field in IPv6 basic header.
@param[in] ExtHdrs The first byte of the option.
@param[in] ExtHdrsLen The length of the whole option.
@param[in] Rcvd The option is from the packet we received if TRUE,
otherwise, the option we want to transmit.
@param[out] FormerHeader The offset of NextHeader which points to Fragment
Header when we received, of the ExtHdrs.
Ignored if we transmit.
@param[out] LastHeader The pointer of NextHeader of the last extension
header processed by IP6.
@param[out] RealExtsLen The length of extension headers processed by IP6 layer.
This is an optional parameter that may be NULL.
@param[out] UnFragmentLen The length of unfragmented length of extension headers.
This is an optional parameter that may be NULL.
@param[out] Fragmented Indicate whether the packet is fragmented.
This is an optional parameter that may be NULL.
@retval TRUE The option is properly formated.
@retval FALSE The option is malformated.
**/
BOOLEAN
Ip6IsExtsValid (
IN IP6_SERVICE *IpSb OPTIONAL,
IN NET_BUF *Packet OPTIONAL,
IN UINT8 *NextHeader,
IN UINT8 *ExtHdrs,
IN UINT32 ExtHdrsLen,
IN BOOLEAN Rcvd,
OUT UINT32 *FormerHeader OPTIONAL,
OUT UINT8 **LastHeader,
OUT UINT32 *RealExtsLen OPTIONAL,
OUT UINT32 *UnFragmentLen OPTIONAL,
OUT BOOLEAN *Fragmented OPTIONAL
);
/**
Generate an IPv6 router alert option in network order and output it through Buffer.
@param[out] Buffer Points to a buffer to record the generated option.
@param[in, out] BufferLen The length of Buffer, in bytes.
@param[in] NextHeader The 8-bit selector indicates the type of header
immediately following the Hop-by-Hop Options header.
@retval EFI_BUFFER_TOO_SMALL The Buffer is too small to contain the generated
option. BufferLen is updated for the required size.
@retval EFI_SUCCESS The option is generated and filled in to Buffer.
**/
EFI_STATUS
Ip6FillHopByHop (
OUT UINT8 *Buffer,
IN OUT UINTN *BufferLen,
IN UINT8 NextHeader
);
/**
Insert a Fragment Header to the Extension headers and output it in UpdatedExtHdrs.
@param[in] IpSb The IP6 service instance to transmit the packet.
@param[in] NextHeader The extension header type of first extension header.
@param[in] LastHeader The extension header type of last extension header.
@param[in] ExtHdrs The length of the original extension header.
@param[in] ExtHdrsLen The length of the extension headers.
@param[in] FragmentOffset The fragment offset of the data following the header.
@param[out] UpdatedExtHdrs The updated ExtHdrs with Fragment header inserted.
It's caller's responsiblity to free this buffer.
@retval EFI_OUT_OF_RESOURCES Failed to finish the operation due to lake of
resource.
@retval EFI_UNSUPPORTED The extension header specified in ExtHdrs is not
supported currently.
@retval EFI_SUCCESS The operation performed successfully.
**/
EFI_STATUS
Ip6FillFragmentHeader (
IN IP6_SERVICE *IpSb,
IN UINT8 NextHeader,
IN UINT8 LastHeader,
IN UINT8 *ExtHdrs,
IN UINT32 ExtHdrsLen,
IN UINT16 FragmentOffset,
OUT UINT8 **UpdatedExtHdrs
);
/**
Copy the extension headers from the original to buffer. A Fragment header is
appended to the end.
@param[in] NextHeader The 8-bit selector indicates the type of
the fragment header's next header.
@param[in] ExtHdrs The length of the original extension header.
@param[in] LastHeader The pointer of next header of last extension header.
@param[in] FragmentOffset The fragment offset of the data following the header.
@param[in] UnFragmentHdrLen The length of unfragmented length of extension headers.
@param[in, out] Buf The buffer to copy options to.
@param[in, out] BufLen The length of the buffer.
@retval EFI_SUCCESS The options are copied over.
@retval EFI_BUFFER_TOO_SMALL The buffer caller provided is too small.
**/
EFI_STATUS
Ip6CopyExts (
IN UINT8 NextHeader,
IN UINT8 *ExtHdrs,
IN UINT8 *LastHeader,
IN UINT16 FragmentOffset,
IN UINT32 UnFragmentHdrLen,
IN OUT UINT8 *Buf,
IN OUT UINT32 *BufLen
);
/**
Validate the IP6 option format for both the packets we received
and that we will transmit. It supports the defined options in Neighbor
Discovery messages.
@param[in] Option The first byte of the option.
@param[in] OptionLen The length of the whole option.
@retval TRUE The option is properly formatted.
@retval FALSE The option is malformated.
**/
BOOLEAN
Ip6IsNDOptionValid (
IN UINT8 *Option,
IN UINT16 OptionLen
);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,141 @@
/** @file
The internal functions and routines to transmit the IP6 packet.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6_OUTPUT_H__
#define __EFI_IP6_OUTPUT_H__
extern UINT32 mIp6Id;
/**
Output all the available source addresses to the list entry head SourceList. The
number of source addresses are also returned.
@param[in] IpSb Points to a IP6 service binding instance.
@param[in] Destination The IPv6 destination address.
@param[out] Source The selected IPv6 source address according to
the Destination.
@retval EFI_SUCCESS The source addresses were copied to the list entry
head SourceList.
@retval EFI_NO_MAPPING The IPv6 stack is not auto configured.
**/
EFI_STATUS
Ip6SelectSourceAddress (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Destination,
OUT EFI_IPv6_ADDRESS *Source
);
/**
The default callback function for system generated packet.
It will free the packet.
@param[in] Packet The packet that transmitted.
@param[in] IoStatus The result of the transmission: succeeded or failed.
@param[in] LinkFlag Not used when transmission. Check IP6_FRAME_CALLBACK
for reference.
@param[in] Context The context provided by us.
**/
VOID
Ip6SysPacketSent (
NET_BUF *Packet,
EFI_STATUS IoStatus,
UINT32 LinkFlag,
VOID *Context
);
/**
Transmit an IP6 packet. The packet comes either from the IP6
child's consumer (IpInstance != NULL) or the IP6 driver itself
(IpInstance == NULL). It will route the packet, fragment it,
then transmit all the fragments through an interface.
@param[in] IpSb The IP6 service instance to transmit the packet.
@param[in] Interface The IP6 interface to transmit the packet. Ignored
if NULL.
@param[in] IpInstance The IP6 child that issues the transmission. It is
NULL if the packet is from the system.
@param[in] Packet The user data to send, excluding the IP header.
@param[in] Head The caller supplied header. The caller should set
the following header fields: NextHeader, HopLimit,
Src, Dest, FlowLabel, PayloadLength. This function
will fill in the Ver, TrafficClass.
@param[in] ExtHdrs The extension headers to append to the IPv6 basic
header.
@param[in] ExtHdrsLen The length of the extension headers.
@param[in] Callback The callback function to issue when transmission
completed.
@param[in] Context The opaque context for the callback.
@retval EFI_INVALID_PARAMETER Any input parameter or the packet is invalid.
@retval EFI_NO_MAPPING There is no interface to the destination.
@retval EFI_NOT_FOUND There is no route to the destination.
@retval EFI_SUCCESS The packet successfully transmitted.
@retval EFI_OUT_OF_RESOURCES Failed to finish the operation due to lack of
resources.
@retval Others Failed to transmit the packet.
**/
EFI_STATUS
Ip6Output (
IN IP6_SERVICE *IpSb,
IN IP6_INTERFACE *Interface OPTIONAL,
IN IP6_PROTOCOL *IpInstance OPTIONAL,
IN NET_BUF *Packet,
IN EFI_IP6_HEADER *Head,
IN UINT8 *ExtHdrs,
IN UINT32 ExtHdrsLen,
IN IP6_FRAME_CALLBACK Callback,
IN VOID *Context
);
/**
Remove all the frames on the interface that pass the FrameToCancel,
either queued on ARP queues, or that have already been delivered to
MNP and not yet recycled.
@param[in] Interface Interface to remove the frames from.
@param[in] IoStatus The transmit status returned to the frames' callback.
@param[in] FrameToCancel Function to select the frame to cancel; NULL to select all.
@param[in] Context Opaque parameters passed to FrameToCancel. Ignored if
FrameToCancel is NULL.
**/
VOID
Ip6CancelFrames (
IN IP6_INTERFACE *Interface,
IN EFI_STATUS IoStatus,
IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
IN VOID *Context OPTIONAL
);
/**
Cancel the Packet and all its fragments.
@param[in] IpIf The interface from which the Packet is sent.
@param[in] Packet The Packet to cancel.
@param[in] IoStatus The status returns to the sender.
**/
VOID
Ip6CancelPacket (
IN IP6_INTERFACE *IpIf,
IN NET_BUF *Packet,
IN EFI_STATUS IoStatus
);
#endif

View File

@@ -0,0 +1,635 @@
/** @file
The functions and routines to handle the route caches and route table.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ip6Impl.h"
/**
This is the worker function for IP6_ROUTE_CACHE_HASH(). It calculates the value
as the index of the route cache bucket according to the prefix of two IPv6 addresses.
@param[in] Ip1 The IPv6 address.
@param[in] Ip2 The IPv6 address.
@return The hash value of the prefix of two IPv6 addresses.
**/
UINT32
Ip6RouteCacheHash (
IN EFI_IPv6_ADDRESS *Ip1,
IN EFI_IPv6_ADDRESS *Ip2
)
{
UINT32 Prefix1;
UINT32 Prefix2;
Prefix1 = *((UINT32 *) ((UINTN *) (Ip1)));
Prefix2 = *((UINT32 *) ((UINTN *) (Ip2)));
return ((UINT32) (Prefix1 ^ Prefix2) % IP6_ROUTE_CACHE_HASH_SIZE);
}
/**
Allocate a route entry then initialize it with the Destination/PrefixLength
and Gateway.
@param[in] Destination The IPv6 destination address. This is an optional
parameter that may be NULL.
@param[in] PrefixLength The destination network's prefix length.
@param[in] GatewayAddress The next hop address. This is an optional parameter
that may be NULL.
@return NULL if failed to allocate memeory; otherwise, the newly created route entry.
**/
IP6_ROUTE_ENTRY *
Ip6CreateRouteEntry (
IN EFI_IPv6_ADDRESS *Destination OPTIONAL,
IN UINT8 PrefixLength,
IN EFI_IPv6_ADDRESS *GatewayAddress OPTIONAL
)
{
IP6_ROUTE_ENTRY *RtEntry;
RtEntry = AllocateZeroPool (sizeof (IP6_ROUTE_ENTRY));
if (RtEntry == NULL) {
return NULL;
}
RtEntry->RefCnt = 1;
RtEntry->Flag = 0;
RtEntry->PrefixLength = PrefixLength;
if (Destination != NULL) {
IP6_COPY_ADDRESS (&RtEntry->Destination, Destination);
}
if (GatewayAddress != NULL) {
IP6_COPY_ADDRESS (&RtEntry->NextHop, GatewayAddress);
}
return RtEntry;
}
/**
Free the route table entry. It is reference counted.
@param[in, out] RtEntry The route entry to free.
**/
VOID
Ip6FreeRouteEntry (
IN OUT IP6_ROUTE_ENTRY *RtEntry
)
{
ASSERT ((RtEntry != NULL) && (RtEntry->RefCnt > 0));
if (--RtEntry->RefCnt == 0) {
FreePool (RtEntry);
}
}
/**
Search the route table for a most specific match to the Dst. It searches
from the longest route area (prefix length == 128) to the shortest route area
(default routes). In each route area, it will first search the instance's
route table, then the default route table. This is required per the following
requirements:
1. IP search the route table for a most specific match.
2. The local route entries have precedence over the default route entry.
@param[in] RtTable The route table to search from.
@param[in] Destination The destionation address to search. If NULL, search
the route table by NextHop.
@param[in] NextHop The next hop address. If NULL, search the route table
by Destination.
@return NULL if no route matches the Dst. Otherwise, the point to the
@return most specific route to the Dst.
**/
IP6_ROUTE_ENTRY *
Ip6FindRouteEntry (
IN IP6_ROUTE_TABLE *RtTable,
IN EFI_IPv6_ADDRESS *Destination OPTIONAL,
IN EFI_IPv6_ADDRESS *NextHop OPTIONAL
)
{
LIST_ENTRY *Entry;
IP6_ROUTE_ENTRY *RtEntry;
INTN Index;
ASSERT (Destination != NULL || NextHop != NULL);
RtEntry = NULL;
for (Index = IP6_PREFIX_NUM - 1; Index >= 0; Index--) {
NET_LIST_FOR_EACH (Entry, &RtTable->RouteArea[Index]) {
RtEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_ENTRY, Link);
if (Destination != NULL) {
if (NetIp6IsNetEqual (Destination, &RtEntry->Destination, RtEntry->PrefixLength)) {
NET_GET_REF (RtEntry);
return RtEntry;
}
} else if (NextHop != NULL) {
if (NetIp6IsNetEqual (NextHop, &RtEntry->NextHop, RtEntry->PrefixLength)) {
NET_GET_REF (RtEntry);
return RtEntry;
}
}
}
}
return NULL;
}
/**
Allocate and initialize a IP6 route cache entry.
@param[in] Dst The destination address.
@param[in] Src The source address.
@param[in] GateWay The next hop address.
@param[in] Tag The tag from the caller. This marks all the cache entries
spawned from one route table entry.
@return NULL if failed to allocate memory for the cache. Otherwise, point
to the created route cache entry.
**/
IP6_ROUTE_CACHE_ENTRY *
Ip6CreateRouteCacheEntry (
IN EFI_IPv6_ADDRESS *Dst,
IN EFI_IPv6_ADDRESS *Src,
IN EFI_IPv6_ADDRESS *GateWay,
IN UINTN Tag
)
{
IP6_ROUTE_CACHE_ENTRY *RtCacheEntry;
RtCacheEntry = AllocatePool (sizeof (IP6_ROUTE_CACHE_ENTRY));
if (RtCacheEntry == NULL) {
return NULL;
}
RtCacheEntry->RefCnt = 1;
RtCacheEntry->Tag = Tag;
IP6_COPY_ADDRESS (&RtCacheEntry->Destination, Dst);
IP6_COPY_ADDRESS (&RtCacheEntry->Source, Src);
IP6_COPY_ADDRESS (&RtCacheEntry->NextHop, GateWay);
return RtCacheEntry;
}
/**
Free the route cache entry. It is reference counted.
@param[in, out] RtCacheEntry The route cache entry to free.
**/
VOID
Ip6FreeRouteCacheEntry (
IN OUT IP6_ROUTE_CACHE_ENTRY *RtCacheEntry
)
{
ASSERT (RtCacheEntry->RefCnt > 0);
if (--RtCacheEntry->RefCnt == 0) {
FreePool (RtCacheEntry);
}
}
/**
Find a route cache with the destination and source address. This is
used by the ICMPv6 redirect messasge process.
@param[in] RtTable The route table to search the cache for.
@param[in] Dest The destination address.
@param[in] Src The source address.
@return NULL if no route entry to the (Dest, Src). Otherwise, the pointer
to the correct route cache entry.
**/
IP6_ROUTE_CACHE_ENTRY *
Ip6FindRouteCache (
IN IP6_ROUTE_TABLE *RtTable,
IN EFI_IPv6_ADDRESS *Dest,
IN EFI_IPv6_ADDRESS *Src
)
{
LIST_ENTRY *Entry;
IP6_ROUTE_CACHE_ENTRY *RtCacheEntry;
UINT32 Index;
Index = IP6_ROUTE_CACHE_HASH (Dest, Src);
NET_LIST_FOR_EACH (Entry, &RtTable->Cache.CacheBucket[Index]) {
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_CACHE_ENTRY, Link);
if (EFI_IP6_EQUAL (Dest, &RtCacheEntry->Destination)&& EFI_IP6_EQUAL (Src, &RtCacheEntry->Source)) {
NET_GET_REF (RtCacheEntry);
return RtCacheEntry;
}
}
return NULL;
}
/**
Build an array of EFI_IP6_ROUTE_TABLE to be returned to the caller. The number
of EFI_IP6_ROUTE_TABLE is also returned.
@param[in] RouteTable The pointer of IP6_ROUTE_TABLE internal used.
@param[out] EfiRouteCount The number of returned route entries.
@param[out] EfiRouteTable The pointer to the array of EFI_IP6_ROUTE_TABLE.
If NULL, only the route entry count is returned.
@retval EFI_SUCCESS The EFI_IP6_ROUTE_TABLE successfully built.
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the route table.
**/
EFI_STATUS
Ip6BuildEfiRouteTable (
IN IP6_ROUTE_TABLE *RouteTable,
OUT UINT32 *EfiRouteCount,
OUT EFI_IP6_ROUTE_TABLE **EfiRouteTable OPTIONAL
)
{
LIST_ENTRY *Entry;
IP6_ROUTE_ENTRY *RtEntry;
EFI_IP6_ROUTE_TABLE *EfiTable;
UINT32 Count;
INT32 Index;
ASSERT (EfiRouteCount != NULL);
Count = RouteTable->TotalNum;
*EfiRouteCount = Count;
if ((EfiRouteTable == NULL) || (Count == 0)) {
return EFI_SUCCESS;
}
if (*EfiRouteTable == NULL) {
*EfiRouteTable = AllocatePool (sizeof (EFI_IP6_ROUTE_TABLE) * Count);
if (*EfiRouteTable == NULL) {
return EFI_OUT_OF_RESOURCES;
}
}
EfiTable = *EfiRouteTable;
//
// Copy the route entry to EFI route table.
//
Count = 0;
for (Index = IP6_PREFIX_NUM - 1; Index >= 0; Index--) {
NET_LIST_FOR_EACH (Entry, &(RouteTable->RouteArea[Index])) {
RtEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_ENTRY, Link);
Ip6CopyAddressByPrefix (
&EfiTable[Count].Destination,
&RtEntry->Destination,
RtEntry->PrefixLength
);
IP6_COPY_ADDRESS (&EfiTable[Count].Gateway, &RtEntry->NextHop);
EfiTable[Count].PrefixLength = RtEntry->PrefixLength;
Count++;
}
}
ASSERT (Count == RouteTable->TotalNum);
return EFI_SUCCESS;
}
/**
Create an empty route table. This includes its internal route cache.
@return NULL if failed to allocate memory for the route table. Otherwise,
the point to newly created route table.
**/
IP6_ROUTE_TABLE *
Ip6CreateRouteTable (
VOID
)
{
IP6_ROUTE_TABLE *RtTable;
UINT32 Index;
RtTable = AllocatePool (sizeof (IP6_ROUTE_TABLE));
if (RtTable == NULL) {
return NULL;
}
RtTable->RefCnt = 1;
RtTable->TotalNum = 0;
for (Index = 0; Index < IP6_PREFIX_NUM; Index++) {
InitializeListHead (&RtTable->RouteArea[Index]);
}
for (Index = 0; Index < IP6_ROUTE_CACHE_HASH_SIZE; Index++) {
InitializeListHead (&RtTable->Cache.CacheBucket[Index]);
RtTable->Cache.CacheNum[Index] = 0;
}
return RtTable;
}
/**
Free the route table and its associated route cache. Route
table is reference counted.
@param[in, out] RtTable The route table to free.
**/
VOID
Ip6CleanRouteTable (
IN OUT IP6_ROUTE_TABLE *RtTable
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *Next;
IP6_ROUTE_ENTRY *RtEntry;
IP6_ROUTE_CACHE_ENTRY *RtCacheEntry;
UINT32 Index;
ASSERT (RtTable->RefCnt > 0);
if (--RtTable->RefCnt > 0) {
return ;
}
//
// Free all the route table entry and its route cache.
//
for (Index = 0; Index < IP6_PREFIX_NUM; Index++) {
NET_LIST_FOR_EACH_SAFE (Entry, Next, &RtTable->RouteArea[Index]) {
RtEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_ENTRY, Link);
RemoveEntryList (Entry);
Ip6FreeRouteEntry (RtEntry);
}
}
for (Index = 0; Index < IP6_ROUTE_CACHE_HASH_SIZE; Index++) {
NET_LIST_FOR_EACH_SAFE (Entry, Next, &RtTable->Cache.CacheBucket[Index]) {
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_CACHE_ENTRY, Link);
RemoveEntryList (Entry);
Ip6FreeRouteCacheEntry (RtCacheEntry);
}
}
FreePool (RtTable);
}
/**
Remove all the cache entries bearing the Tag. When a route cache
entry is created, it is tagged with the address of route entry
from which it is spawned. When a route entry is deleted, the cache
entries spawned from it are also deleted.
@param[in] RtCache Route cache to remove the entries from.
@param[in] Tag The Tag of the entries to remove.
**/
VOID
Ip6PurgeRouteCache (
IN IP6_ROUTE_CACHE *RtCache,
IN UINTN Tag
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *Next;
IP6_ROUTE_CACHE_ENTRY *RtCacheEntry;
UINT32 Index;
for (Index = 0; Index < IP6_ROUTE_CACHE_HASH_SIZE; Index++) {
NET_LIST_FOR_EACH_SAFE (Entry, Next, &RtCache->CacheBucket[Index]) {
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_CACHE_ENTRY, Link);
if (RtCacheEntry->Tag == Tag) {
RemoveEntryList (Entry);
Ip6FreeRouteCacheEntry (RtCacheEntry);
}
}
}
}
/**
Add a route entry to the route table. It is the help function for EfiIp6Routes.
@param[in, out] RtTable Route table to add route to.
@param[in] Destination The destination of the network.
@param[in] PrefixLength The PrefixLength of the destination.
@param[in] GatewayAddress The next hop address.
@retval EFI_ACCESS_DENIED The same route already exists.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the entry.
@retval EFI_SUCCESS The route was added successfully.
**/
EFI_STATUS
Ip6AddRoute (
IN OUT IP6_ROUTE_TABLE *RtTable,
IN EFI_IPv6_ADDRESS *Destination,
IN UINT8 PrefixLength,
IN EFI_IPv6_ADDRESS *GatewayAddress
)
{
LIST_ENTRY *ListHead;
LIST_ENTRY *Entry;
IP6_ROUTE_ENTRY *Route;
ListHead = &RtTable->RouteArea[PrefixLength];
//
// First check whether the route exists
//
NET_LIST_FOR_EACH (Entry, ListHead) {
Route = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_ENTRY, Link);
if (NetIp6IsNetEqual (Destination, &Route->Destination, PrefixLength) &&
EFI_IP6_EQUAL (GatewayAddress, &Route->NextHop)) {
return EFI_ACCESS_DENIED;
}
}
//
// Create a route entry and insert it to the route area.
//
Route = Ip6CreateRouteEntry (Destination, PrefixLength, GatewayAddress);
if (Route == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (NetIp6IsUnspecifiedAddr (GatewayAddress)) {
Route->Flag = IP6_DIRECT_ROUTE;
}
InsertHeadList (ListHead, &Route->Link);
RtTable->TotalNum++;
return EFI_SUCCESS;
}
/**
Remove a route entry and all the route caches spawn from it.
It is the help function for EfiIp6Routes.
@param[in, out] RtTable The route table to remove the route from.
@param[in] Destination The destination network.
@param[in] PrefixLength The PrefixLength of the Destination.
@param[in] GatewayAddress The next hop address.
@retval EFI_SUCCESS The route entry was successfully removed.
@retval EFI_NOT_FOUND There is no route entry in the table with that
property.
**/
EFI_STATUS
Ip6DelRoute (
IN OUT IP6_ROUTE_TABLE *RtTable,
IN EFI_IPv6_ADDRESS *Destination,
IN UINT8 PrefixLength,
IN EFI_IPv6_ADDRESS *GatewayAddress
)
{
LIST_ENTRY *ListHead;
LIST_ENTRY *Entry;
LIST_ENTRY *Next;
IP6_ROUTE_ENTRY *Route;
UINT32 TotalNum;
ListHead = &RtTable->RouteArea[PrefixLength];
TotalNum = RtTable->TotalNum;
NET_LIST_FOR_EACH_SAFE (Entry, Next, ListHead) {
Route = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_ENTRY, Link);
if (Destination != NULL && !NetIp6IsNetEqual (Destination, &Route->Destination, PrefixLength)) {
continue;
}
if (GatewayAddress != NULL && !EFI_IP6_EQUAL (GatewayAddress, &Route->NextHop)) {
continue;
}
Ip6PurgeRouteCache (&RtTable->Cache, (UINTN) Route);
RemoveEntryList (Entry);
Ip6FreeRouteEntry (Route);
ASSERT (RtTable->TotalNum > 0);
RtTable->TotalNum--;
}
return TotalNum == RtTable->TotalNum ? EFI_NOT_FOUND : EFI_SUCCESS;
}
/**
Search the route table to route the packet. Return/create a route
cache if there is a route to the destination.
@param[in] IpSb The IP6 service data.
@param[in] Dest The destination address to search for.
@param[in] Src The source address to search for.
@return NULL if it failed to route the packet. Otherwise, a route cache
entry that can be used to route packets.
**/
IP6_ROUTE_CACHE_ENTRY *
Ip6Route (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Dest,
IN EFI_IPv6_ADDRESS *Src
)
{
IP6_ROUTE_TABLE *RtTable;
LIST_ENTRY *ListHead;
IP6_ROUTE_CACHE_ENTRY *RtCacheEntry;
IP6_ROUTE_ENTRY *RtEntry;
EFI_IPv6_ADDRESS NextHop;
UINT32 Index;
RtTable = IpSb->RouteTable;
ASSERT (RtTable != NULL);
//
// Search the destination cache in IP6_ROUTE_TABLE.
//
Index = IP6_ROUTE_CACHE_HASH (Dest, Src);
ListHead = &RtTable->Cache.CacheBucket[Index];
RtCacheEntry = Ip6FindRouteCache (RtTable, Dest, Src);
//
// If found, promote the cache entry to the head of the hash bucket.
//
if (RtCacheEntry != NULL) {
RemoveEntryList (&RtCacheEntry->Link);
InsertHeadList (ListHead, &RtCacheEntry->Link);
return RtCacheEntry;
}
//
// Search the route table for the most specific route
//
RtEntry = Ip6FindRouteEntry (RtTable, Dest, NULL);
if (RtEntry == NULL) {
return NULL;
}
//
// Found a route to the Dest, if it is a direct route, the packet
// will be send directly to the destination, such as for connected
// network. Otherwise, it is an indirect route, the packet will be
// send the next hop router.
//
if ((RtEntry->Flag & IP6_DIRECT_ROUTE) == IP6_DIRECT_ROUTE) {
IP6_COPY_ADDRESS (&NextHop, Dest);
} else {
IP6_COPY_ADDRESS (&NextHop, &RtEntry->NextHop);
}
Ip6FreeRouteEntry (RtEntry);
//
// Create a route cache entry, and tag it as spawned from this route entry
//
RtCacheEntry = Ip6CreateRouteCacheEntry (Dest, Src, &NextHop, (UINTN) RtEntry);
if (RtCacheEntry == NULL) {
return NULL;
}
InsertHeadList (ListHead, &RtCacheEntry->Link);
NET_GET_REF (RtCacheEntry);
RtTable->Cache.CacheNum[Index]++;
return RtCacheEntry;
}

View File

@@ -0,0 +1,299 @@
/** @file
EFI IP6 route table and route cache table defintions.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6_ROUTE_H__
#define __EFI_IP6_ROUTE_H__
#define IP6_DIRECT_ROUTE 0x00000001
#define IP6_PACKET_TOO_BIG 0x00000010
#define IP6_ROUTE_CACHE_HASH_SIZE 31
///
/// Max NO. of cache entry per hash bucket
///
#define IP6_ROUTE_CACHE_MAX 32
#define IP6_ROUTE_CACHE_HASH(Ip1, Ip2) Ip6RouteCacheHash ((Ip1), (Ip2))
typedef struct {
LIST_ENTRY Link;
INTN RefCnt;
UINT32 Flag;
UINT8 PrefixLength;
EFI_IPv6_ADDRESS Destination;
EFI_IPv6_ADDRESS NextHop;
} IP6_ROUTE_ENTRY;
typedef struct {
LIST_ENTRY Link;
INTN RefCnt;
UINTN Tag;
EFI_IPv6_ADDRESS Destination;
EFI_IPv6_ADDRESS Source;
EFI_IPv6_ADDRESS NextHop;
} IP6_ROUTE_CACHE_ENTRY;
typedef struct {
LIST_ENTRY CacheBucket[IP6_ROUTE_CACHE_HASH_SIZE];
UINT8 CacheNum[IP6_ROUTE_CACHE_HASH_SIZE];
} IP6_ROUTE_CACHE;
//
// Each IP6 instance has its own route table. Each ServiceBinding
// instance has a default route table and default address.
//
// All the route table entries with the same prefix length are linked
// together in one route area. For example, RouteArea[0] contains
// the default routes. A route table also contains a route cache.
//
typedef struct _IP6_ROUTE_TABLE {
INTN RefCnt;
UINT32 TotalNum;
LIST_ENTRY RouteArea[IP6_PREFIX_NUM];
IP6_ROUTE_CACHE Cache;
} IP6_ROUTE_TABLE;
/**
This is the worker function for IP6_ROUTE_CACHE_HASH(). It calculates the value
as the index of the route cache bucket according to the prefix of two IPv6 addresses.
@param[in] Ip1 The IPv6 address.
@param[in] Ip2 The IPv6 address.
@return The hash value of the prefix of two IPv6 addresses.
**/
UINT32
Ip6RouteCacheHash (
IN EFI_IPv6_ADDRESS *Ip1,
IN EFI_IPv6_ADDRESS *Ip2
);
/**
Allocate and initialize an IP6 route cache entry.
@param[in] Dst The destination address.
@param[in] Src The source address.
@param[in] GateWay The next hop address.
@param[in] Tag The tag from the caller. This marks all the cache entries
spawned from one route table entry.
@return NULL if it failed to allocate memory for the cache. Otherwise, point
to the created route cache entry.
**/
IP6_ROUTE_CACHE_ENTRY *
Ip6CreateRouteCacheEntry (
IN EFI_IPv6_ADDRESS *Dst,
IN EFI_IPv6_ADDRESS *Src,
IN EFI_IPv6_ADDRESS *GateWay,
IN UINTN Tag
);
/**
Free the route cache entry. It is reference counted.
@param[in, out] RtCacheEntry The route cache entry to free.
**/
VOID
Ip6FreeRouteCacheEntry (
IN OUT IP6_ROUTE_CACHE_ENTRY *RtCacheEntry
);
/**
Find a route cache with the destination and source address. This is
used by the ICMPv6 redirect messasge process.
@param[in] RtTable The route table to search the cache for.
@param[in] Dest The destination address.
@param[in] Src The source address.
@return NULL if no route entry to the (Dest, Src). Otherwise, point
to the correct route cache entry.
**/
IP6_ROUTE_CACHE_ENTRY *
Ip6FindRouteCache (
IN IP6_ROUTE_TABLE *RtTable,
IN EFI_IPv6_ADDRESS *Dest,
IN EFI_IPv6_ADDRESS *Src
);
/**
Build a array of EFI_IP6_ROUTE_TABLE to be returned to the caller. The number
of EFI_IP6_ROUTE_TABLE is also returned.
@param[in] RouteTable The pointer of IP6_ROUTE_TABLE internal used.
@param[out] EfiRouteCount The number of returned route entries.
@param[out] EfiRouteTable The pointer to the array of EFI_IP6_ROUTE_TABLE.
If NULL, only the route entry count is returned.
@retval EFI_SUCCESS The EFI_IP6_ROUTE_TABLE successfully built.
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the route table.
**/
EFI_STATUS
Ip6BuildEfiRouteTable (
IN IP6_ROUTE_TABLE *RouteTable,
OUT UINT32 *EfiRouteCount,
OUT EFI_IP6_ROUTE_TABLE **EfiRouteTable OPTIONAL
);
/**
Create an empty route table, includes its internal route cache.
@return NULL if failed to allocate memory for the route table. Otherwise,
the point to newly created route table.
**/
IP6_ROUTE_TABLE *
Ip6CreateRouteTable (
VOID
);
/**
Free the route table and its associated route cache. Route
table is reference counted.
@param[in, out] RtTable The route table to free.
**/
VOID
Ip6CleanRouteTable (
IN OUT IP6_ROUTE_TABLE *RtTable
);
/**
Allocate a route entry then initialize it with the Destination/PrefixLength
and Gateway.
@param[in] Destination The IPv6 destination address. This is an optional
parameter that may be NULL.
@param[in] PrefixLength The destination network's prefix length.
@param[in] GatewayAddress The next hop address. This is optional parameter
that may be NULL.
@return NULL if it failed to allocate memeory. Otherwise, the newly created route entry.
**/
IP6_ROUTE_ENTRY *
Ip6CreateRouteEntry (
IN EFI_IPv6_ADDRESS *Destination OPTIONAL,
IN UINT8 PrefixLength,
IN EFI_IPv6_ADDRESS *GatewayAddress OPTIONAL
);
/**
Search the route table for a most specific match to the Dst. It searches
from the longest route area (prefix length == 128) to the shortest route area
(default routes). In each route area, it will first search the instance's
route table, then the default route table. This is required per the following
requirements:
1. IP search the route table for a most specific match.
2. The local route entries have precedence over the default route entry.
@param[in] RtTable The route table to search from.
@param[in] Destination The destionation address to search. If NULL, search
the route table by NextHop.
@param[in] NextHop The next hop address. If NULL, search the route table
by Destination.
@return NULL if no route matches the Dst. Otherwise the point to the
most specific route to the Dst.
**/
IP6_ROUTE_ENTRY *
Ip6FindRouteEntry (
IN IP6_ROUTE_TABLE *RtTable,
IN EFI_IPv6_ADDRESS *Destination OPTIONAL,
IN EFI_IPv6_ADDRESS *NextHop OPTIONAL
);
/**
Free the route table entry. It is reference counted.
@param[in, out] RtEntry The route entry to free.
**/
VOID
Ip6FreeRouteEntry (
IN OUT IP6_ROUTE_ENTRY *RtEntry
);
/**
Add a route entry to the route table. It is the help function for EfiIp6Routes.
@param[in, out] RtTable Route table to add route to.
@param[in] Destination The destination of the network.
@param[in] PrefixLength The PrefixLength of the destination.
@param[in] GatewayAddress The next hop address.
@retval EFI_ACCESS_DENIED The same route already exists.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the entry.
@retval EFI_SUCCESS The route was added successfully.
**/
EFI_STATUS
Ip6AddRoute (
IN OUT IP6_ROUTE_TABLE *RtTable,
IN EFI_IPv6_ADDRESS *Destination,
IN UINT8 PrefixLength,
IN EFI_IPv6_ADDRESS *GatewayAddress
);
/**
Remove a route entry and all the route caches spawn from it.
It is the help function for EfiIp6Routes.
@param[in, out] RtTable The route table to remove the route from.
@param[in] Destination The destination network.
@param[in] PrefixLength The PrefixLength of the Destination.
@param[in] GatewayAddress The next hop address.
@retval EFI_SUCCESS Successfully removed the route entry.
@retval EFI_NOT_FOUND There is no route entry in the table with that
properity.
**/
EFI_STATUS
Ip6DelRoute (
IN OUT IP6_ROUTE_TABLE *RtTable,
IN EFI_IPv6_ADDRESS *Destination,
IN UINT8 PrefixLength,
IN EFI_IPv6_ADDRESS *GatewayAddress
);
/**
Search the route table to route the packet. Return/create a route
cache if there is a route to the destination.
@param[in] IpSb The IP6 service data.
@param[in] Dest The destination address to search for.
@param[in] Src The source address to search for.
@return NULL if failed to route packet. Otherwise, a route cache
entry that can be used to route packet.
**/
IP6_ROUTE_CACHE_ENTRY *
Ip6Route (
IN IP6_SERVICE *IpSb,
IN EFI_IPv6_ADDRESS *Dest,
IN EFI_IPv6_ADDRESS *Src
);
#endif

View File

@@ -0,0 +1,310 @@
/** @file
UEFI Component Name(2) protocol implementation for IPsec driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "IpSecImpl.h"
//
// EFI Component Name Functions
//
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
IpSecComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is being managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
IpSecComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle, OPTIONAL
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI Component Name Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIpSecComponentName = {
IpSecComponentNameGetDriverName,
IpSecComponentNameGetControllerName,
"eng"
};
//
// EFI Component Name 2 Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIpSecComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IpSecComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IpSecComponentNameGetControllerName,
"en"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIpSecDriverNameTable[] = {
{
"eng;en",
L"IpSec Driver"
},
{
NULL,
NULL
}
};
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This, and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
IpSecComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mIpSecDriverNameTable,
DriverName,
(BOOLEAN) (This == &gIpSecComponentName)
);
}
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is being managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
IpSecComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle, OPTIONAL
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
return EFI_UNSUPPORTED;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,952 @@
/** @file
Definitions related to IPSEC_CONFIG_PROTOCOL implementations.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _IPSEC_CONFIG_IMPL_H_
#define _IPSEC_CONFIG_IMPL_H_
#include <Protocol/IpSec.h>
#include <Protocol/IpSecConfig.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/PrintLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include "IpSecImpl.h"
#define EFI_IPSEC_ANY_PROTOCOL 0xFFFF
#define EFI_IPSEC_ANY_PORT 0
#define IPSEC_VAR_ITEM_HEADER_LOGO_BIT 0x80
#define IPSEC_VAR_ITEM_HEADER_CONTENT_BIT 0x7F
#define IPSECCONFIG_VARIABLE_NAME L"IpSecConfig"
#define IPSECCONFIG_STATUS_NAME L"IpSecStatus"
#define SIZE_OF_SPD_SELECTOR(x) (UINTN) (sizeof (EFI_IPSEC_SPD_SELECTOR) \
+ sizeof (EFI_IP_ADDRESS_INFO) * ((x)->LocalAddressCount + (x)->RemoteAddressCount))
#define FIX_REF_BUF_ADDR(addr, base) addr = (VOID *) ((UINTN) (addr) - (UINTN) (base))
#define UNFIX_REF_BUF_ADDR(addr, base) addr = (VOID *) ((UINTN) (addr) + (UINTN) (base))
//
// The data structure used to store the genernall information of IPsec configuration.
//
typedef struct {
UINT32 VariableCount; // the total number of the IPsecConfig variables.
UINT32 VariableSize; // The total size of all IpsecConfig variables.
UINT32 SingleVariableSize; // The max size of single variable
} IP_SEC_VARIABLE_INFO;
typedef struct {
EFI_IPSEC_CONFIG_SELECTOR *Selector;
VOID *Data;
LIST_ENTRY List;
} IPSEC_COMMON_POLICY_ENTRY;
typedef struct {
UINT8 *Ptr;
UINTN Size;
UINTN Capacity;
} IPSEC_VARIABLE_BUFFER;
#pragma pack(1)
typedef struct {
UINT8 Type;
UINT16 Size;
} IPSEC_VAR_ITEM_HEADER;
#pragma pack()
/**
The prototype of Copy Source Selector to the Destination Selector.
@param[in out] DstSel Pointer of Destination Selector. It would be
SPD Selector, or SAD Selector or PAD Selector.
@param[in] SrcSel Pointer of Source Selector. It would be
SPD Selector, or SAD Selector or PAD Selector.
@param[in out] Size The size of the Destination Selector. If it
is not NULL and its value is less than the size of
Source Selector, the value of Source Selector's
size will be passed to the caller by this parameter.
@retval EFI_INVALID_PARAMETER If the Destination or Source Selector is NULL.
@retval EFI_BUFFER_TOO_SMALL If the input Size is less than size of Source Selector.
@retval EFI_SUCCESS Copy Source Selector to the Destination
Selector successfully.
**/
typedef
EFI_STATUS
(*IPSEC_DUPLICATE_SELECTOR) (
IN OUT EFI_IPSEC_CONFIG_SELECTOR *DstSel,
IN EFI_IPSEC_CONFIG_SELECTOR *SrcSel,
IN OUT UINTN *Size
);
/**
It is prototype of compare two Selectors. The Selector would be SPD Selector,
or SAD Selector, or PAD selector.
@param[in] Selector1 Pointer of the first Selector.
@param[in] Selector2 Pointer of the second Selector.
@retval TRUE These two Selectors have the same value in certain fields.
@retval FALSE Not all fields have the same value in these two Selectors.
**/
typedef
BOOLEAN
(*IPSEC_COMPARE_SELECTOR) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector1,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector2
);
/**
The prototype of a function to check if the Selector is Zero by its certain fields.
@param[in] Selector Pointer of the Selector.
@retval TRUE If the Selector is Zero.
@retval FALSE If the Selector is not Zero.
**/
typedef
BOOLEAN
(*IPSEC_IS_ZERO_SELECTOR) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector
);
/**
The prototype of a function to fix the value of particular members of the Selector.
@param[in] Selector Pointer of Selector.
@param[in] Data Pointer of Data.
**/
typedef
VOID
(*IPSEC_FIX_POLICY_ENTRY) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data
);
/**
It is prototype function to define a routine function by the caller of IpSecVisitConfigData().
@param[in] Type A specified IPSEC_CONFIG_DATA_TYPE.
@param[in] Selector Points to EFI_IPSEC_CONFIG_SELECTOR to be copied
to the buffer.
@param[in] Data Points to data to be copied to the buffer. The
Data type is related to the Type.
@param[in] SelectorSize The size of the Selector.
@param[in] DataSize The size of the Data.
@param[in out] Buffer The buffer to store the Selector and Data.
@retval EFI_SUCCESS Copied the Selector and Data to a buffer successfully.
@retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated.
**/
typedef
EFI_STATUS
(*IPSEC_COPY_POLICY_ENTRY) (
IN EFI_IPSEC_CONFIG_DATA_TYPE Type,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN UINTN SelectorSize,
IN UINTN DataSize,
IN OUT VOID *Context
);
/**
Set the security policy information for the EFI IPsec driver.
The IPsec configuration data has a unique selector/identifier separately to
identify a data entry.
@param[in] Selector Pointer to an entry selector on operated
configuration data specified by DataType.
A NULL Selector causes the entire specified-type
configuration information to be flushed.
@param[in] Data The data buffer to be set.
@param[in] Context Pointer to one entry selector that describes
the expected position the new data entry will
be added. If Context is NULL, the new entry will
be appended to the end of the database.
@retval EFI_INVALID_PARAMETER Certain Parameters are not correct. The Parameter
requiring a check depends on the Selector type.
@retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
**/
typedef
EFI_STATUS
(*IPSEC_SET_POLICY_ENTRY) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN VOID *Context OPTIONAL
);
/**
A prototype function definition to lookup the data entry from IPsec. Return the configuration
value of the specified Entry.
@param[in] Selector Pointer to an entry selector that is an identifier
of the entry.
@param[in, out] DataSize On output, the size of data returned in Data.
@param[out] Data The buffer to return the contents of the IPsec
configuration data. The type of the data buffer
is associated with the DataType.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
@retval EFI_INVALID_PARAMETER Data is NULL and *DataSize is not zero.
@retval EFI_NOT_FOUND The configuration data specified by Selector is not found.
@retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been
updated with the size needed to complete the request.
**/
typedef
EFI_STATUS
(*IPSEC_GET_POLICY_ENTRY) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN OUT UINTN *DataSize,
IN VOID *Data
);
/**
Compare two SPD Selectors.
Compare two SPD Selector by the fields of LocalAddressCount/RemoteAddressCount/
NextLayerProtocol/LocalPort/LocalPortRange/RemotePort/RemotePortRange and the
Local Addresses and remote Addresses.
@param[in] Selector1 Pointer of the first SPD Selector.
@param[in] Selector2 Pointer of the second SPD Selector.
@retval TRUE These two Selectors have the same value in above fields.
@retval FALSE Not all of the above fields have the same value in these two Selectors.
**/
BOOLEAN
CompareSpdSelector (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector1,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector2
);
/**
Visit all IPsec Configurations of specified Type and call the caller defined
interface.
@param[in] DataType The specified IPsec Config Data Type.
@param[in] Routine The function caller defined.
@param[in] Context The data passed to the Routine.
@retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated.
@retval EFI_SUCCESS This function complete successfully.
**/
EFI_STATUS
IpSecVisitConfigData (
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN IPSEC_COPY_POLICY_ENTRY Routine,
IN VOID *Context
);
/**
This function is the subfunction of the EFIIpSecConfigSetData.
This function call IpSecSetVaraible to set the IPsec Configuration into the firmware.
@retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated.
@retval EFI_SUCCESS Saved the configration successfully.
@retval Others Other errors were found while obtaining the variable.
**/
EFI_STATUS
IpSecConfigSave (
VOID
);
/**
Initialize IPsecConfig protocol
@param[in, out] Private Pointer to IPSEC_PRIVATE_DATA. After this function finish,
the pointer of IPsecConfig Protocol implementation will copy
into its IPsecConfig member.
@retval EFI_SUCCESS Initialized the IPsecConfig Protocol successfully.
@retval Others Initializing the IPsecConfig Protocol failed.
**/
EFI_STATUS
IpSecConfigInitialize (
IN OUT IPSEC_PRIVATE_DATA *Private
);
/**
Calculate the entire size of EFI_IPSEC_SPD_DATA, which includes the buffer size pointed
by the pointer members.
@param[in] SpdData Pointer to a specified EFI_IPSEC_SPD_DATA.
@return The entire size of the specified EFI_IPSEC_SPD_DATA.
**/
UINTN
IpSecGetSizeOfEfiSpdData (
IN EFI_IPSEC_SPD_DATA *SpdData
);
/**
Calculate the a entire size of IPSEC_SPD_DATA, which includes the buffer size pointed
by the pointer members and the buffer size used by Sa List.
@param[in] SpdData Pointer to the specified IPSEC_SPD_DATA.
@return The entire size of IPSEC_SPD_DATA.
**/
UINTN
IpSecGetSizeOfSpdData (
IN IPSEC_SPD_DATA *SpdData
);
/**
Copy Source Process Policy to the Destination Process Policy.
@param[in] Dst Pointer to the Source Process Policy.
@param[in] Src Pointer to the Destination Process Policy.
**/
VOID
IpSecDuplicateProcessPolicy (
IN EFI_IPSEC_PROCESS_POLICY *Dst,
IN EFI_IPSEC_PROCESS_POLICY *Src
);
/**
Compare two SPD Selectors.
Compare two SPD Selector by the fields of LocalAddressCount/RemoteAddressCount/
NextLayerProtocol/LocalPort/LocalPortRange/RemotePort/RemotePortRange and the
Local Addresses and remote Addresses.
@param[in] Selector1 Pointer of the first SPD Selector.
@param[in] Selector2 Pointer of the second SPD Selector.
@retval TRUE This two Selector have the same value in above fields.
@retval FALSE Not all of the above fields have the same value in these two Selectors.
**/
BOOLEAN
CompareSpdSelector (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector1,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector2
);
/**
Compare two SA IDs.
@param[in] Selector1 Pointer of the first SA ID.
@param[in] Selector2 Pointer of the second SA ID.
@retval TRUE This two Selectors have the same SA ID.
@retval FALSE This two Selecotrs don't have the same SA ID.
**/
BOOLEAN
CompareSaId (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector1,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector2
);
/**
Compare two PAD IDs.
@param[in] Selector1 Pointer of the first PAD ID.
@param[in] Selector2 Pointer of the second PAD ID.
@retval TRUE This two Selectors have the same PAD ID.
@retval FALSE This two Selecotrs don't have the same PAD ID.
**/
BOOLEAN
ComparePadId (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector1,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector2
);
/**
Check if the SPD Selector is Zero by its LocalAddressCount and RemoteAddressCount
fields.
@param[in] Selector Pointer of the SPD Selector.
@retval TRUE If the SPD Selector is Zero.
@retval FALSE If the SPD Selector is not Zero.
**/
BOOLEAN
IsZeroSpdSelector (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector
);
/**
Check if the SA ID is Zero by its DestAddress.
@param[in] Selector Pointer of the SA ID.
@retval TRUE If the SA ID is Zero.
@retval FALSE If the SA ID is not Zero.
**/
BOOLEAN
IsZeroSaId (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector
);
/**
Check if the PAD ID is Zero.
@param[in] Selector Pointer of the PAD ID.
@retval TRUE If the PAD ID is Zero.
@retval FALSE If the PAD ID is not Zero.
**/
BOOLEAN
IsZeroPadId (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector
);
/**
Copy Source SPD Selector to the Destination SPD Selector.
@param[in, out] DstSel Pointer of Destination SPD Selector.
@param[in] SrcSel Pointer of Source SPD Selector.
@param[in, out] Size The size of the Destination SPD Selector. If
it is not NULL and its value is less than the
size of Source SPD Selector, the value of
Source SPD Selector's size will be passed to
the caller by this parameter.
@retval EFI_INVALID_PARAMETER If the Destination or Source SPD Selector is NULL.
@retval EFI_BUFFER_TOO_SMALL If the input Size is less than size of Source SPD Selector.
@retval EFI_SUCCESS Copy Source SPD Selector to the Destination SPD
Selector successfully.
**/
EFI_STATUS
DuplicateSpdSelector (
IN OUT EFI_IPSEC_CONFIG_SELECTOR *DstSel,
IN EFI_IPSEC_CONFIG_SELECTOR *SrcSel,
IN OUT UINTN *Size
);
/**
Copy Source SA ID to the Destination SA ID.
@param[in, out] DstSel Pointer of the Destination SA ID.
@param[in] SrcSel Pointer of the Source SA ID.
@param[in, out] Size The size of the Destination SA ID. If it
not NULL, and its value is less than the size of
Source SA ID, the value of Source SA ID's size
will be passed to the caller by this parameter.
@retval EFI_INVALID_PARAMETER If the Destination or Source SA ID is NULL.
@retval EFI_BUFFER_TOO_SMALL If the input Size less than size of source SA ID.
@retval EFI_SUCCESS Copied Source SA ID to the Destination SA ID successfully.
**/
EFI_STATUS
DuplicateSaId (
IN OUT EFI_IPSEC_CONFIG_SELECTOR *DstSel,
IN EFI_IPSEC_CONFIG_SELECTOR *SrcSel,
IN OUT UINTN *Size
);
/**
Copy Source PAD ID to the Destination PAD ID.
@param[in, out] DstSel Pointer of Destination PAD ID.
@param[in] SrcSel Pointer of Source PAD ID.
@param[in, out] Size The size of the Destination PAD ID. If it
not NULL, and its value less than the size of
Source PAD ID, the value of Source PAD ID's size
will be passed to the caller by this parameter.
@retval EFI_INVALID_PARAMETER If the Destination or Source PAD ID is NULL.
@retval EFI_BUFFER_TOO_SMALL If the input Size less than size of source PAD ID.
@retval EFI_SUCCESS Copied Source PAD ID to the Destination PAD ID successfully.
**/
EFI_STATUS
DuplicatePadId (
IN OUT EFI_IPSEC_CONFIG_SELECTOR *DstSel,
IN EFI_IPSEC_CONFIG_SELECTOR *SrcSel,
IN OUT UINTN *Size
);
/**
Fix the value of some members of the SPD Selector.
This function is called by IpSecCopyPolicyEntry(), which copies the Policy
Entry into the Variable. Since some members in SPD Selector are pointers,
a physical address to relative address conversion is required before copying
this SPD entry into the variable.
@param[in] Selector Pointer of SPD Selector.
@param[in, out] Data Pointer of SPD Data.
**/
VOID
FixSpdEntry (
IN EFI_IPSEC_SPD_SELECTOR *Selector,
IN OUT EFI_IPSEC_SPD_DATA *Data
);
/**
Fix the value of some members of SA ID.
This function is called by IpSecCopyPolicyEntry(), which copies the Policy
Entry into the Variable. Since some members in SA ID are pointers,
a physical address to relative address conversion is required before copying
this SAD into the variable.
@param[in] SaId Pointer of SA ID.
@param[in, out] Data Pointer of SA Data.
**/
VOID
FixSadEntry (
IN EFI_IPSEC_SA_ID *SaId,
IN OUT EFI_IPSEC_SA_DATA *Data
);
/**
Fix the value of some members of PAD ID.
This function is called by IpSecCopyPolicyEntry(), which copy the Policy
Entry into the Variable. Since some members in PAD ID are pointers,
a physical address to relative address conversion is required before copying
this PAD into the variable.
@param[in] PadId Pointer of PAD ID.
@param[in, out] Data Pointer of PAD Data.
**/
VOID
FixPadEntry (
IN EFI_IPSEC_PAD_ID *PadId,
IN OUT EFI_IPSEC_PAD_DATA *Data
);
/**
Recover the value of some members of SPD Selector.
This function is corresponding to FixSpdEntry(). It recovers the value of members
of SPD Selector which fix by the FixSpdEntry().
@param[in, out] Selector Pointer of SPD Selector.
@param[in, out] Data Pointer of SPD Data.
**/
VOID
UnfixSpdEntry (
IN OUT EFI_IPSEC_SPD_SELECTOR *Selector,
IN OUT EFI_IPSEC_SPD_DATA *Data
);
/**
Recover the value of some members of SA ID.
This function is corresponding to FixSadEntry(). It recovers the value of members
of SAD ID which fix by the FixSadEntry().
@param[in, out] SaId Pointer of SAD ID
@param[in, out] Data Pointer of SAD Data.
**/
VOID
UnfixSadEntry (
IN OUT EFI_IPSEC_SA_ID *SaId,
IN OUT EFI_IPSEC_SA_DATA *Data
);
/**
Recover the value of some members of PAD ID.
This function is corresponding to FixPadEntry(). It recovers the value of members
of PAD ID which fix by the FixPadEntry().
@param[in] PadId Pointer of PAD ID
@param[in, out] Data Pointer of PAD Data.
**/
VOID
UnfixPadEntry (
IN EFI_IPSEC_PAD_ID *PadId,
IN OUT EFI_IPSEC_PAD_DATA *Data
);
/**
Set the security policy information for the EFI IPsec driver.
The IPsec configuration data has a unique selector/identifier separately to
identify a data entry.
@param[in] Selector Pointer to an entry selector on operated
configuration data specified by DataType.
A NULL Selector causes the entire specified-type
configuration information to be flushed.
@param[in] Data The data buffer to be set. The structure
of the data buffer should be EFI_IPSEC_SPD_DATA.
@param[in] Context Pointer to one entry selector that describes
the expected position the new data entry will
be added. If Context is NULL,the new entry will
be appended the end of database.
@retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
- Selector is not NULL and its LocalAddress
is NULL or its RemoteAddress is NULL.
- Data is not NULL, its Action is Protected,
and its policy is NULL.
- Data is not NULL and its Action is not protected
and its policy is not NULL.
- The Action of Data is Protected, its policy
mode is Tunnel, and its tunnel option is NULL.
- The Action of Data is protected, its policy
mode is not Tunnel, and it tunnel option is not NULL.
@retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
**/
EFI_STATUS
SetSpdEntry (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN VOID *Context OPTIONAL
);
/**
Set the security association information for the EFI IPsec driver.
The IPsec configuration data has a unique selector/identifier separately to
identify a data entry.
@param[in] Selector Pointer to an entry selector on operated
configuration data specified by DataType.
A NULL Selector causes the entire specified-type
configuration information to be flushed.
@param[in] Data The data buffer to be set. The structure
of the data buffer should be EFI_IPSEC_SA_DATA.
@param[in] Context Pointer to one entry selector which describes
the expected position the new data entry will
be added. If Context is NULL,the new entry will
be appended to the end of database.
@retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
**/
EFI_STATUS
SetSadEntry (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN VOID *Context OPTIONAL
);
/**
Set the peer authorization configuration information for the EFI IPsec driver.
The IPsec configuration data has a unique selector/identifier separately to
identify a data entry.
@param[in] Selector Pointer to an entry selector on operated
configuration data specified by DataType.
A NULL Selector causes the entire specified-type
configuration information to be flushed.
@param[in] Data The data buffer to be set. The structure
of the data buffer should be EFI_IPSEC_PAD_DATA.
@param[in] Context Pointer to one entry selector that describes
the expected position where the new data entry will
be added. If Context is NULL, the new entry will
be appended the end of database.
@retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
**/
EFI_STATUS
SetPadEntry (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN VOID *Context OPTIONAL
);
/**
This function looks up the data entry from IPsec SPD, and returns the configuration
value of the specified SPD Entry.
@param[in] Selector Pointer to an entry selector which is an identifier
of the SPD entry.
@param[in, out] DataSize On output the size of data returned in Data.
@param[out] Data The buffer to return the contents of the IPsec
configuration data. The type of the data buffer
is associated with the DataType.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
@retval EFI_INVALID_PARAMETER Data is NULL and *DataSize is not zero.
@retval EFI_NOT_FOUND The configuration data specified by Selector is not found.
@retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been
updated with the size needed to complete the request.
**/
EFI_STATUS
GetSpdEntry (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN OUT UINTN *DataSize,
OUT VOID *Data
);
/**
This function looks up the data entry from IPsec SAD and returns the configuration
value of the specified SAD Entry.
@param[in] Selector Pointer to an entry selector that is an identifier
of the SAD entry.
@param[in, out] DataSize On output, the size of data returned in Data.
@param[out] Data The buffer to return the contents of the IPsec
configuration data. This type of the data buffer
is associated with the DataType.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
@retval EFI_NOT_FOUND The configuration data specified by Selector is not found.
@retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been
updated with the size needed to complete the request.
**/
EFI_STATUS
GetSadEntry (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN OUT UINTN *DataSize,
OUT VOID *Data
);
/**
This function looks up the data entry from IPsec PADand returns the configuration
value of the specified PAD Entry.
@param[in] Selector Pointer to an entry selector that is an identifier
of the PAD entry.
@param[in, out] DataSize On output the size of data returned in Data.
@param[out] Data The buffer to return the contents of the IPsec
configuration data. This type of the data buffer
is associated with the DataType.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
@retval EFI_NOT_FOUND The configuration data specified by Selector is not found.
@retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been
updated with the size needed to complete the request.
**/
EFI_STATUS
GetPadEntry (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN OUT UINTN *DataSize,
OUT VOID *Data
);
/**
Return the configuration value for the EFI IPsec driver.
This function lookup the data entry from IPsec database or IKEv2 configuration
information. The expected data type and unique identification are described in
DataType and Selector parameters.
@param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
@param[in] DataType The type of data to retrieve.
@param[in] Selector Pointer to an entry selector that is an identifier of the IPsec
configuration data entry.
@param[in, out] DataSize On output the size of data returned in Data.
@param[out] Data The buffer to return the contents of the IPsec configuration data.
The type of the data buffer is associated with the DataType.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
@retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
- This is NULL.
- Selector is NULL.
- DataSize is NULL.
- Data is NULL and *DataSize is not zero
@retval EFI_NOT_FOUND The configuration data specified by Selector is not found.
@retval EFI_UNSUPPORTED The specified DataType is not supported.
@retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been
updated with the size needed to complete the request.
**/
EFI_STATUS
EFIAPI
EfiIpSecConfigGetData (
IN EFI_IPSEC_CONFIG_PROTOCOL *This,
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN OUT UINTN *DataSize,
OUT VOID *Data
);
/**
Set the security association, security policy and peer authorization configuration
information for the EFI IPsec driver.
This function is used to set the IPsec configuration information of type DataType for
the EFI IPsec driver.
The IPsec configuration data has a unique selector/identifier separately to identify
a data entry. The selector structure depends on DataType's definition.
Using SetData() with a Data of NULL causes the IPsec configuration data entry identified
by DataType and Selector to be deleted.
@param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
@param[in] DataType The type of data to be set.
@param[in] Selector Pointer to an entry selector on operated configuration data
specified by DataType. A NULL Selector causes the entire
specified-type configuration information to be flushed.
@param[in] Data The data buffer to be set. The structure of the data buffer is
associated with the DataType.
@param[in] InsertBefore Pointer to one entry selector which describes the expected
position the new data entry will be added. If InsertBefore is NULL,
the new entry will be appended the end of database.
@retval EFI_SUCCESS The specified configuration entry data was set successfully.
@retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
- This is NULL.
@retval EFI_UNSUPPORTED The specified DataType is not supported.
@retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated.
**/
EFI_STATUS
EFIAPI
EfiIpSecConfigSetData (
IN EFI_IPSEC_CONFIG_PROTOCOL *This,
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN EFI_IPSEC_CONFIG_SELECTOR *InsertBefore OPTIONAL
);
/**
Enumerates the current selector for IPsec configuration data entry.
This function is called multiple times to retrieve the entry Selector in IPsec
configuration database. On each call to GetNextSelector(), the next entry
Selector are retrieved into the output interface.
If the entire IPsec configuration database has been iterated, the error
EFI_NOT_FOUND is returned.
If the Selector buffer is too small for the next Selector copy, an
EFI_BUFFER_TOO_SMALL error is returned, and SelectorSize is updated to reflect
the size of buffer needed.
On the initial call to GetNextSelector() to start the IPsec configuration database
search, a pointer to the buffer with all zero value is passed in Selector. Calls
to SetData() between calls to GetNextSelector may produce unpredictable results.
@param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
@param[in] DataType The type of IPsec configuration data to retrieve.
@param[in, out] SelectorSize The size of the Selector buffer.
@param[in, out] Selector On input, supplies the pointer to last Selector that was
returned by GetNextSelector().
On output, returns one copy of the current entry Selector
of a given DataType.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
@retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
- This is NULL.
- SelectorSize is NULL.
- Selector is NULL.
@retval EFI_NOT_FOUND The next configuration data entry was not found.
@retval EFI_UNSUPPORTED The specified DataType is not supported.
@retval EFI_BUFFER_TOO_SMALL The SelectorSize is too small for the result. This parameter
has been updated with the size needed to complete the search
request.
**/
EFI_STATUS
EFIAPI
EfiIpSecConfigGetNextSelector (
IN EFI_IPSEC_CONFIG_PROTOCOL *This,
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN OUT UINTN *SelectorSize,
IN OUT EFI_IPSEC_CONFIG_SELECTOR *Selector
);
/**
Register an event that is to be signaled whenever a configuration process on the
specified IPsec configuration information is done.
The register function is not surpport now and always returns EFI_UNSUPPORTED.
@param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
@param[in] DataType The type of data to be registered the event for.
@param[in] Event The event to be registered.
@retval EFI_SUCCESS The event is registered successfully.
@retval EFI_INVALID_PARAMETER This is NULL, or Event is NULL.
@retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
@retval EFI_UNSUPPORTED The notify registration unsupported, or the specified
DataType is not supported.
**/
EFI_STATUS
EFIAPI
EfiIpSecConfigRegisterNotify (
IN EFI_IPSEC_CONFIG_PROTOCOL *This,
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN EFI_EVENT Event
);
/**
Remove the specified event that was previously registered on the specified IPsec
configuration data.
This function is not supported now and always returns EFI_UNSUPPORTED.
@param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
@param[in] DataType The configuration data type to remove the registered event for.
@param[in] Event The event to be unregistered.
@retval EFI_SUCCESS The event was removed successfully.
@retval EFI_NOT_FOUND The Event specified by DataType could not be found in the
database.
@retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
@retval EFI_UNSUPPORTED The notify registration unsupported or the specified
DataType is not supported.
**/
EFI_STATUS
EFIAPI
EfiIpSecConfigUnregisterNotify (
IN EFI_IPSEC_CONFIG_PROTOCOL *This,
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN EFI_EVENT Event
);
#endif

View File

@@ -0,0 +1,133 @@
/** @file
Common operation for Security.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "IpSecCryptIo.h"
//
// Alogrithm's informations for the Encrypt/Decrpt Alogrithm.
//
ENCRYPT_ALGORITHM mIpsecEncryptAlgorithmList[IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE] = {
{EFI_IPSEC_EALG_NULL, 0, 0, 1, NULL, NULL, NULL, NULL},
{(UINT8)-1, 0, 0, 0, NULL, NULL, NULL, NULL}
};
//
// Alogrithm's informations for the Authentication algorithm
//
AUTH_ALGORITHM mIpsecAuthAlgorithmList[IPSEC_AUTH_ALGORITHM_LIST_SIZE] = {
{EFI_IPSEC_AALG_NONE, 0, 0, 0, NULL, NULL, NULL, NULL},
{EFI_IPSEC_AALG_NULL, 0, 0, 0, NULL, NULL, NULL, NULL},
{(UINT8)-1, 0, 0, 0, NULL, NULL, NULL, NULL}
};
/**
Get the block size of encrypt alogrithm. The block size is based on the algorithm used.
@param[in] AlgorithmId The encrypt algorithm ID.
@return The value of block size.
**/
UINTN
IpSecGetEncryptBlockSize (
IN UINT8 AlgorithmId
)
{
UINT8 Index;
for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
//
// The BlockSize is same with IvSize.
//
return mIpsecEncryptAlgorithmList[Index].BlockSize;
}
}
return (UINTN) -1;
}
/**
Get the IV size of encrypt alogrithm. The IV size is based on the algorithm used.
@param[in] AlgorithmId The encrypt algorithm ID.
@return The value of IV size.
**/
UINTN
IpSecGetEncryptIvLength (
IN UINT8 AlgorithmId
)
{
UINT8 Index;
for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
//
// The BlockSize is same with IvSize.
//
return mIpsecEncryptAlgorithmList[Index].IvLength;
}
}
return (UINTN) -1;
}
/**
Get the ICV size of Authenticaion alogrithm. The ICV size is based on the algorithm used.
@param[in] AuthAlgorithmId The Authentication algorithm ID.
@return The value of ICV size.
**/
UINTN
IpSecGetIcvLength (
IN UINT8 AuthAlgorithmId
)
{
UINT8 Index;
for (Index = 0; Index < IPSEC_AUTH_ALGORITHM_LIST_SIZE; Index++) {
if (AuthAlgorithmId == mIpsecAuthAlgorithmList[Index].AlgorithmId) {
return mIpsecAuthAlgorithmList[Index].IcvLength;
}
}
return (UINTN) -1;
}
/**
Generate a random data for IV. If the IvSize is zero, not needed to create
IV and return EFI_SUCCESS.
@param[in] IvBuffer The pointer of the IV buffer.
@param[in] IvSize The IV size.
@retval EFI_SUCCESS Create a random data for IV.
**/
EFI_STATUS
IpSecGenerateIv (
IN UINT8 *IvBuffer,
IN UINTN IvSize
)
{
if (IvSize != 0) {
//
//TODO: return CryptGenerateRandom (IvBuffer, IvSize);
//
return EFI_SUCCESS;
}
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,322 @@
/** @file
Definition related to the Security operation.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _EFI_IPSEC_CRYPTIO_H_
#define _EFI_IPSEC_CRYPTIO_H_
#include <Protocol/IpSecConfig.h>
#include <Library/DebugLib.h>
#define IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE 2
#define IPSEC_AUTH_ALGORITHM_LIST_SIZE 3
/**
Prototype of Hash GetContextSize.
Retrieves the size, in bytes, of the context buffer required.
@return The size, in bytes, of the context buffer required.
**/
typedef
UINTN
(EFIAPI *CPL_HASH_GETCONTEXTSIZE) (
VOID
);
/**
Prototype of Hash Operation Initiating.
Initialization with a new context.
@param[in,out] Context Input Context.
@retval TRUE Initialization Successfully.
**/
typedef
EFI_STATUS
(EFIAPI *CPL_HASH_INIT) (
IN OUT VOID *Context
);
/**
Prototype of HASH update.
Hash update operation. Continue an Hash message digest operation, processing
another message block, and updating the Hash context.
If Context is NULL, then ASSERT().
If Data is NULL, then ASSERT().
@param[in,out] Context The Specified Context.
@param[in,out] Data The Input Data to hash.
@param[in] DataLength The length, in bytes, of Data.
@retval TRUE Update data successfully.
@retval FALSE The Context has been finalized.
**/
typedef
BOOLEAN
(EFIAPI *CPL_HASH_UPDATE) (
IN OUT VOID *Context,
IN CONST VOID *Data,
IN UINTN DataLength
);
/**
Prototype of Hash finallization.
Terminate a Hash message digest operation and output the message digest.
If Context is NULL, then ASSERT().
If HashValue is NULL, then ASSERT().
@param[in,out] Context The specified Context.
@param[out] HashValue Pointer to a 16-byte message digest output buffer.
@retval TRUE Finalized successfully.
**/
typedef
BOOLEAN
(EFIAPI *CPL_HASH_FINAL) (
IN OUT VOID *Context,
OUT UINT8 *HashValue
);
/**
Prototype of Cipher GetContextSize.
Retrieves the size, in bytes, of the context buffer required.
@return The size, in bytes, of the context buffer required.
**/
typedef
UINTN
(EFIAPI *CPL_CIPHER_GETCONTEXTSIZE) (
VOID
);
/**
Prototype of Cipher initiation.
Intializes the user-supplied key as the specifed context (key materials) for both
encryption and decryption operations.
If Context is NULL, then ASSERT().
If Key is NULL, then generate random key for usage.
@param[in,out] Context The specified Context.
@param[in] Key User-supplied TDES key (64/128/192 bits).
@param[in] KeyBits Key length in bits.
@retval TRUE TDES Initialization was successful.
**/
typedef
BOOLEAN
(EFIAPI *CPL_CIPHER_INIT) (
IN OUT VOID *Context,
IN CONST UINT8 *Key,
IN CONST UINTN KeyBits
);
/**
Prototype of Cipher encryption.
Encrypts plaintext message with the specified cipher.
If Context is NULL, then ASSERT().
if InData is NULL, then ASSERT().
If Size of input data is not multiple of Cipher algorithm related block size,
then ASSERT().
@param[in] Context The specified Context.
@param[in] InData The input plaintext data to be encrypted.
@param[out] OutData The resultant encrypted ciphertext.
@param[in] DataLength Length of input data in bytes.
@retval TRUE Encryption successful.
**/
typedef
BOOLEAN
(EFIAPI *CPL_CIPHER_ENCRYPT) (
IN VOID *Context,
IN CONST UINT8 *InData,
OUT UINT8 *OutData,
IN CONST UINTN DataLength
);
/**
Prototype of Cipher decryption.
Decrypts cipher message with specified cipher.
If Context is NULL, then ASSERT().
if InData is NULL, then ASSERT().
If Size of input data is not a multiple of a certaion block size , then ASSERT().
@param[in] Context The specified Context.
@param[in] InData The input ciphertext data to be decrypted.
@param[out] OutData The resultant decrypted plaintext.
@param[in] DataLength Length of input data in bytes.
@retval TRUE Decryption successful.
**/
typedef
BOOLEAN
(EFIAPI *CPL_CIPHER_DECRYPT) (
IN CONST VOID *Context,
IN CONST UINT8 *InData,
OUT UINT8 *OutData,
IN CONST UINTN DataLength
);
//
// The struct used to store the informatino and operation of Cipher algorithm.
//
typedef struct _ENCRYPT_ALGORITHM {
//
// The ID of the Algorithm
//
UINT8 AlgorithmId;
//
// The Key length of the Algorithm
//
UINTN KeyLength;
//
// Iv Size of the Algorithm
//
UINTN IvLength;
//
// The Block Size of the Algorithm
//
UINTN BlockSize;
//
// The Function pointer of GetContextSize.
//
CPL_CIPHER_GETCONTEXTSIZE CipherGetContextSize;
//
// The Function pointer of Cipher intitiaion.
//
CPL_CIPHER_INIT CipherInitiate;
//
// The Function pointer of Cipher Encryption.
//
CPL_CIPHER_ENCRYPT CipherEncrypt;
//
// The Function pointer of Cipher Decrption.
//
CPL_CIPHER_DECRYPT CipherDecrypt;
} ENCRYPT_ALGORITHM;
//
// The struct used to store the informatino and operation of Autahentication algorithm.
//
typedef struct _AUTH_ALGORITHM {
//
// ID of the Algorithm
//
UINT8 AlgorithmId;
//
// The Key length of the Algorithm
//
UINTN KeyLength;
//
// The ICV length of the Algorithm
//
UINTN IcvLength;
//
// The block size of the Algorithm
//
UINTN BlockSize;
//
// The function pointer of GetContextSize.
//
CPL_HASH_GETCONTEXTSIZE HashGetContextSize;
//
// The function pointer of Initiatoion
//
CPL_HASH_INIT HashInitiate;
//
// The function pointer of Hash Update.
//
CPL_HASH_UPDATE HashUpdate;
//
// The fucntion pointer of Hash Final
//
CPL_HASH_FINAL HashFinal;
} AUTH_ALGORITHM;
/**
Get the IV size of encrypt alogrithm. IV size is different from different algorithm.
@param[in] AlgorithmId The encrypt algorithm ID.
@return The value of IV size.
**/
UINTN
IpSecGetEncryptIvLength (
IN UINT8 AlgorithmId
);
/**
Get the block size of encrypt alogrithm. Block size is different from different algorithm.
@param[in] AlgorithmId The encrypt algorithm ID.
@return The value of block size.
**/
UINTN
IpSecGetEncryptBlockSize (
IN UINT8 AlgorithmId
);
/**
Get the ICV size of Authenticaion alogrithm. ICV size is different from different algorithm.
@param[in] AuthAlgorithmId The Authentication algorithm ID.
@return The value of ICV size.
**/
UINTN
IpSecGetIcvLength (
IN UINT8 AuthAlgorithmId
);
/**
Generate a random data for IV. If the IvSize is zero, not needed to create
IV and return EFI_SUCCESS.
@param[in] IvBuffer The pointer of the IV buffer.
@param[in] IvSize The IV size.
@retval EFI_SUCCESS Create random data for IV.
**/
EFI_STATUS
IpSecGenerateIv (
IN UINT8 *IvBuffer,
IN UINTN IvSize
);
#endif

View File

@@ -0,0 +1,172 @@
/** @file
Interface of IPsec printing debug information.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "IpSecImpl.h"
#include "IpSecDebug.h"
//
// The print title for IKEv1 variety phase.
//
CHAR8 *mStateStr[] = {
"IKEv1_MAIN_1",
"IKEv1_MAIN_2",
"IKEv1_MAIN_3",
"IKEv1_MAIN_ESTABLISHED",
"IKEv1_QUICK_1",
"IKEv1_QUICK_2",
"IKEv1_QUICK_ESTABLISHED"
};
//
// The print title for IKEv1 variety Exchagne.
//
CHAR8 *mExchangeStr[] = {
"IKEv1 Main Exchange",
"IKEv1 Info Exchange",
"IKEv1 Quick Exchange",
"IKEv1 Unknown Exchange"
};
//
// The print title for IKEv1 variety Payload.
//
CHAR8 *mPayloadStr[] = {
"IKEv1 None Payload",
"IKEv1 SA Payload",
"IKEv1 Proposal Payload",
"IKEv1 Transform Payload",
"IKEv1 KE Payload",
"IKEv1 ID Payload",
"IKEv1 Certificate Payload",
"IKEv1 Certificate Request Payload",
"IKEv1 Hash Payload",
"IKEv1 Signature Payload",
"IKEv1 Nonce Payload",
"IKEv1 Notify Payload",
"IKEv1 Delete Payload",
"IKEv1 Vendor Payload"
};
/**
Print the IP address.
@param[in] Level Debug print error level. Pass to DEBUG().
@param[in] Ip Point to a specified IP address.
@param[in] IpVersion The IP Version.
**/
VOID
IpSecDumpAddress (
IN UINTN Level,
IN EFI_IP_ADDRESS *Ip,
IN UINT8 IpVersion
)
{
if (IpVersion == IP_VERSION_6) {
DEBUG (
(Level,
"%x%x:%x%x:%x%x:%x%x",
Ip->v6.Addr[0],
Ip->v6.Addr[1],
Ip->v6.Addr[2],
Ip->v6.Addr[3],
Ip->v6.Addr[4],
Ip->v6.Addr[5],
Ip->v6.Addr[6],
Ip->v6.Addr[7])
);
DEBUG (
(Level,
":%x%x:%x%x:%x%x:%x%x\n",
Ip->v6.Addr[8],
Ip->v6.Addr[9],
Ip->v6.Addr[10],
Ip->v6.Addr[11],
Ip->v6.Addr[12],
Ip->v6.Addr[13],
Ip->v6.Addr[14],
Ip->v6.Addr[15])
);
} else {
DEBUG (
(Level,
"%d.%d.%d.%d\n",
Ip->v4.Addr[0],
Ip->v4.Addr[1],
Ip->v4.Addr[2],
Ip->v4.Addr[3])
);
}
}
/**
Print IKEv1 Current states.
@param[in] Previous The Previous state of IKEv1.
@param[in] Current The current state of IKEv1.
**/
VOID
IpSecDumpState (
IN UINT32 Previous,
IN UINT32 Current
)
{
if (Previous == Current) {
DEBUG ((DEBUG_INFO, "\n****Current state is %a\n", mStateStr[Previous]));
} else {
DEBUG ((DEBUG_INFO, "\n****Change state from %a to %a\n", mStateStr[Previous], mStateStr[Current]));
}
}
/**
Print the buffer in form of Hex.
@param[in] Title The strings to be printed before the data of the buffer.
@param[in] Data Points to buffer to be printed.
@param[in] DataSize The size of the buffer to be printed.
**/
VOID
IpSecDumpBuf (
IN CHAR8 *Title,
IN UINT8 *Data,
IN UINTN DataSize
)
{
UINTN Index;
UINTN DataIndex;
UINTN BytesRemaining;
UINTN BytesToPrint;
DataIndex = 0;
BytesRemaining = DataSize;
DEBUG ((DEBUG_INFO, "==%a %d bytes==\n", Title, DataSize));
while (BytesRemaining > 0) {
BytesToPrint = (BytesRemaining > IPSEC_DEBUG_BYTE_PER_LINE) ? IPSEC_DEBUG_BYTE_PER_LINE : BytesRemaining;
for (Index = 0; Index < BytesToPrint; Index++) {
DEBUG ((DEBUG_INFO, " 0x%02x,", Data[DataIndex++]));
}
DEBUG ((DEBUG_INFO, "\n"));
BytesRemaining -= BytesToPrint;
}
}

View File

@@ -0,0 +1,102 @@
/** @file
The definition of functions and MACROs used for IPsec debug information print.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _EFI_IPSEC_DEBUG_H_
#define _EFI_IPSEC_DEBUG_H_
#include <Library/DebugLib.h>
#define IPSEC_DUMP_ADDRESS(Level, Ip, Version) IpSecDumpAddress (Level, Ip, Version)
#define IPSEC_DUMP_STATE(Previous, Current) IpSecDumpState (Previous, Current)
#define IPSEC_DUMP_PACKET(Packet, Direction, IpVersion) IpSecDumpPacket (Packet, Direction, IpVersion)
#define IPSEC_DUMP_PAYLOAD(IkePayload) IpSecDumpPayload (IkePayload)
#define IPSEC_DUMP_BUF(Title, Data, DataSize) IpSecDumpBuf (Title, Data, DataSize)
#define IPSEC_DEBUG_BYTE_PER_LINE 8
/**
Print the IP address.
@param[in] Level Debug print error level. Pass to DEBUG().
@param[in] Ip Point to specified IP address.
@param[in] IpVersion The IP Version.
**/
VOID
IpSecDumpAddress (
IN UINTN Level,
IN EFI_IP_ADDRESS *Ip,
IN UINT8 IpVersion
);
/**
Print IKEv1 Current states.
@param[in] Previous The Previous state of IKEv1.
@param[in] Current The current state of IKEv1.
**/
VOID
IpSecDumpState (
IN UINT32 Previous,
IN UINT32 Current
);
/**
Print the Ike Packet.
@param[in] Packet Point to IKE packet to be printed.
@param[in] Direction Point to the IKE packet is inbound or outbound.
@param[in] IpVersion Specified IP Version.
**/
/*
VOID
IpSecDumpPacket (
IN IKE_PACKET *Packet,
IN EFI_IPSEC_TRAFFIC_DIR Direction,
IN UINT8 IpVersion
);
*/
/**
Print the IKE Paylolad.
@param[in] IkePayload Points to the payload to be printed.
**/
/*
VOID
IpSecDumpPayload (
IN IKE_PAYLOAD *IkePayload
);
*/
/**
Print the buffer in form of Hex.
@param[in] Title The strings to be printed before the data of the buffer.
@param[in] Data Points to the buffer to be printed.
@param[in] DataSize The size of the buffer to be printed.
**/
VOID
IpSecDumpBuf (
IN CHAR8 *Title,
IN UINT8 *Data,
IN UINTN DataSize
);
#endif

View File

@@ -0,0 +1,282 @@
/** @file
Driver Binding Protocol for IPsec Driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Library/UdpIoLib.h>
#include "IpSecConfigImpl.h"
#include "IpSecDebug.h"
/**
Test to see if this driver supports ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to test.
@param[in] RemainingDevicePath Optional parameter used 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
IpSecDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
//
//TODO: Add Udp4Protocol and Udp6Protocol testing.
//
return EFI_UNSUPPORTED;
}
/**
Start this driver on ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to bind driver to.
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
device to start.
@retval EFI_SUCCES This driver is added to ControllerHandle
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
@retval EFI_DEVICE_ERROR The device could not be started due to a device error.
Currently not implemented.
@retval other This driver does not support this device
**/
EFI_STATUS
EFIAPI
IpSecDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
//
//TODO: Add Udp4Io and Udp6Io creation for the IKE.
//
return EFI_SUCCESS;
}
/**
Stop this driver on ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of a device to stop the driver on.
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of
children is zero, stop the entire bus driver.
@param[in] ChildHandleBuffer List of Child Handles to Stop.
@retval EFI_SUCCES This driver removed ControllerHandle.
@retval other This driver was not removed from this device.
**/
EFI_STATUS
EFIAPI
IpSecDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
//
//TODO: Add UdpIo4 and UdpIo6 destruction when the Udp driver unload or stop.
//
return EFI_UNSUPPORTED;
}
EFI_DRIVER_BINDING_PROTOCOL gIpSecDriverBinding = {
IpSecDriverBindingSupported,
IpSecDriverBindingStart,
IpSecDriverBindingStop,
0xa,
NULL,
NULL
};
/**
This is a callback function when the mIpSecInstance.DisabledEvent is signaled.
@param[in] Event Event whose notification function is being invoked.
@param[in] Context Pointer to the notification function's context.
**/
VOID
EFIAPI
IpSecCleanupAllSa (
IN EFI_EVENT Event,
IN VOID *Context
)
{
IPSEC_PRIVATE_DATA *Private;
UINT8 Value;
EFI_STATUS Status;
Private = (IPSEC_PRIVATE_DATA *) Context;
//
// Set the Status Variable
//
Value = IPSEC_STATUS_DISABLED;
Status = gRT->SetVariable (
IPSECCONFIG_STATUS_NAME,
&gEfiIpSecConfigProtocolGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
sizeof (Value),
&Value
);
if (!EFI_ERROR (Status)) {
Private->IpSec.DisabledFlag = TRUE;
}
}
/**
This is the declaration of an EFI image entry point. This entry point is
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
both device drivers and bus drivers.
The entry point for IPsec driver which installs the driver binding,
component name protocol, IPsec Config protcolon, and IPsec protocol in
its ImageHandle.
@param[in] ImageHandle The firmware allocated handle for the UEFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_ALREADY_STARTED The IPsec driver has been already loaded.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
@retval Others The operation is failed.
**/
EFI_STATUS
EFIAPI
IpSecDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
IPSEC_PRIVATE_DATA *Private;
EFI_IPSEC_PROTOCOL *IpSec;
//
// Check whether ipsec protocol has already been installed.
//
Status = gBS->LocateProtocol (&gEfiIpSecProtocolGuid, NULL, (VOID **) &IpSec);
if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "_ModuleEntryPoint: IpSec has been already loaded\n"));
Status = EFI_ALREADY_STARTED;
goto ON_EXIT;
}
Status = gBS->LocateProtocol (&gEfiDpcProtocolGuid, NULL, (VOID **) &mDpc);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to locate EfiDpcProtocol\n"));
goto ON_EXIT;
}
Private = AllocateZeroPool (sizeof (IPSEC_PRIVATE_DATA));
if (Private == NULL) {
DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to allocate private data\n"));
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
//
// Create disable event to cleanup all sa when ipsec disabled by user.
//
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
IpSecCleanupAllSa,
Private,
&mIpSecInstance.DisabledEvent
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to create disable event\n"));
goto ON_FREE_PRIVATE;
}
Private->Signature = IPSEC_PRIVATE_DATA_SIGNATURE;
Private->ImageHandle = ImageHandle;
CopyMem (&Private->IpSec, &mIpSecInstance, sizeof (EFI_IPSEC_PROTOCOL));
//
// Initilize Private's members. Thess members is used for IKE.
//
InitializeListHead (&Private->Udp4List);
InitializeListHead (&Private->Udp6List);
InitializeListHead (&Private->Ikev1SessionList);
InitializeListHead (&Private->Ikev1EstablishedList);
InitializeListHead (&Private->Ikev2SessionList);
InitializeListHead (&Private->Ikev2EstablishedList);
//
// Initialize the ipsec config data and restore it from variable.
//
Status = IpSecConfigInitialize (Private);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to initialize IpSecConfig\n"));
goto ON_CLOSE_EVENT;
}
//
// Install ipsec protocol which is used by ip driver to process ipsec header.
//
Status = gBS->InstallMultipleProtocolInterfaces (
&Private->Handle,
&gEfiIpSecProtocolGuid,
&Private->IpSec,
NULL
);
if (EFI_ERROR (Status)) {
goto ON_UNINSTALL_CONFIG;
}
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gIpSecDriverBinding,
ImageHandle,
&gIpSecComponentName,
&gIpSecComponentName2
);
if (EFI_ERROR (Status)) {
goto ON_UNINSTALL_CONFIG;
}
return Status;
ON_UNINSTALL_CONFIG:
gBS->UninstallProtocolInterface (
Private->Handle,
&gEfiIpSecConfigProtocolGuid,
&Private->IpSecConfig
);
ON_CLOSE_EVENT:
gBS->CloseEvent (mIpSecInstance.DisabledEvent);
mIpSecInstance.DisabledEvent = NULL;
ON_FREE_PRIVATE:
FreePool (Private);
ON_EXIT:
return Status;
}

View File

@@ -0,0 +1,63 @@
## @file
# Component description file for IpSec module.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = IpSecDxe
FILE_GUID = EE8367C0-A1D6-4565-8F89-EF628547B722
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = IpSecDriverEntryPoint
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
IpSecConfigImpl.c
IpSecConfigImpl.h
IpSecCryptIo.h
IpSecCryptIo.c
IpSecDebug.h
ComponentName.c
IpSecImpl.c
IpSecDebug.c
IpSecSaEngine.c
IpSecDriver.c
IpSecImpl.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
MemoryAllocationLib
BaseLib
UefiLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
UefiDriverEntryPoint
BaseMemoryLib
DebugLib
PrintLib
DpcLib
NetLib
[Protocols]
gEfiIp4ConfigProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiIpSecConfigProtocolGuid # PROTOCOL ALWAYS_PRODUCED
gEfiIpSecProtocolGuid # PROTOCOL ALWAYS_PRODUCED

View File

@@ -0,0 +1,856 @@
/** @file
The implementation of IPsec Protocol
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "IpSecConfigImpl.h"
EFI_IPSEC_PROTOCOL mIpSecInstance = { IpSecProcess, NULL, TRUE };
extern LIST_ENTRY mConfigData[IPsecConfigDataTypeMaximum];
/**
Check if the specified Address is the Valid Address Range.
This function checks if the bytes after prefixed length are all Zero in this
Address. This Address is supposed to point to a range address, meaning it only
gives the correct prefixed address.
@param[in] IpVersion The IP version.
@param[in] Address Points to EFI_IP_ADDRESS to be checked.
@param[in] PrefixLength The PrefixeLength of this address.
@retval TRUE The address is a vaild address range.
@retval FALSE The address is not a vaild address range.
**/
BOOLEAN
IpSecValidAddressRange (
IN UINT8 IpVersion,
IN EFI_IP_ADDRESS *Address,
IN UINT8 PrefixLength
)
{
UINT8 Div;
UINT8 Mod;
UINT8 Mask;
UINT8 AddrLen;
UINT8 *Addr;
EFI_IP_ADDRESS ZeroAddr;
if (PrefixLength == 0) {
return TRUE;
}
AddrLen = (UINT8) ((IpVersion == IP_VERSION_4) ? 32 : 128);
if (AddrLen <= PrefixLength) {
return FALSE;
}
Div = (UINT8) (PrefixLength / 8);
Mod = (UINT8) (PrefixLength % 8);
Addr = (UINT8 *) Address;
ZeroMem (&ZeroAddr, sizeof (EFI_IP_ADDRESS));
//
// Check whether the mod part of host scope is zero or not.
//
if (Mod > 0) {
Mask = (UINT8) (0xFF << (8 - Mod));
if ((Addr[Div] | Mask) != Mask) {
return FALSE;
}
Div++;
}
//
// Check whether the div part of host scope is zero or not.
//
if (CompareMem (
&Addr[Div],
&ZeroAddr,
sizeof (EFI_IP_ADDRESS) - Div
) != 0) {
return FALSE;
}
return TRUE;
}
/**
Extrct the Address Range from a Address.
This function keep the prefix address and zero other part address.
@param[in] Address Point to a specified address.
@param[in] PrefixLength The prefix length.
@param[out] Range Contain the return Address Range.
**/
VOID
IpSecExtractAddressRange (
IN EFI_IP_ADDRESS *Address,
IN UINT8 PrefixLength,
OUT EFI_IP_ADDRESS *Range
)
{
UINT8 Div;
UINT8 Mod;
UINT8 Mask;
UINT8 *Addr;
if (PrefixLength == 0) {
return ;
}
Div = (UINT8) (PrefixLength / 8);
Mod = (UINT8) (PrefixLength % 8);
Addr = (UINT8 *) Range;
CopyMem (Range, Address, sizeof (EFI_IP_ADDRESS));
//
// Zero the mod part of host scope.
//
if (Mod > 0) {
Mask = (UINT8) (0xFF << (8 - Mod));
Addr[Div] = (UINT8) (Addr[Div] & Mask);
Div++;
}
//
// Zero the div part of host scope.
//
ZeroMem (&Addr[Div], sizeof (EFI_IP_ADDRESS) - Div);
}
/**
Checks if the IP Address in the address range of AddressInfos specified.
@param[in] IpVersion The IP version.
@param[in] IpAddr Point to EFI_IP_ADDRESS to be check.
@param[in] AddressInfo A list of EFI_IP_ADDRESS_INFO that is used to check
the IP Address is matched.
@param[in] AddressCount The total numbers of the AddressInfo.
@retval TRUE If the Specified IP Address is in the range of the AddressInfos specified.
@retval FALSE If the Specified IP Address is not in the range of the AddressInfos specified.
**/
BOOLEAN
IpSecMatchIpAddress (
IN UINT8 IpVersion,
IN EFI_IP_ADDRESS *IpAddr,
IN EFI_IP_ADDRESS_INFO *AddressInfo,
IN UINT32 AddressCount
)
{
EFI_IP_ADDRESS Range;
UINT32 Index;
BOOLEAN IsMatch;
IsMatch = FALSE;
for (Index = 0; Index < AddressCount; Index++) {
//
// Check whether the target address is in the address range
// if it's a valid range of address.
//
if (IpSecValidAddressRange (
IpVersion,
&AddressInfo[Index].Address,
AddressInfo[Index].PrefixLength
)) {
//
// Get the range of the target address belongs to.
//
ZeroMem (&Range, sizeof (EFI_IP_ADDRESS));
IpSecExtractAddressRange (
IpAddr,
AddressInfo[Index].PrefixLength,
&Range
);
if (CompareMem (
&Range,
&AddressInfo[Index].Address,
sizeof (EFI_IP_ADDRESS)
) == 0) {
//
// The target address is in the address range.
//
IsMatch = TRUE;
break;
}
}
if (CompareMem (
IpAddr,
&AddressInfo[Index].Address,
sizeof (EFI_IP_ADDRESS)
) == 0) {
//
// The target address is exact same as the address.
//
IsMatch = TRUE;
break;
}
}
return IsMatch;
}
/**
Check if the specified Protocol and Prot is supported by the specified SPD Entry.
This function is the subfunction of IPsecLookUpSpdEntry() that is used to
check if the sent/received IKE packet has the related SPD entry support.
@param[in] Protocol The Protocol to be checked.
@param[in] IpPayload Point to IP Payload to be check.
@param[in] SpdProtocol The Protocol supported by SPD.
@param[in] SpdLocalPort The Local Port in SPD.
@param[in] SpdRemotePort The Remote Port in SPD.
@param[in] IsOutbound Flag to indicate the is for IKE Packet sending or recieving.
@retval TRUE The Protocol and Port are supported by the SPD Entry.
@retval FALSE The Protocol and Port are not supported by the SPD Entry.
**/
BOOLEAN
IpSecMatchNextLayerProtocol (
IN UINT8 Protocol,
IN UINT8 *IpPayload,
IN UINT16 SpdProtocol,
IN UINT16 SpdLocalPort,
IN UINT16 SpdRemotePort,
IN BOOLEAN IsOutbound
)
{
BOOLEAN IsMatch;
if (SpdProtocol == EFI_IPSEC_ANY_PROTOCOL) {
return TRUE;
}
IsMatch = FALSE;
if (SpdProtocol == Protocol) {
switch (Protocol) {
case EFI_IP_PROTO_UDP:
case EFI_IP_PROTO_TCP:
//
// For udp and tcp, (0, 0) means no need to check local and remote
// port. The payload is passed from upper level, which means it should
// be in network order.
//
IsMatch = (BOOLEAN) (SpdLocalPort == 0 && SpdRemotePort == 0);
IsMatch = (BOOLEAN) (IsMatch ||
(IsOutbound &&
(BOOLEAN)(
NTOHS (((EFI_UDP_HEADER *) IpPayload)->SrcPort) == SpdLocalPort &&
NTOHS (((EFI_UDP_HEADER *) IpPayload)->DstPort) == SpdRemotePort
)
));
IsMatch = (BOOLEAN) (IsMatch ||
(!IsOutbound &&
(BOOLEAN)(
NTOHS (((EFI_UDP_HEADER *) IpPayload)->DstPort) == SpdLocalPort &&
NTOHS (((EFI_UDP_HEADER *) IpPayload)->SrcPort) == SpdRemotePort
)
));
break;
case EFI_IP_PROTO_ICMP:
//
// For icmpv4, type code is replaced with local port and remote port,
// and (0, 0) means no need to check.
//
IsMatch = (BOOLEAN) (SpdLocalPort == 0 && SpdRemotePort == 0);
IsMatch = (BOOLEAN) (IsMatch ||
(BOOLEAN) (((IP4_ICMP_HEAD *) IpPayload)->Type == SpdLocalPort &&
((IP4_ICMP_HEAD *) IpPayload)->Code == SpdRemotePort
)
);
break;
case IP6_ICMP:
//
// For icmpv6, type code is replaced with local port and remote port,
// and (0, 0) means no need to check.
//
IsMatch = (BOOLEAN) (SpdLocalPort == 0 && SpdRemotePort == 0);
IsMatch = (BOOLEAN) (IsMatch ||
(BOOLEAN) (((IP6_ICMP_HEAD *) IpPayload)->Type == SpdLocalPort &&
((IP6_ICMP_HEAD *) IpPayload)->Code == SpdRemotePort
)
);
break;
default:
IsMatch = TRUE;
break;
}
}
return IsMatch;
}
/**
Find the SAD through a specified SPD's SAD list.
@param[in] SadList SAD list related to a specified SPD entry.
@param[in] DestAddress The destination address used to find the SAD entry.
@return The pointer to a certain SAD entry.
**/
IPSEC_SAD_ENTRY *
IpSecLookupSadBySpd (
IN LIST_ENTRY *SadList,
IN EFI_IP_ADDRESS *DestAddress
)
{
LIST_ENTRY *Entry;
IPSEC_SAD_ENTRY *SadEntry;
for (Entry = SadList->ForwardLink; Entry != SadList; Entry = Entry->ForwardLink) {
SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry);
//
// Find the right sad entry which contains the appointed dest address.
//
if (CompareMem (
&SadEntry->Id->DestAddress,
DestAddress,
sizeof (EFI_IP_ADDRESS)
) == 0) {
return SadEntry;
}
}
return NULL;
}
/**
Find the SAD through whole SAD list.
@param[in] Spi The SPI used to search the SAD entry.
@param[in] DestAddress The destination used to search the SAD entry.
@return the pointer to a certain SAD entry.
**/
IPSEC_SAD_ENTRY *
IpSecLookupSadBySpi (
IN UINT32 Spi,
IN EFI_IP_ADDRESS *DestAddress
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *SadList;
IPSEC_SAD_ENTRY *SadEntry;
SadList = &mConfigData[IPsecConfigDataTypeSad];
for (Entry = SadList->ForwardLink; Entry != SadList; Entry = Entry->ForwardLink) {
SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
//
// Find the right sad entry which contain the appointed spi and dest addr.
//
if (SadEntry->Id->Spi == Spi && CompareMem (
&SadEntry->Id->DestAddress,
DestAddress,
sizeof (EFI_IP_ADDRESS)
) == 0) {
return SadEntry;
}
}
return NULL;
}
/**
Look up if there is existing SAD entry for specified IP packet sending.
This function is called by the IPsecProcess when there is some IP packet needed to
send out. This function checks if there is an existing SAD entry that can be serviced
to this IP packet sending. If no existing SAD entry could be used, this
function will invoke an IPsec Key Exchange Negotiation.
@param[in] Private Points to private data.
@param[in] NicHandle Points to a NIC handle.
@param[in] IpVersion The version of IP.
@param[in] IpHead The IP Header of packet to be sent out.
@param[in] IpPayload The IP Payload to be sent out.
@param[in] OldLastHead The Last protocol of the IP packet.
@param[in] SpdEntry Points to a related SPD entry.
@param[out] SadEntry Contains the Point of a related SAD entry.
@retval EFI_DEVICE_ERROR One of following conditions is TRUE:
- If don't find related UDP service.
- Sequence Number is used up.
- Extension Sequence Number is used up.
@retval EFI_DEVICE_ERROR GC_TODO: Add description for return value.
@retval EFI_NOT_READY No existing SAD entry could be used.
@retval EFI_SUCCESS Find the related SAD entry.
**/
EFI_STATUS
IpSecLookupSadEntry (
IN IPSEC_PRIVATE_DATA *Private,
IN EFI_HANDLE NicHandle,
IN UINT8 IpVersion,
IN VOID *IpHead,
IN UINT8 *IpPayload,
IN UINT8 OldLastHead,
IN IPSEC_SPD_ENTRY *SpdEntry,
OUT IPSEC_SAD_ENTRY **SadEntry
)
{
IPSEC_SAD_ENTRY *Entry;
IPSEC_SAD_DATA *Data;
EFI_IP_ADDRESS DestIp;
UINT32 SeqNum32;
*SadEntry = NULL;
//
// Parse the destination address from ip header.
//
ZeroMem (&DestIp, sizeof (EFI_IP_ADDRESS));
if (IpVersion == IP_VERSION_4) {
CopyMem (
&DestIp,
&((IP4_HEAD *) IpHead)->Dst,
sizeof (IP4_ADDR)
);
} else {
CopyMem (
&DestIp,
&((EFI_IP6_HEADER *) IpHead)->DestinationAddress,
sizeof (EFI_IP_ADDRESS)
);
}
//
// Find the sad entry in the spd.sas list according to the dest address.
//
Entry = IpSecLookupSadBySpd (&SpdEntry->Data->Sas, &DestIp);
if (Entry == NULL) {
if (OldLastHead != IP6_ICMP ||
(OldLastHead == IP6_ICMP && *IpPayload == ICMP_V6_ECHO_REQUEST)
) {
//
// TODO: Start ike negotiation process except the request packet of ping.
//
//IkeNegotiate (UdpService, SpdEntry, &DestIp);
}
return EFI_NOT_READY;
}
Data = Entry->Data;
if (!Data->ManualSet) {
if (Data->ESNEnabled) {
//
// Validate the 64bit sn number if 64bit sn enabled.
//
if (Data->SequenceNumber + 1 < Data->SequenceNumber) {
//
// TODO: Re-negotiate SA
//
return EFI_DEVICE_ERROR;
}
} else {
//
// Validate the 32bit sn number if 64bit sn disabled.
//
SeqNum32 = (UINT32) Data->SequenceNumber;
if (SeqNum32 + 1 < SeqNum32) {
//
// TODO: Re-negotiate SA
//
return EFI_DEVICE_ERROR;
}
}
}
*SadEntry = Entry;
return EFI_SUCCESS;
}
/**
Find a PAD entry according to a remote IP address.
@param[in] IpVersion The version of IP.
@param[in] IpAddr Points to remote IP address.
@return the pointer of related PAD entry.
**/
IPSEC_PAD_ENTRY *
IpSecLookupPadEntry (
IN UINT8 IpVersion,
IN EFI_IP_ADDRESS *IpAddr
)
{
LIST_ENTRY *PadList;
LIST_ENTRY *Entry;
EFI_IP_ADDRESS_INFO *IpAddrInfo;
IPSEC_PAD_ENTRY *PadEntry;
PadList = &mConfigData[IPsecConfigDataTypePad];
for (Entry = PadList->ForwardLink; Entry != PadList; Entry = Entry->ForwardLink) {
PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
IpAddrInfo = &PadEntry->Id->Id.IpAddress;
//
// Find the right pad entry which contain the appointed dest addr.
//
if (IpSecMatchIpAddress (IpVersion, IpAddr, IpAddrInfo, 1)) {
return PadEntry;
}
}
return NULL;
}
/**
Check if the specified IP packet can be serviced by this SPD entry.
@param[in] SpdEntry Point to SPD entry.
@param[in] IpVersion Version of IP.
@param[in] IpHead Point to IP header.
@param[in] IpPayload Point to IP payload.
@param[in] Protocol The Last protocol of IP packet.
@param[in] IsOutbound Traffic direction.
@retval EFI_IPSEC_ACTION The support action of SPD entry.
@retval -1 If the input packet header doesn't match the SpdEntry.
**/
EFI_IPSEC_ACTION
IpSecLookupSpdEntry (
IN IPSEC_SPD_ENTRY *SpdEntry,
IN UINT8 IpVersion,
IN VOID *IpHead,
IN UINT8 *IpPayload,
IN UINT8 Protocol,
IN BOOLEAN IsOutbound
)
{
EFI_IPSEC_SPD_SELECTOR *SpdSel;
IP4_HEAD *Ip4;
EFI_IP6_HEADER *Ip6;
EFI_IP_ADDRESS SrcAddr;
EFI_IP_ADDRESS DstAddr;
BOOLEAN SpdMatch;
ASSERT (SpdEntry != NULL);
SpdSel = SpdEntry->Selector;
Ip4 = (IP4_HEAD *) IpHead;
Ip6 = (EFI_IP6_HEADER *) IpHead;
ZeroMem (&SrcAddr, sizeof (EFI_IP_ADDRESS));
ZeroMem (&DstAddr, sizeof (EFI_IP_ADDRESS));
//
// Parse the source and destination address from ip header.
//
if (IpVersion == IP_VERSION_4) {
CopyMem (&SrcAddr, &Ip4->Src, sizeof (IP4_ADDR));
CopyMem (&DstAddr, &Ip4->Dst, sizeof (IP4_ADDR));
} else {
CopyMem (&SrcAddr, &Ip6->SourceAddress, sizeof (EFI_IPv6_ADDRESS));
CopyMem (&DstAddr, &Ip6->DestinationAddress, sizeof (EFI_IPv6_ADDRESS));
}
//
// Check the local and remote addresses for outbound traffic
//
SpdMatch = (BOOLEAN)(IsOutbound &&
IpSecMatchIpAddress (
IpVersion,
&SrcAddr,
SpdSel->LocalAddress,
SpdSel->LocalAddressCount
) &&
IpSecMatchIpAddress (
IpVersion,
&DstAddr,
SpdSel->RemoteAddress,
SpdSel->RemoteAddressCount
)
);
//
// Check the local and remote addresses for inbound traffic
//
SpdMatch = (BOOLEAN) (SpdMatch ||
(!IsOutbound &&
IpSecMatchIpAddress (
IpVersion,
&DstAddr,
SpdSel->LocalAddress,
SpdSel->LocalAddressCount
) &&
IpSecMatchIpAddress (
IpVersion,
&SrcAddr,
SpdSel->RemoteAddress,
SpdSel->RemoteAddressCount
)
));
//
// Check the next layer protocol and local and remote ports.
//
SpdMatch = (BOOLEAN) (SpdMatch &&
IpSecMatchNextLayerProtocol (
Protocol,
IpPayload,
SpdSel->NextLayerProtocol,
SpdSel->LocalPort,
SpdSel->RemotePort,
IsOutbound
)
);
if (SpdMatch) {
//
// Find the right spd entry if match the 5 key elements.
//
return SpdEntry->Data->Action;
}
return (EFI_IPSEC_ACTION) - 1;
}
/**
Handles IPsec packet processing for inbound and outbound IP packets.
The EFI_IPSEC_PROCESS process routine handles each inbound or outbound packet.
The behavior is that it can perform one of the following actions:
bypass the packet, discard the packet, or protect the packet.
@param[in] This Pointer to the EFI_IPSEC_PROTOCOL instance.
@param[in] NicHandle Instance of the network interface.
@param[in] IpVersion IPV4 or IPV6.
@param[in, out] IpHead Pointer to the IP Header.
@param[in] LastHead The protocol of the next layer to be processed by IPsec.
@param[in] OptionsBuffer Pointer to the options buffer.
@param[in] OptionsLength Length of the options buffer.
@param[in, out] FragmentTable Pointer to a list of fragments.
@param[in] FragmentCount Number of fragments.
@param[in] TrafficDirection Traffic direction.
@param[out] RecycleSignal Event for recycling of resources.
@retval EFI_SUCCESS The packet was bypassed and all buffers remain the same.
@retval EFI_SUCCESS The packet was protected.
@retval EFI_ACCESS_DENIED The packet was discarded.
**/
EFI_STATUS
EFIAPI
IpSecProcess (
IN EFI_IPSEC_PROTOCOL *This,
IN EFI_HANDLE NicHandle,
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer,
IN UINT32 OptionsLength,
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
IN EFI_IPSEC_TRAFFIC_DIR TrafficDirection,
OUT EFI_EVENT *RecycleSignal
)
{
IPSEC_PRIVATE_DATA *Private;
IPSEC_SPD_ENTRY *SpdEntry;
IPSEC_SAD_ENTRY *SadEntry;
LIST_ENTRY *SpdList;
LIST_ENTRY *Entry;
EFI_IPSEC_ACTION Action;
EFI_STATUS Status;
UINT8 *IpPayload;
UINT8 OldLastHead;
BOOLEAN IsOutbound;
Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (This);
IpPayload = (*FragmentTable)[0].FragmentBuffer;
IsOutbound = (BOOLEAN) ((TrafficDirection == EfiIPsecOutBound) ? TRUE : FALSE);
OldLastHead = *LastHead;
*RecycleSignal = NULL;
if (!IsOutbound) {
//
// For inbound traffic, process the ipsec header of the packet.
//
Status = IpSecProtectInboundPacket (
IpVersion,
IpHead,
LastHead,
OptionsBuffer,
OptionsLength,
FragmentTable,
FragmentCount,
&SpdEntry,
RecycleSignal
);
if (Status == EFI_ACCESS_DENIED) {
//
// The packet is denied to access.
//
goto ON_EXIT;
}
if (Status == EFI_SUCCESS) {
//
// Check the spd entry if the packet is accessible.
//
if (SpdEntry == NULL) {
Status = EFI_ACCESS_DENIED;
goto ON_EXIT;
}
Action = IpSecLookupSpdEntry (
SpdEntry,
IpVersion,
IpHead,
IpPayload,
*LastHead,
IsOutbound
);
if (Action != EfiIPsecActionProtect) {
//
// Discard the packet if the spd entry is not protect.
//
gBS->SignalEvent (*RecycleSignal);
*RecycleSignal = NULL;
Status = EFI_ACCESS_DENIED;
}
goto ON_EXIT;
}
}
Status = EFI_ACCESS_DENIED;
SpdList = &mConfigData[IPsecConfigDataTypeSpd];
for (Entry = SpdList->ForwardLink; Entry != SpdList; Entry = Entry->ForwardLink) {
//
// For outbound and non-ipsec Inbound traffic: check the spd entry.
//
SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
Action = IpSecLookupSpdEntry (
SpdEntry,
IpVersion,
IpHead,
IpPayload,
OldLastHead,
IsOutbound
);
switch (Action) {
case EfiIPsecActionProtect:
if (IsOutbound) {
//
// For outbound traffic, lookup the sad entry.
//
Status = IpSecLookupSadEntry (
Private,
NicHandle,
IpVersion,
IpHead,
IpPayload,
OldLastHead,
SpdEntry,
&SadEntry
);
if (SadEntry != NULL) {
//
// Process the packet by the found sad entry.
//
Status = IpSecProtectOutboundPacket (
IpVersion,
IpHead,
LastHead,
OptionsBuffer,
OptionsLength,
FragmentTable,
FragmentCount,
SadEntry,
RecycleSignal
);
} else if (OldLastHead == IP6_ICMP && *IpPayload != ICMP_V6_ECHO_REQUEST) {
//
// TODO: if no need return not ready to upper layer, change here.
//
Status = EFI_SUCCESS;
}
} else if (OldLastHead == IP6_ICMP && *IpPayload != ICMP_V6_ECHO_REQUEST) {
//
// For inbound icmpv6 traffic except ping request, accept the packet
// although no sad entry associated with protect spd entry.
//
IpSecLookupSadEntry (
Private,
NicHandle,
IpVersion,
IpHead,
IpPayload,
OldLastHead,
SpdEntry,
&SadEntry
);
if (SadEntry == NULL) {
Status = EFI_SUCCESS;
}
}
goto ON_EXIT;
case EfiIPsecActionBypass:
Status = EFI_SUCCESS;
goto ON_EXIT;
case EfiIPsecActionDiscard:
goto ON_EXIT;
default:
//
// Discard the packet if no spd entry match.
//
break;
}
}
ON_EXIT:
return Status;
}

View File

@@ -0,0 +1,313 @@
/** @file
The definitions related to IPsec protocol implementation.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _IP_SEC_IMPL_H_
#define _IP_SEC_IMPL_H_
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/NetLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Protocol/IpSec.h>
#include <Protocol/IpSecConfig.h>
#include <Protocol/Dpc.h>
#include <Protocol/ComponentName.h>
#include <Protocol/ComponentName2.h>
typedef struct _IPSEC_PRIVATE_DATA IPSEC_PRIVATE_DATA;
typedef struct _IPSEC_SPD_ENTRY IPSEC_SPD_ENTRY;
typedef struct _IPSEC_PAD_ENTRY IPSEC_PAD_ENTRY;
typedef struct _IPSEC_SPD_DATA IPSEC_SPD_DATA;
#define IPSEC_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I', 'P', 'S', 'E')
#define IPSEC_PRIVATE_DATA_FROM_IPSEC(a) CR (a, IPSEC_PRIVATE_DATA, IpSec, IPSEC_PRIVATE_DATA_SIGNATURE)
#define IPSEC_PRIVATE_DATA_FROM_UDP4LIST(a) CR (a, IPSEC_PRIVATE_DATA, Udp4List, IPSEC_PRIVATE_DATA_SIGNATURE)
#define IPSEC_PRIVATE_DATA_FROM_UDP6LIST(a) CR (a, IPSEC_PRIVATE_DATA, Udp6List, IPSEC_PRIVATE_DATA_SIGNATURE)
#define IPSEC_UDP_SERVICE_FROM_LIST(a) BASE_CR (a, IKE_UDP_SERVICE, List)
#define IPSEC_SPD_ENTRY_FROM_LIST(a) BASE_CR (a, IPSEC_SPD_ENTRY, List)
#define IPSEC_SAD_ENTRY_FROM_LIST(a) BASE_CR (a, IPSEC_SAD_ENTRY, List)
#define IPSEC_PAD_ENTRY_FROM_LIST(a) BASE_CR (a, IPSEC_PAD_ENTRY, List)
#define IPSEC_SAD_ENTRY_FROM_SPD(a) BASE_CR (a, IPSEC_SAD_ENTRY, BySpd)
#define IPSEC_STATUS_DISABLED 0
#define IPSEC_STATUS_ENABLED 1
#define IPSEC_ESP_PROTOCOL 50
#define IPSEC_AH_PROTOCOL 51
#define IPSEC_DEFAULT_VARIABLE_SIZE 0x100
//
// Internal Structure Definition
//
#pragma pack(1)
typedef struct _EFI_AH_HEADER {
UINT8 NextHeader;
UINT8 PayloadLen;
UINT16 Reserved;
UINT32 Spi;
UINT32 SequenceNumber;
} EFI_AH_HEADER;
typedef struct _EFI_ESP_HEADER {
UINT32 Spi;
UINT32 SequenceNumber;
} EFI_ESP_HEADER;
typedef struct _EFI_ESP_TAIL {
UINT8 PaddingLength;
UINT8 NextHeader;
} EFI_ESP_TAIL;
#pragma pack()
struct _IPSEC_SPD_DATA {
CHAR16 Name[100];
UINT32 PackageFlag;
EFI_IPSEC_ACTION Action;
EFI_IPSEC_PROCESS_POLICY *ProcessingPolicy;
LIST_ENTRY Sas;
};
struct _IPSEC_SPD_ENTRY {
EFI_IPSEC_SPD_SELECTOR *Selector;
IPSEC_SPD_DATA *Data;
LIST_ENTRY List;
};
typedef struct _IPSEC_SAD_DATA {
EFI_IPSEC_MODE Mode;
UINT64 SequenceNumber;
UINT8 AntiReplayWindowSize;
UINT64 AntiReplayBitmap[4]; // bitmap for received packet
EFI_IPSEC_ALGO_INFO AlgoInfo;
EFI_IPSEC_SA_LIFETIME SaLifetime;
UINT32 PathMTU;
IPSEC_SPD_ENTRY *SpdEntry;
BOOLEAN ESNEnabled; // Extended (64-bit) SN enabled
BOOLEAN ManualSet;
} IPSEC_SAD_DATA;
typedef struct _IPSEC_SAD_ENTRY {
EFI_IPSEC_SA_ID *Id;
IPSEC_SAD_DATA *Data;
LIST_ENTRY List;
LIST_ENTRY BySpd; // Linked on IPSEC_SPD_DATA.Sas
} IPSEC_SAD_ENTRY;
struct _IPSEC_PAD_ENTRY {
EFI_IPSEC_PAD_ID *Id;
EFI_IPSEC_PAD_DATA *Data;
LIST_ENTRY List;
};
typedef struct _IPSEC_RECYCLE_CONTEXT {
EFI_IPSEC_FRAGMENT_DATA *FragmentTable;
UINT8 *PayloadBuffer;
} IPSEC_RECYCLE_CONTEXT;
struct _IPSEC_PRIVATE_DATA {
UINT32 Signature;
EFI_HANDLE Handle; // Virtual handle to install private prtocol
EFI_HANDLE ImageHandle;
EFI_IPSEC_PROTOCOL IpSec;
EFI_IPSEC_CONFIG_PROTOCOL IpSecConfig;
BOOLEAN SetBySelf;
LIST_ENTRY Udp4List;
UINTN Udp4Num;
LIST_ENTRY Udp6List;
UINTN Udp6Num;
LIST_ENTRY Ikev1SessionList;
LIST_ENTRY Ikev1EstablishedList;
LIST_ENTRY Ikev2SessionList;
LIST_ENTRY Ikev2EstablishedList;
BOOLEAN IsIPsecDisabling;
};
/**
This function processes the inbound traffic with IPsec.
It checks the received packet security property, trims the ESP/AH header, and then
returns without an IPsec protected IP Header and FragmentTable.
@param[in] IpVersion The version of IP.
@param[in, out] IpHead Points to IP header containing the ESP/AH header
to be trimed on input, and without ESP/AH header
on return.
@param[in] LastHead The Last Header in IP header on return.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@param[in, out] FragmentTable Pointer to a list of fragments in the form of IPsec
protected on input, and without IPsec protected
on return.
@param[in] FragmentCount Number of fragments.
@param[out] SpdEntry Pointer to contain the address of SPD entry on return.
@param[out] RecycleEvent Event for recycling of resources.
@retval EFI_SUCCESS The operation is successful.
@retval EFI_UNSUPPORTED If the IPSEC protocol is not supported.
**/
EFI_STATUS
IpSecProtectInboundPacket (
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
OUT IPSEC_SPD_ENTRY **SpdEntry,
OUT EFI_EVENT *RecycleEvent
);
/**
This fucntion processes the output traffic with IPsec.
It protected the sending packet by encrypting it payload and inserting ESP/AH header
in the orginal IP header, then return the IpHeader and IPsec protected Fragmentable.
@param[in] IpVersion The version of IP.
@param[in, out] IpHead Point to IP header containing the orginal IP header
to be processed on input, and inserted ESP/AH header
on return.
@param[in] LastHead The Last Header in IP header.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@param[in, out] FragmentTable Pointer to a list of fragments to be protected by
IPsec on input, and with IPsec protected
on return.
@param[in] FragmentCount Number of fragments.
@param[in] SadEntry Related SAD entry.
@param[out] RecycleEvent Event for recycling of resources.
@retval EFI_SUCCESS The operation is successful.
@retval EFI_UNSUPPORTED If the IPSEC protocol is not supported.
**/
EFI_STATUS
IpSecProtectOutboundPacket (
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
IN IPSEC_SAD_ENTRY *SadEntry,
OUT EFI_EVENT *RecycleEvent
);
/**
Check if the IP Address in the address range of AddressInfos specified.
@param[in] IpVersion The IP version.
@param[in] IpAddr Points to EFI_IP_ADDRESS to be check.
@param[in] AddressInfo A list of EFI_IP_ADDRESS_INFO that is used to check
the IP Address is matched.
@param[in] AddressCount The total numbers of the AddressInfo.
@retval TRUE If the Specified IP Address is in the range of the AddressInfos specified.
@retval FALSE If the Specified IP Address is not in the range of the AddressInfos specified.
**/
BOOLEAN
IpSecMatchIpAddress (
IN UINT8 IpVersion,
IN EFI_IP_ADDRESS *IpAddr,
IN EFI_IP_ADDRESS_INFO *AddressInfo,
IN UINT32 AddressCount
);
/**
Find a PAD entry according to remote IP address.
@param[in] IpVersion The version of IP.
@param[in] IpAddr Point to remote IP address.
@return The pointer of related PAD entry.
**/
IPSEC_PAD_ENTRY *
IpSecLookupPadEntry (
IN UINT8 IpVersion,
IN EFI_IP_ADDRESS *IpAddr
);
/**
Find the SAD through whole SAD list.
@param[in] Spi The SPI used to search the SAD entry.
@param[in] DestAddress The destination used to search the SAD entry.
@return The pointer to a certain SAD entry.
**/
IPSEC_SAD_ENTRY *
IpSecLookupSadBySpi (
IN UINT32 Spi,
IN EFI_IP_ADDRESS *DestAddress
)
;
/**
Handles IPsec packet processing for inbound and outbound IP packets.
The EFI_IPSEC_PROCESS process routine handles each inbound or outbound packet.
The behavior is that it can perform one of the following actions:
bypass the packet, discard the packet, or protect the packet.
@param[in] This Pointer to the EFI_IPSEC_PROTOCOL instance.
@param[in] NicHandle Instance of the network interface.
@param[in] IpVersion IPV4 or IPV6.
@param[in, out] IpHead Pointer to the IP Header.
@param[in] LastHead The protocol of the next layer to be processed by IPsec.
@param[in] OptionsBuffer Pointer to the options buffer.
@param[in] OptionsLength Length of the options buffer.
@param[in, out] FragmentTable Pointer to a list of fragments.
@param[in] FragmentCount Number of fragments.
@param[in] TrafficDirection Traffic direction.
@param[out] RecycleSignal Event for recycling of resources.
@retval EFI_SUCCESS The packet was bypassed and all buffers remain the same.
@retval EFI_SUCCESS The packet was protected.
@retval EFI_ACCESS_DENIED The packet was discarded.
**/
EFI_STATUS
EFIAPI
IpSecProcess (
IN EFI_IPSEC_PROTOCOL *This,
IN EFI_HANDLE NicHandle,
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer,
IN UINT32 OptionsLength,
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
IN EFI_IPSEC_TRAFFIC_DIR TrafficDirection,
OUT EFI_EVENT *RecycleSignal
);
extern EFI_DPC_PROTOCOL *mDpc;
extern EFI_IPSEC_PROTOCOL mIpSecInstance;
extern EFI_COMPONENT_NAME2_PROTOCOL gIpSecComponentName2;
extern EFI_COMPONENT_NAME_PROTOCOL gIpSecComponentName;
#endif

View File

@@ -0,0 +1,934 @@
/** @file
IPsec inbound and outbound traffic processing.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "IpSecImpl.h"
#include "IpSecDebug.h"
#include "IpSecCryptIo.h"
extern LIST_ENTRY mConfigData[IPsecConfigDataTypeMaximum];
/**
The call back function of NetbufFromExt.
@param[in] Arg The argument passed from the caller.
**/
VOID
EFIAPI
IpSecOnRecyclePacket (
IN VOID *Arg
)
{
}
/**
This is a Notification function. It is called when the related IP6_TXTOKEN_WRAP
is released.
@param[in] Event The related event.
@param[in] Context The data passed by the caller.
**/
VOID
EFIAPI
IpSecRecycleCallback (
IN EFI_EVENT Event,
IN VOID *Context
)
{
IPSEC_RECYCLE_CONTEXT *RecycleContext;
RecycleContext = (IPSEC_RECYCLE_CONTEXT *) Context;
if (RecycleContext->FragmentTable != NULL) {
FreePool (RecycleContext->FragmentTable);
}
if (RecycleContext->PayloadBuffer != NULL) {
FreePool (RecycleContext->PayloadBuffer);
}
FreePool (RecycleContext);
gBS->CloseEvent (Event);
}
/**
Calculate the extension header of IP. The return length only doesn't contain
the fixed IP header length.
@param[in] IpHead Points to an IP head to be calculated.
@param[in] LastHead Points to the last header of the IP header.
@return The length of the extension header.
**/
UINT16
IpSecGetPlainExtHeadSize (
IN VOID *IpHead,
IN UINT8 *LastHead
)
{
UINT16 Size;
Size = (UINT16) (LastHead - (UINT8 *) IpHead);
if (Size > sizeof (EFI_IP6_HEADER)) {
//
// * (LastHead+1) point the last header's length but not include the first
// 8 octers, so this formluation add 8 at the end.
//
Size = (UINT16) (Size - sizeof (EFI_IP6_HEADER) + *(LastHead + 1) + 8);
} else {
Size = 0;
}
return Size;
}
/**
Authenticate the IpSec Payload and store the result in the IcvBuffer.
@param[in] BufferToAuth The buffer to be Authenticated.
@param[in] AuthSize The size of the buffer to be Authenticated.
@param[in, out] IcvBuffer The buffer to store the ICV.
@param[in] IcvSize The size of ICV.
@param[in] Key The Key passed to the CryptLib to generate a
CRYPT_HANDLE.
@param[in] AuthAlgId The Authentication Algorithm ID.
@retval EFI_UNSUPPORTED If the AuthAlg is not in the support list.
@retval EFI_SUCCESS Authenticated the payload successfully.
@retval otherwise Authentication of the payload failed.
**/
EFI_STATUS
IpSecAuthPayload (
IN UINT8 *BufferToAuth,
IN UINTN AuthSize,
IN OUT UINT8 *IcvBuffer,
IN UINTN IcvSize,
IN VOID *Key,
IN UINT8 AuthAlgId
)
{
switch (AuthAlgId) {
case EFI_IPSEC_AALG_NONE :
case EFI_IPSEC_AALG_NULL :
return EFI_SUCCESS;
default:
return EFI_UNSUPPORTED;
}
}
/**
Verify if the Authentication payload is correct.
@param[in] EspBuffer Points to the ESP wrapped buffer.
@param[in] EspSize The size of the ESP wrapped buffer.
@param[in] SadEntry The related SAD entry to store the authentication
algorithm key.
@param[in] IcvSize The length of ICV.
@retval EFI_SUCCESS The authentication data is correct.
@retval EFI_ACCESS_DENIED The authentication data is not correct.
**/
EFI_STATUS
IpSecEspAuthVerifyPayload (
IN UINT8 *EspBuffer,
IN UINTN EspSize,
IN IPSEC_SAD_ENTRY *SadEntry,
IN UINTN *IcvSize
)
{
EFI_STATUS Status;
UINTN AuthSize;
UINT8 IcvBuffer[12];
//
// Calculate the size of authentication payload.
//
*IcvSize = IpSecGetIcvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId);
AuthSize = EspSize - *IcvSize;
//
// Calculate the icv buffer and size of the payload.
//
Status = IpSecAuthPayload (
EspBuffer,
AuthSize,
IcvBuffer,
*IcvSize,
SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Compare the calculated icv and the appended original icv.
//
if (CompareMem (EspBuffer + AuthSize, IcvBuffer, *IcvSize) == 0) {
return EFI_SUCCESS;
}
DEBUG ((DEBUG_ERROR, "Error auth verify payload\n"));
return EFI_ACCESS_DENIED;
}
/**
ESP Decrypt the payload.
@param[in, out] PayloadBuffer Pointer to the buffer containing the ESP wrapped;
to be decrypted on input, and plaintext on return. The
number of bytes of data to be decrypted is
specified by EncryptSize.
@param[in] EncryptSize The size of the PayloadBuffer as input.
@param[in] SadEntry The related SAD entry.
@param[in] IvSize The size of IV.
@param[out] PlainPayloadSize Contains the return value of decrypted size.
@param[out] PaddingSize Contains the return value of Padding size.
@param[out] NextHeader Contains the return value of the last protocol header
of the IP packet.
@retval EFI_UNSUPPORTED The Algorithm pointed to by the SAD entry is not supported.
@retval EFI_SUCCESS The operation completed successfully.
**/
EFI_STATUS
IpSecEspDecryptPayload (
IN OUT UINT8 *PayloadBuffer,
IN UINTN EncryptSize,
IN IPSEC_SAD_ENTRY *SadEntry,
IN UINTN *IvSize,
OUT UINTN *PlainPayloadSize,
OUT UINTN *PaddingSize,
OUT UINT8 *NextHeader
)
{
EFI_ESP_TAIL *EspTail;
switch (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId) {
case EFI_IPSEC_EALG_NULL:
EspTail = (EFI_ESP_TAIL *) (PayloadBuffer + EncryptSize - sizeof (EFI_ESP_TAIL));
*PaddingSize = EspTail->PaddingLength;
*NextHeader = EspTail->NextHeader;
*PlainPayloadSize = EncryptSize - EspTail->PaddingLength - sizeof (EFI_ESP_TAIL);
break;
case EFI_IPSEC_EALG_3DESCBC:
case EFI_IPSEC_EALG_AESCBC:
//
// TODO: support these algorithm
//
return EFI_UNSUPPORTED;
default :
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
/**
ESP Encrypt the payload.
@param[in, out] BufferToEncrypt Pointer to the buffer containing plaintext to be
encrypted on input, and ciphertext on return. The
number of bytes of data to be encrypted is
specified by EncryptSize.
@param[in, out] EncryptSize The size of the plaintext on input, and the size of the
ciphertext on return.
@param[in] IvBuffer Points to IV data.
@param[in] IvSize Size of IV.
@param[in] SadEntry Related SAD entry.
@retval EFI_UNSUPPORTED The Algorithm pointed by SAD entry is not supported.
@retval EFI_SUCCESS The operation completed successfully.
**/
EFI_STATUS
IpSecEspEncryptPayload (
IN OUT UINT8 *BufferToEncrypt,
IN OUT UINTN EncryptSize,
IN UINT8 *IvBuffer,
IN UINTN IvSize,
IN IPSEC_SAD_ENTRY *SadEntry
)
{
switch (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId) {
case EFI_IPSEC_EALG_NULL:
return EFI_SUCCESS;
case EFI_IPSEC_EALG_3DESCBC:
case EFI_IPSEC_EALG_AESCBC:
//
// TODO: support these algorithms
//
return EFI_UNSUPPORTED;
default :
return EFI_UNSUPPORTED;
}
}
/**
The actual entry to relative function processes the inbound traffic of ESP header.
This function is the subfunction of IpSecProtectInboundPacket(). It checks the
received packet security property and trim the ESP header and then returns without
an IPsec protected IP Header and FramgmentTable.
@param[in] IpVersion The version of IP.
@param[in, out] IpHead Points to the IP header containing the ESP header
to be trimed on input, and without ESP header
on return.
@param[out] LastHead The Last Header in IP header on return.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@param[in, out] FragmentTable Pointer to a list of fragments in the form of IPsec
protected on input, and without IPsec protected
on return.
@param[in] FragmentCount The number of fragments.
@param[out] SpdEntry Pointer to contain the address of SPD entry on return.
@param[out] RecycleEvent The event for recycling of resources.
@retval EFI_SUCCESS The operation was successful.
@retval EFI_ACCESS_DENIED One or more following conditions is TRUE:
- ESP header was not found.
- The related SAD entry was not found.
- The related SAD entry does not support the ESP protocol.
@retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.
**/
EFI_STATUS
IpSecEspInboundPacket (
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
OUT UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
OUT IPSEC_SPD_ENTRY **SpdEntry,
OUT EFI_EVENT *RecycleEvent
)
{
EFI_STATUS Status;
NET_BUF *Payload;
UINTN EspSize;
UINTN IvSize;
UINTN PlainPayloadSize;
UINTN PaddingSize;
UINTN IcvSize;
UINT8 *ProcessBuffer;
EFI_IP_ADDRESS DestIp;
EFI_ESP_HEADER *EspHeader;
EFI_ESP_TAIL *EspTail;
EFI_IPSEC_SA_ID *SaId;
IPSEC_SAD_DATA *SadData;
IPSEC_SAD_ENTRY *SadEntry;
IPSEC_RECYCLE_CONTEXT *RecycleContext;
UINT32 Spi;
UINT8 NextHeader;
UINT16 IpSecHeadSize;
Status = EFI_SUCCESS;
Payload = NULL;
ProcessBuffer = NULL;
RecycleContext = NULL;
*RecycleEvent = NULL;
PlainPayloadSize = 0;
NextHeader = 0;
//
// Build netbuf from fragment table first.
//
Payload = NetbufFromExt (
(NET_FRAGMENT *) *FragmentTable,
*FragmentCount,
0,
sizeof (EFI_ESP_HEADER),
IpSecOnRecyclePacket,
NULL
);
if (Payload == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
//
// Get the esp size and eso header from netbuf.
//
EspSize = Payload->TotalSize;
EspHeader = (EFI_ESP_HEADER *) NetbufGetByte (Payload, 0, NULL);
if (EspHeader == NULL) {
Status = EFI_ACCESS_DENIED;
goto ON_EXIT;
}
//
// Parse destination address from ip header.
//
ZeroMem (&DestIp, sizeof (EFI_IP_ADDRESS));
if (IpVersion == IP_VERSION_4) {
CopyMem (
&DestIp,
&((IP4_HEAD *) IpHead)->Dst,
sizeof (IP4_ADDR)
);
} else {
CopyMem (
&DestIp,
&((EFI_IP6_HEADER *) IpHead)->DestinationAddress,
sizeof (EFI_IPv6_ADDRESS)
);
}
//
// Lookup sad entry according to the spi and dest address.
//
Spi = NTOHL (EspHeader->Spi);
SadEntry = IpSecLookupSadBySpi (Spi, &DestIp);
if (SadEntry == NULL) {
Status = EFI_ACCESS_DENIED;
goto ON_EXIT;
}
SaId = SadEntry->Id;
SadData = SadEntry->Data;
//
// Only support esp protocol currently.
//
if (SaId->Proto != EfiIPsecESP) {
Status = EFI_ACCESS_DENIED;
goto ON_EXIT;
}
if (!SadData->ManualSet) {
//
// TODO: Check sa lifetime and sequence number
//
}
//
// Allocate buffer for decryption and authentication by esp.
//
ProcessBuffer = AllocateZeroPool (EspSize);
if (ProcessBuffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
NetbufCopy (Payload, 0, (UINT32) EspSize, ProcessBuffer);
//
// Authenticate the esp wrapped buffer by the sad entry if has auth key.
//
IcvSize = 0;
if (SadData->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {
Status = IpSecEspAuthVerifyPayload (
ProcessBuffer,
EspSize,
SadEntry,
&IcvSize
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
//
// Decrypt the payload by the sad entry if has decrypt key.
//
IvSize = 0;
if (SadData->AlgoInfo.EspAlgoInfo.EncKey != NULL) {
Status = IpSecEspDecryptPayload (
ProcessBuffer + sizeof (EFI_ESP_HEADER),
EspSize - sizeof (EFI_ESP_HEADER) - IcvSize,
SadEntry,
&IvSize,
&PlainPayloadSize,
&PaddingSize,
&NextHeader
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
} else {
EspTail = (EFI_ESP_TAIL *) (ProcessBuffer + EspSize - IcvSize - sizeof (EFI_ESP_TAIL));
PaddingSize = EspTail->PaddingLength;
NextHeader = EspTail->NextHeader;
PlainPayloadSize = EspSize - sizeof (EFI_ESP_HEADER) - IvSize - IcvSize - sizeof (EFI_ESP_TAIL) - PaddingSize;
}
//
// TODO: handle anti-replay window
//
//
// Decryption and authentication with esp has been done, so it's time to
// reload the new packet, create recycle event and fixup ip header.
//
RecycleContext = AllocateZeroPool (sizeof (IPSEC_RECYCLE_CONTEXT));
if (RecycleContext == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
IpSecRecycleCallback,
RecycleContext,
RecycleEvent
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// TODO: Who take responsible to handle the original fragment table?
//
*FragmentTable = AllocateZeroPool (sizeof (EFI_IPSEC_FRAGMENT_DATA));
if (*FragmentTable == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
RecycleContext->PayloadBuffer = ProcessBuffer;
RecycleContext->FragmentTable = *FragmentTable;
(*FragmentTable)[0].FragmentBuffer = ProcessBuffer + sizeof (EFI_ESP_HEADER) + IvSize;
(*FragmentTable)[0].FragmentLength = (UINT32) PlainPayloadSize;
*FragmentCount = 1;
//
// Update the total length field in ip header since processed by esp.
//
if (IpVersion == IP_VERSION_4) {
((IP4_HEAD *) IpHead)->TotalLen = HTONS ((UINT16) (((IP4_HEAD *) IpHead)->HeadLen + PlainPayloadSize));
} else {
IpSecHeadSize = IpSecGetPlainExtHeadSize (IpHead, LastHead);
((EFI_IP6_HEADER *) IpHead)->PayloadLength = HTONS ((UINT16)(IpSecHeadSize + PlainPayloadSize));
}
//
// Update the next layer field in ip header since esp header inserted.
//
*LastHead = NextHeader;
//
// Update the spd association of the sad entry.
//
*SpdEntry = SadData->SpdEntry;
ON_EXIT:
if (Payload != NULL) {
NetbufFree (Payload);
}
if (EFI_ERROR (Status)) {
if (ProcessBuffer != NULL) {
FreePool (ProcessBuffer);
}
if (RecycleContext != NULL) {
FreePool (RecycleContext);
}
if (*RecycleEvent != NULL) {
gBS->CloseEvent (*RecycleEvent);
}
}
return Status;
}
/**
The actual entry to the relative function processes the output traffic using the ESP protocol.
This function is the subfunction of IpSecProtectOutboundPacket(). It protected
the sending packet by encrypting its payload and inserting ESP header in the orginal
IP header, then return the IpHeader and IPsec protected Fragmentable.
@param[in] IpVersion The version of IP.
@param[in, out] IpHead Points to IP header containing the orginal IP header
to be processed on input, and inserted ESP header
on return.
@param[in] LastHead The Last Header in IP header.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@param[in, out] FragmentTable Pointer to a list of fragments to be protected by
IPsec on input, and with IPsec protected
on return.
@param[in] FragmentCount The number of fragments.
@param[in] SadEntry The related SAD entry.
@param[out] RecycleEvent The event for recycling of resources.
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES The required system resources can't be allocated.
**/
EFI_STATUS
IpSecEspOutboundPacket (
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
IN IPSEC_SAD_ENTRY *SadEntry,
OUT EFI_EVENT *RecycleEvent
)
{
EFI_STATUS Status;
UINTN Index;
EFI_IPSEC_SA_ID *SaId;
IPSEC_SAD_DATA *SadData;
IPSEC_RECYCLE_CONTEXT *RecycleContext;
UINT8 *ProcessBuffer;
UINTN BytesCopied;
INTN EncryptBlockSize;// Size of encryption block, 4 bytes aligned and >= 4
UINTN EspSize; // Total size of esp wrapped ip payload
UINTN IvSize; // Size of IV, optional, might be 0
UINTN PlainPayloadSize;// Original IP payload size
UINTN PaddingSize; // Size of padding
UINTN EncryptSize; // Size of data to be encrypted, start after IV and
// stop before ICV
UINTN IcvSize; // Size of ICV, optional, might be 0
UINT8 *RestOfPayload; // Start of Payload after IV
UINT8 *Padding; // Start address of padding
EFI_ESP_HEADER *EspHeader; // Start address of ESP frame
EFI_ESP_TAIL *EspTail; // Address behind padding
Status = EFI_ACCESS_DENIED;
SaId = SadEntry->Id;
SadData = SadEntry->Data;
ProcessBuffer = NULL;
RecycleContext = NULL;
*RecycleEvent = NULL;
if (!SadData->ManualSet &&
SadData->AlgoInfo.EspAlgoInfo.EncKey == NULL &&
SadData->AlgoInfo.EspAlgoInfo.AuthKey == NULL
) {
//
// Invalid manual sad entry configuration.
//
goto ON_EXIT;
}
//
// Calculate enctrypt block size, need iv by default and 4 bytes alignment.
//
EncryptBlockSize = 4;
if (SadData->AlgoInfo.EspAlgoInfo.EncKey != NULL) {
EncryptBlockSize = IpSecGetEncryptBlockSize (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId);
if (EncryptBlockSize < 0 || (EncryptBlockSize != 1 && EncryptBlockSize % 4 != 0)) {
goto ON_EXIT;
}
}
//
// Calculate the plain payload size accroding to the fragment table.
//
PlainPayloadSize = 0;
for (Index = 0; Index < *FragmentCount; Index++) {
PlainPayloadSize += (*FragmentTable)[Index].FragmentLength;
}
//
// Calculate icv size, optional by default and 4 bytes alignment.
//
IcvSize = 0;
if (SadData->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {
IcvSize = IpSecGetIcvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId);
if (IcvSize % 4 != 0) {
goto ON_EXIT;
}
}
//
// Calcuate the total size of esp wrapped ip payload.
//
IvSize = IpSecGetEncryptIvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId);
EncryptSize = (PlainPayloadSize + sizeof (EFI_ESP_TAIL) + EncryptBlockSize - 1) / EncryptBlockSize * EncryptBlockSize;
PaddingSize = EncryptSize - PlainPayloadSize - sizeof (EFI_ESP_TAIL);
EspSize = sizeof (EFI_ESP_HEADER) + IvSize + EncryptSize + IcvSize;
ProcessBuffer = AllocateZeroPool (EspSize);
if (ProcessBuffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
//
// Calculate esp header and esp tail including header, payload and padding.
//
EspHeader = (EFI_ESP_HEADER *) ProcessBuffer;
RestOfPayload = (UINT8 *) (EspHeader + 1) + IvSize;
Padding = RestOfPayload + PlainPayloadSize;
EspTail = (EFI_ESP_TAIL *) (Padding + PaddingSize);
//
// Fill the sn and spi fields in esp header.
//
EspHeader->SequenceNumber = HTONL ((UINT32) SadData->SequenceNumber + 1);
EspHeader->Spi = HTONL (SaId->Spi);
//
// Copy the rest of payload (after iv) from the original fragment buffer.
//
BytesCopied = 0;
for (Index = 0; Index < *FragmentCount; Index++) {
CopyMem (
(RestOfPayload + BytesCopied),
(*FragmentTable)[Index].FragmentBuffer,
(*FragmentTable)[Index].FragmentLength
);
BytesCopied += (*FragmentTable)[Index].FragmentLength;
}
//
// Fill the padding buffer by natural number sequence.
//
for (Index = 0; Index < PaddingSize; Index++) {
Padding[Index] = (UINT8) (Index + 1);
}
//
// Fill the padding length and next header fields in esp tail.
//
EspTail->PaddingLength = (UINT8) PaddingSize;
EspTail->NextHeader = *LastHead;
//
// Generate iv at random by crypt library.
//
Status = IpSecGenerateIv (
(UINT8 *) (EspHeader + 1),
IvSize
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// Encrypt the payload (after iv) by the sad entry if has encrypt key.
//
if (SadData->AlgoInfo.EspAlgoInfo.EncKey != NULL) {
Status = IpSecEspEncryptPayload (
RestOfPayload,
EncryptSize,
(UINT8 *) (EspHeader + 1),
IvSize,
SadEntry
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
//
// Authenticate the esp wrapped buffer by the sad entry if has auth key.
//
if (SadData->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {
Status = IpSecAuthPayload (
ProcessBuffer,
EspSize - IcvSize,
ProcessBuffer + EspSize - IcvSize,
IcvSize,
SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
//
// Encryption and authentication with esp has been done, so it's time to
// reload the new packet, create recycle event and fixup ip header.
//
RecycleContext = AllocateZeroPool (sizeof (IPSEC_RECYCLE_CONTEXT));
if (RecycleContext == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
IpSecRecycleCallback,
RecycleContext,
RecycleEvent
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// TODO: Who take responsible to handle the original fragment table?
//
*FragmentTable = AllocateZeroPool (sizeof (EFI_IPSEC_FRAGMENT_DATA));
if (*FragmentTable == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
RecycleContext->FragmentTable = *FragmentTable;
RecycleContext->PayloadBuffer = ProcessBuffer;
(*FragmentTable)[0].FragmentBuffer = ProcessBuffer;
(*FragmentTable)[0].FragmentLength = (UINT32) EspSize;
*FragmentCount = 1;
//
// Update the total length field in ip header since processed by esp.
//
if (IpVersion == IP_VERSION_4) {
((IP4_HEAD *) IpHead)->TotalLen = HTONS ((UINT16) (((IP4_HEAD *) IpHead)->HeadLen + EspSize));
} else {
((EFI_IP6_HEADER *) IpHead)->PayloadLength = (UINT16) (IpSecGetPlainExtHeadSize (IpHead, LastHead) + EspSize);
}
//
// Update the next layer field in ip header since esp header inserted.
//
*LastHead = IPSEC_ESP_PROTOCOL;
//
// Increase the sn number in sad entry according to rfc4303.
//
SadData->SequenceNumber++;
ON_EXIT:
if (EFI_ERROR (Status)) {
if (ProcessBuffer != NULL) {
FreePool (ProcessBuffer);
}
if (RecycleContext != NULL) {
FreePool (RecycleContext);
}
if (*RecycleEvent != NULL) {
gBS->CloseEvent (*RecycleEvent);
}
}
return Status;
}
/**
This function processes the inbound traffic with IPsec.
It checks the received packet security property, trims the ESP/AH header, and then
returns without an IPsec protected IP Header and FragmentTable.
@param[in] IpVersion The version of IP.
@param[in, out] IpHead Points to IP header containing the ESP/AH header
to be trimed on input, and without ESP/AH header
on return.
@param[in] LastHead The Last Header in IP header on return.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@param[in, out] FragmentTable Pointer to a list of fragments in form of IPsec
protected on input, and without IPsec protected
on return.
@param[in] FragmentCount The number of fragments.
@param[out] SpdEntry Pointer to contain the address of SPD entry on return.
@param[out] RecycleEvent The event for recycling of resources.
@retval EFI_SUCCESS The operation was successful.
@retval EFI_UNSUPPORTED The IPSEC protocol is not supported.
**/
EFI_STATUS
IpSecProtectInboundPacket (
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
OUT IPSEC_SPD_ENTRY **SpdEntry,
OUT EFI_EVENT *RecycleEvent
)
{
if (*LastHead == IPSEC_ESP_PROTOCOL) {
//
// Process the esp ipsec header of the inbound traffic.
//
return IpSecEspInboundPacket (
IpVersion,
IpHead,
LastHead,
OptionsBuffer,
OptionsLength,
FragmentTable,
FragmentCount,
SpdEntry,
RecycleEvent
);
}
//
// The other protocols are not supported.
//
return EFI_UNSUPPORTED;
}
/**
This function processes the output traffic with IPsec.
It protected the sending packet by encrypting it payload and inserting ESP/AH header
in the orginal IP header, then returns the IpHeader and IPsec protected Fragmentable.
@param[in] IpVersion The version of IP.
@param[in, out] IpHead Points to IP header containing the orginal IP header
to be processed on input, and inserted ESP/AH header
on return.
@param[in] LastHead The Last Header in the IP header.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@param[in, out] FragmentTable Pointer to a list of fragments to be protected by
IPsec on input, and with IPsec protected
on return.
@param[in] FragmentCount The number of fragments.
@param[in] SadEntry The related SAD entry.
@param[out] RecycleEvent The event for recycling of resources.
@retval EFI_SUCCESS The operation was successful.
@retval EFI_UNSUPPORTED If the IPSEC protocol is not supported.
**/
EFI_STATUS
IpSecProtectOutboundPacket (
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
IN IPSEC_SAD_ENTRY *SadEntry,
OUT EFI_EVENT *RecycleEvent
)
{
if (SadEntry->Id->Proto == EfiIPsecESP) {
//
// Process the esp ipsec header of the outbound traffic.
//
return IpSecEspOutboundPacket (
IpVersion,
IpHead,
LastHead,
OptionsBuffer,
OptionsLength,
FragmentTable,
FragmentCount,
SadEntry,
RecycleEvent
);
}
//
// The other protocols are not supported.
//
return EFI_UNSUPPORTED;
}

View File

@@ -0,0 +1,308 @@
/** @file
UEFI Component Name(2) protocol implementation for Mtftp6 driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Mtftp6Impl.h"
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Mtftp6ComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is being managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for bus drivers
attempting to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that attempts to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Mtftp6ComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI Component Name Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gMtftp6ComponentName = {
Mtftp6ComponentNameGetDriverName,
Mtftp6ComponentNameGetControllerName,
"eng"
};
//
// EFI Component Name 2 Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gMtftp6ComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Mtftp6ComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Mtftp6ComponentNameGetControllerName,
"en"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mMtftp6DriverNameTable[] = {
{
"eng;en",
L"MTFTP6 Network Service Driver"
},
{
NULL,
NULL
}
};
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Mtftp6ComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mMtftp6DriverNameTable,
DriverName,
(BOOLEAN)(This == &gMtftp6ComponentName)
);
}
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is being managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
attempting to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that attempts to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
Mtftp6ComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
return EFI_UNSUPPORTED;
}

View File

@@ -0,0 +1,703 @@
/** @file
Driver Binding functions and Service Binding functions
implementation for Mtftp6 Driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Mtftp6Impl.h"
EFI_DRIVER_BINDING_PROTOCOL gMtftp6DriverBinding = {
Mtftp6DriverBindingSupported,
Mtftp6DriverBindingStart,
Mtftp6DriverBindingStop,
0xa,
NULL,
NULL
};
EFI_SERVICE_BINDING_PROTOCOL gMtftp6ServiceBindingTemplate = {
Mtftp6ServiceBindingCreateChild,
Mtftp6ServiceBindingDestroyChild
};
/**
Destory the MTFTP6 service. The MTFTP6 service may be partly initialized,
or partly destroyed. If a resource is destroyed, it is marked as such in
case the destroy failed and is called again later.
@param[in] Service The MTFTP6 service to be destroyed.
**/
VOID
Mtftp6DestroyService (
IN MTFTP6_SERVICE *Service
)
{
//
// Make sure all children instances have been already destoryed.
//
ASSERT (Service->ChildrenNum == 0);
if (Service->DummyUdpIo != NULL) {
UdpIoFreeIo (Service->DummyUdpIo);
}
if (Service->Timer != NULL) {
gBS->CloseEvent (Service->Timer);
}
FreePool (Service);
}
/**
Create then initialize a MTFTP6 service binding instance.
@param[in] Controller The controller to install the MTFTP6 service
binding on.
@param[in] Image The driver binding image of the MTFTP6 driver.
@param[out] Service The variable to receive the created service
binding instance.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources to create the instance
@retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep connection with UDP.
@retval EFI_SUCCESS The service instance is created for the controller.
**/
EFI_STATUS
Mtftp6CreateService (
IN EFI_HANDLE Controller,
IN EFI_HANDLE Image,
OUT MTFTP6_SERVICE **Service
)
{
MTFTP6_SERVICE *Mtftp6Srv;
EFI_STATUS Status;
ASSERT (Service != NULL);
*Service = NULL;
Mtftp6Srv = AllocateZeroPool (sizeof (MTFTP6_SERVICE));
if (Mtftp6Srv == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Mtftp6Srv->Signature = MTFTP6_SERVICE_SIGNATURE;
Mtftp6Srv->Controller = Controller;
Mtftp6Srv->Image = Image;
Mtftp6Srv->InDestory = FALSE;
Mtftp6Srv->ChildrenNum = 0;
CopyMem (
&Mtftp6Srv->ServiceBinding,
&gMtftp6ServiceBindingTemplate,
sizeof (EFI_SERVICE_BINDING_PROTOCOL)
);
InitializeListHead (&Mtftp6Srv->Children);
//
// Create a internal timer for all instances.
//
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL | EVT_TIMER,
TPL_CALLBACK,
Mtftp6OnTimerTick,
Mtftp6Srv,
&Mtftp6Srv->Timer
);
if (EFI_ERROR (Status)) {
FreePool (Mtftp6Srv);
return Status;
}
//
// Create a dummy Udp6Io to build parent-child relationship between Udp6 driver
// and Mtftp6 driver.
//
Mtftp6Srv->DummyUdpIo = UdpIoCreateIo (
Controller,
Image,
Mtftp6ConfigDummyUdpIo,
UDP_IO_UDP6_VERSION,
NULL
);
if (Mtftp6Srv->DummyUdpIo == NULL) {
gBS->CloseEvent (Mtftp6Srv->Timer);
FreePool (Mtftp6Srv);
return EFI_DEVICE_ERROR;
}
*Service = Mtftp6Srv;
return EFI_SUCCESS;
}
/**
Destroy the MTFTP6 instance and recycle the resources.
@param[in] Instance The pointer to the MTFTP6 instance.
**/
VOID
Mtftp6DestroyInstance (
IN MTFTP6_INSTANCE *Instance
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *Next;
MTFTP6_BLOCK_RANGE *Block;
if (Instance->Config != NULL) {
FreePool (Instance->Config);
}
if (Instance->Token != NULL && Instance->Token->Event != NULL) {
gBS->SignalEvent (Instance->Token->Event);
}
if (Instance->LastPacket != NULL) {
NetbufFree (Instance->LastPacket);
}
if (Instance->UdpIo!= NULL) {
UdpIoFreeIo (Instance->UdpIo);
}
if (Instance->McastUdpIo != NULL) {
UdpIoFreeIo (Instance->McastUdpIo);
}
NET_LIST_FOR_EACH_SAFE (Entry, Next, &Instance->BlkList) {
Block = NET_LIST_USER_STRUCT (Entry, MTFTP6_BLOCK_RANGE, Link);
RemoveEntryList (Entry);
FreePool (Block);
}
FreePool (Instance);
}
/**
Create the MTFTP6 instance and initialize it.
@param[in] Service The pointer to the MTFTP6 service.
@param[out] Instance The pointer to the MTFTP6 instance.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
@retval EFI_SUCCESS The MTFTP6 instance is created.
**/
EFI_STATUS
Mtftp6CreateInstance (
IN MTFTP6_SERVICE *Service,
OUT MTFTP6_INSTANCE **Instance
)
{
MTFTP6_INSTANCE *Mtftp6Ins;
*Instance = NULL;
Mtftp6Ins = AllocateZeroPool (sizeof (MTFTP6_INSTANCE));
if (Mtftp6Ins == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Mtftp6Ins->Signature = MTFTP6_INSTANCE_SIGNATURE;
Mtftp6Ins->InDestory = FALSE;
Mtftp6Ins->Service = Service;
CopyMem (
&Mtftp6Ins->Mtftp6,
&gMtftp6ProtocolTemplate,
sizeof (EFI_MTFTP6_PROTOCOL)
);
InitializeListHead (&Mtftp6Ins->Link);
InitializeListHead (&Mtftp6Ins->BlkList);
*Instance = Mtftp6Ins;
return EFI_SUCCESS;
}
/**
This is the declaration of an EFI image entry point. This entry point is
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
both device drivers and bus drivers.
Entry point of the MTFTP6 driver to install various protocols.
@param[in] ImageHandle The firmware allocated handle for the UEFI image.
@param[in] SystemTable The pointer to the EFI System Table.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
**/
EFI_STATUS
EFIAPI
Mtftp6DriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gMtftp6DriverBinding,
ImageHandle,
&gMtftp6ComponentName,
&gMtftp6ComponentName2
);
}
/**
Test to see if this driver supports ControllerHandle. This service
is called by the EFI boot service ConnectController(). In
order to make drivers as small as possible, there are calling
restrictions for this service. ConnectController() must
follow these calling restrictions. If any other agent wishes to call
Supported(), it must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to test
@param[in] RemainingDevicePath Optional parameter use to pick a specific child.
device to start.
@retval EFI_SUCCESS This driver supports this device.
@retval Others This driver does not support this device.
**/
EFI_STATUS
EFIAPI
Mtftp6DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
return gBS->OpenProtocol (
Controller,
&gEfiUdp6ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
}
/**
Start this driver on ControllerHandle. This service is called by the
EFI boot service ConnectController(). In order to make
drivers as small as possible, there are calling restrictions for
this service. ConnectController() must follow these
calling restrictions. If any other agent wishes to call Start() it
must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to bind driver to.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to start.
@retval EFI_SUCCESS This driver is added to ControllerHandle.
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
@retval Others This driver does not support this device.
**/
EFI_STATUS
EFIAPI
Mtftp6DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
MTFTP6_SERVICE *Service;
EFI_STATUS Status;
//
// Directly return if driver is already running on this Nic handle.
//
Status = gBS->OpenProtocol (
Controller,
&gEfiMtftp6ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (!EFI_ERROR (Status)) {
return EFI_ALREADY_STARTED;
}
//
// Create Mtftp6 service for this Nic handle
//
Status = Mtftp6CreateService (
Controller,
This->DriverBindingHandle,
&Service
);
if (EFI_ERROR (Status)) {
return Status;
}
ASSERT (Service != NULL);
//
// Start the internal timer to track the packet retransmission.
//
Status = gBS->SetTimer (
Service->Timer,
TimerPeriodic,
TICKS_PER_SECOND
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Install the Mtftp6 service on the Nic handle.
//
Status = gBS->InstallMultipleProtocolInterfaces (
&Controller,
&gEfiMtftp6ServiceBindingProtocolGuid,
&Service->ServiceBinding,
NULL
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
return EFI_SUCCESS;
ON_ERROR:
Mtftp6DestroyService (Service);
return Status;
}
/**
Stop this driver on ControllerHandle. This service is called by the
EFI boot service DisconnectController(). In order to
make drivers as small as possible, there are a few calling
restrictions for this service. DisconnectController()
must follow these calling restrictions. If any other agent wishes
to call Stop() it must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to stop driver on
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
children is zero, stop the entire bus driver.
@param[in] ChildHandleBuffer List of Child Handles to Stop.
@retval EFI_SUCCESS This driver is removed ControllerHandle.
@retval EFI_DEVICE_ERROR An unexpected error.
@retval Others This driver was not removed from this device.
**/
EFI_STATUS
EFIAPI
Mtftp6DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
MTFTP6_SERVICE *Service;
MTFTP6_INSTANCE *Instance;
EFI_HANDLE NicHandle;
EFI_STATUS Status;
EFI_TPL OldTpl;
//
// Locate the Nic handle to retrieve the Mtftp6 private data.
//
NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp6ProtocolGuid);
if (NicHandle == NULL) {
return EFI_DEVICE_ERROR;
}
Status = gBS->OpenProtocol (
NicHandle,
&gEfiMtftp6ServiceBindingProtocolGuid,
(VOID **) &ServiceBinding,
This->DriverBindingHandle,
NicHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Service = MTFTP6_SERVICE_FROM_THIS (ServiceBinding);
if (Service->InDestory) {
return EFI_SUCCESS;
}
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
if (NumberOfChildren == 0) {
//
// Destory the Mtftp6 service if there is no Mtftp6 child instance left.
//
Service->InDestory = TRUE;
gBS->UninstallProtocolInterface (
NicHandle,
&gEfiMtftp6ServiceBindingProtocolGuid,
ServiceBinding
);
Mtftp6DestroyService (Service);
} else {
//
// Destory the Mtftp6 child instance one by one.
//
while (!IsListEmpty (&Service->Children)) {
Instance = NET_LIST_HEAD (&Service->Children, MTFTP6_INSTANCE, Link);
Mtftp6ServiceBindingDestroyChild (ServiceBinding, Instance->Handle);
}
if (Service->ChildrenNum != 0) {
Status = EFI_DEVICE_ERROR;
}
}
gBS->RestoreTPL (OldTpl);
return Status;
}
/**
Creates a child handle and installs a protocol.
The CreateChild() function installs a protocol on ChildHandle.
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param[in, out] ChildHandle Pointer to the handle of the child to create. If it is NULL,
then a new handle is created. If it is a pointer to an existing
UEFI handle, then the protocol is added to the existing UEFI handle.
@retval EFI_SUCCES The protocol was added to ChildHandle.
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
@retval Others The child handle was not created.
**/
EFI_STATUS
EFIAPI
Mtftp6ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN OUT EFI_HANDLE *ChildHandle
)
{
MTFTP6_SERVICE *Service;
MTFTP6_INSTANCE *Instance;
EFI_STATUS Status;
EFI_TPL OldTpl;
VOID *Udp6;
if (This == NULL || ChildHandle == NULL) {
return EFI_INVALID_PARAMETER;
}
Service = MTFTP6_SERVICE_FROM_THIS (This);
Status = Mtftp6CreateInstance (Service, &Instance);
if (EFI_ERROR (Status)) {
return Status;
}
ASSERT (Instance != NULL);
//
// Install the Mtftp6 protocol on the new child handle.
//
Status = gBS->InstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiMtftp6ProtocolGuid,
&Instance->Mtftp6,
NULL
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Instance->Handle = *ChildHandle;
//
// Open the Udp6 protocol by child.
//
Status = gBS->OpenProtocol (
Service->DummyUdpIo->UdpHandle,
&gEfiUdp6ProtocolGuid,
(VOID **) &Udp6,
gMtftp6DriverBinding.DriverBindingHandle,
Instance->Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
gBS->UninstallMultipleProtocolInterfaces (
Instance->Handle,
&gEfiMtftp6ProtocolGuid,
&Instance->Mtftp6,
NULL
);
goto ON_ERROR;
}
//
// Add the new Mtftp6 instance into the children list of Mtftp6 service.
//
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
InsertTailList (&Service->Children, &Instance->Link);
Service->ChildrenNum++;
gBS->RestoreTPL (OldTpl);
return EFI_SUCCESS;
ON_ERROR:
Mtftp6DestroyInstance (Instance);
return Status;
}
/**
Destroys a child handle with a protocol installed on it.
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
last protocol on ChildHandle, then ChildHandle is destroyed.
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param[in] ChildHandle Handle of the child to destroy.
@retval EFI_SUCCES The protocol was removed from ChildHandle.
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
@retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
@retval Others The child handle was not destroyed
**/
EFI_STATUS
EFIAPI
Mtftp6ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
)
{
MTFTP6_SERVICE *Service;
MTFTP6_INSTANCE *Instance;
EFI_MTFTP6_PROTOCOL *Mtftp6;
EFI_STATUS Status;
EFI_TPL OldTpl;
if (This == NULL || ChildHandle == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Locate the Nic handle to retrieve the Mtftp6 private data.
//
Status = gBS->OpenProtocol (
ChildHandle,
&gEfiMtftp6ProtocolGuid,
(VOID **) &Mtftp6,
gMtftp6DriverBinding.DriverBindingHandle,
ChildHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
Instance = MTFTP6_INSTANCE_FROM_THIS (Mtftp6);
Service = MTFTP6_SERVICE_FROM_THIS (This);
if (Instance->Service != Service) {
return EFI_INVALID_PARAMETER;
}
//
// Check whether the instance already in destory state.
//
if (Instance->InDestory) {
return EFI_SUCCESS;
}
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
Instance->InDestory = TRUE;
gBS->CloseProtocol (
Service->DummyUdpIo->UdpHandle,
&gEfiUdp6ProtocolGuid,
gMtftp6DriverBinding.DriverBindingHandle,
ChildHandle
);
//
// Uninstall the MTFTP6 protocol first to enable a top down destruction.
//
Status = gBS->UninstallProtocolInterface (
ChildHandle,
&gEfiMtftp6ProtocolGuid,
Mtftp6
);
if (EFI_ERROR (Status)) {
Instance->InDestory = FALSE;
gBS->RestoreTPL (OldTpl);
return Status;
}
//
// Remove the Mtftp6 instance from the children list of Mtftp6 service.
//
RemoveEntryList (&Instance->Link);
Service->ChildrenNum --;
Mtftp6DestroyInstance (Instance);
gBS->RestoreTPL (OldTpl);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,151 @@
/** @file
Driver Binding functions and Service Binding functions
declaration for Mtftp6 Driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_MTFTP6_DRIVER_H__
#define __EFI_MTFTP6_DRIVER_H__
#include <Protocol/ServiceBinding.h>
extern EFI_COMPONENT_NAME_PROTOCOL gMtftp6ComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gMtftp6ComponentName2;
/**
Test to see if this driver supports ControllerHandle. This service
is called by the EFI boot service ConnectController(). In
order to make drivers as small as possible, there are a few calling
restrictions for this service. ConnectController() must
follow these calling restrictions. If any other agent wishes to call
Supported(), it must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to test.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to start.
@retval EFI_SUCCESS This driver supports this device.
@retval Others This driver does not support this device.
**/
EFI_STATUS
EFIAPI
Mtftp6DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
/**
Start this driver on ControllerHandle. This service is called by the
EFI boot service ConnectController(). In order to make
drivers as small as possible, there are calling restrictions for
this service. ConnectController() must follow these
calling restrictions. If any other agent wishes to call Start() it
must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to bind driver to.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to start.
@retval EFI_SUCCESS This driver is added to ControllerHandle.
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
@retval Others This driver does not support this device.
**/
EFI_STATUS
EFIAPI
Mtftp6DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
/**
Stop this driver on ControllerHandle. This service is called by the
EFI boot service DisconnectController(). In order to
make drivers as small as possible, there are calling
restrictions for this service. DisconnectController()
must follow these calling restrictions. If any other agent wishes
to call Stop(), it must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to stop driver on
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
children is zero, stop the entire bus driver.
@param[in] ChildHandleBuffer List of Child Handles to Stop.
@retval EFI_SUCCESS This driver is removed ControllerHandle.
@retval EFI_DEVICE_ERROR An unexpected error.
@retval Others This driver was not removed from this device.
**/
EFI_STATUS
EFIAPI
Mtftp6DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
/**
Creates a child handle and installs a protocol.
The CreateChild() function installs a protocol on ChildHandle.
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param[in, out] ChildHandle Pointer to the handle of the child to create. If it is NULL,
then a new handle is created. If it is a pointer to an existing
UEFI handle, then the protocol is added to the existing UEFI handle.
@retval EFI_SUCCES The protocol was added to ChildHandle.
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
@retval Others The child handle was not created.
**/
EFI_STATUS
EFIAPI
Mtftp6ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN OUT EFI_HANDLE *ChildHandle
);
/**
Destroys a child handle with a protocol installed on it.
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
last protocol on ChildHandle, then ChildHandle is destroyed.
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param[in] ChildHandle Handle of the child to destroy.
@retval EFI_SUCCES The protocol was removed from ChildHandle.
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
@retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
@retval Others The child handle was not destroyed
**/
EFI_STATUS
EFIAPI
Mtftp6ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
);
#endif

View File

@@ -0,0 +1,69 @@
## @file
# Component description file for Mtftp6 module.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = Mtftp6Dxe
FILE_GUID = 99F03B99-98D8-49dd-A8D3-3219D0FFE41E
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = Mtftp6DriverEntryPoint
UNLOAD_IMAGE = NetLibDefaultUnload
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
# DRIVER_BINDING = gMtftp6DriverBinding
# COMPONENT_NAME = gMtftp6ComponentName
# COMPONENT_NAME2 = gMtftp6ComponentName2
#
[Sources]
Mtftp6Driver.c
Mtftp6Driver.h
Mtftp6Impl.c
Mtftp6Impl.h
Mtftp6Option.c
Mtftp6Option.h
Mtftp6Support.h
Mtftp6Support.c
Mtftp6Rrq.c
Mtftp6Wrq.c
ComponentName.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiLib
BaseLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
UefiDriverEntryPoint
DebugLib
NetLib
UdpIoLib
[Protocols]
gEfiUdp6ServiceBindingProtocolGuid
gEfiUdp6ProtocolGuid
gEfiMtftp6ServiceBindingProtocolGuid
gEfiMtftp6ProtocolGuid

View File

@@ -0,0 +1,634 @@
/** @file
This EFI_MTFTP6_PROTOCOL interface implementation.
It supports the following RFCs:
RFC1350 - THE TFTP PROTOCOL (REVISION 2)
RFC2090 - TFTP Multicast Option
RFC2347 - TFTP Option Extension
RFC2348 - TFTP Blocksize Option
RFC2349 - TFTP Timeout Interval and Transfer Size Options
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Mtftp6Impl.h"
EFI_MTFTP6_PROTOCOL gMtftp6ProtocolTemplate = {
EfiMtftp6GetModeData,
EfiMtftp6Configure,
EfiMtftp6GetInfo,
EfiMtftp6ParseOptions,
EfiMtftp6ReadFile,
EfiMtftp6WriteFile,
EfiMtftp6ReadDirectory,
EfiMtftp6Poll
};
/**
Returns the current operating mode data for the MTFTP6 instance.
The GetModeData() function returns the current operating mode and
cached data packet for the MTFTP6 instance.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[out] ModeData The buffer in which the EFI MTFTPv6 Protocol driver mode
data is returned.
@retval EFI_SUCCESS The configuration data was returned successfully.
@retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.
@retval EFI_INVALID_PARAMETER This is NULL or ModeData is NULL.
**/
EFI_STATUS
EFIAPI
EfiMtftp6GetModeData (
IN EFI_MTFTP6_PROTOCOL *This,
OUT EFI_MTFTP6_MODE_DATA *ModeData
)
{
MTFTP6_INSTANCE *Instance;
EFI_TPL OldTpl;
if (This == NULL || ModeData == NULL) {
return EFI_INVALID_PARAMETER;
}
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
Instance = MTFTP6_INSTANCE_FROM_THIS (This);
//
// Copy back the configure data if the instance already configured.
//
if (Instance->Config != NULL) {
CopyMem (
&ModeData->ConfigData,
Instance->Config,
sizeof (EFI_MTFTP6_CONFIG_DATA)
);
} else {
ZeroMem (
&ModeData->ConfigData,
sizeof (EFI_MTFTP6_CONFIG_DATA)
);
}
//
// Set the current support options in mode data.
//
ModeData->SupportedOptionCount = MTFTP6_SUPPORTED_OPTIONS_NUM;
ModeData->SupportedOptions = (UINT8 **) mMtftp6SupportedOptions;
gBS->RestoreTPL (OldTpl);
return EFI_SUCCESS;
}
/**
Initializes, changes, or resets the default operational setting for
this EFI MTFTPv6 Protocol driver instance.
The Configure() function is used to set and change the configuration
data for this EFI MTFTPv6 Protocol driver instance. The configuration
data can be reset to startup defaults by calling Configure() with
MtftpConfigData set to NULL. Whenever the instance is reset, any
pending operation is aborted. By changing the EFI MTFTPv6 Protocol
driver instance configuration data, the client can connect to
different MTFTPv6 servers. The configuration parameters in
MtftpConfigData are used as the default parameters in later MTFTPv6
operations and can be overridden in later operations.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] MtftpConfigData Pointer to the configuration data structure.
@retval EFI_SUCCESS The EFI MTFTPv6 Protocol instance was configured successfully.
@retval EFI_INVALID_PARAMETER One or more following conditions are TRUE:
- This is NULL.
- MtftpConfigData.StationIp is neither zero nor one
of the configured IP addresses in the underlying IPv6 driver.
- MtftpCofigData.ServerIp is not a valid IPv6 unicast address.
Note: It does not match the UEFI 2.3 Specification.
@retval EFI_ACCESS_DENIED - The configuration could not be changed at this time because there
is some MTFTP background operation in progress.
- MtftpCofigData.LocalPort is already in use.
Note: It does not match the UEFI 2.3 Specification.
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
address for this instance, but no source address was available for use.
@retval EFI_OUT_OF_RESOURCES The EFI MTFTPv6 Protocol driver instance data could not be
allocated.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI
MTFTPv6 Protocol driver instance is not configured.
Note: It is not defined in the UEFI 2.3 Specification.
**/
EFI_STATUS
EFIAPI
EfiMtftp6Configure (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_CONFIG_DATA *MtftpConfigData OPTIONAL
)
{
MTFTP6_SERVICE *Service;
MTFTP6_INSTANCE *Instance;
EFI_UDP6_PROTOCOL *Udp6;
EFI_UDP6_CONFIG_DATA Udp6Cfg;
EFI_STATUS Status;
EFI_TPL OldTpl;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
if (MtftpConfigData != NULL && !NetIp6IsValidUnicast (&MtftpConfigData->ServerIp)) {
return EFI_INVALID_PARAMETER;
}
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
Instance = MTFTP6_INSTANCE_FROM_THIS (This);
Service = Instance->Service;
Status = EFI_SUCCESS;
if (MtftpConfigData == NULL) {
//
// Configure the instance as NULL to abort the current session.
//
Mtftp6OperationClean (Instance, EFI_ABORTED);
FreePool (Instance->Config);
Instance->Config = NULL;
} else {
//
// It's not allowed to configure one instance twice without configure null.
//
if (Instance->Config != NULL) {
Status = EFI_ACCESS_DENIED;
goto ON_EXIT;
}
//
// Allocate the configure buffer of the instance and store the user's data.
//
Instance->Config = AllocateZeroPool (sizeof (EFI_MTFTP6_CONFIG_DATA));
if (Instance->Config == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
CopyMem (Instance->Config, MtftpConfigData, sizeof (EFI_MTFTP6_CONFIG_DATA));
//
// Don't configure the udpio here because each operation might override
// the configuration, so delay udpio configuration in each operation.
//
Instance->UdpIo = UdpIoCreateIo (
Service->Controller,
Service->Image,
Mtftp6ConfigDummyUdpIo,
UDP_IO_UDP6_VERSION,
NULL
);
if (Instance->UdpIo == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
//
// Continue to configure the downside Udp6 instance by user's data.
//
ZeroMem (&Udp6Cfg, sizeof (EFI_UDP6_CONFIG_DATA));
Udp6Cfg.AcceptPromiscuous = FALSE;
Udp6Cfg.AcceptAnyPort = FALSE;
Udp6Cfg.AllowDuplicatePort = FALSE;
Udp6Cfg.TrafficClass = 0;
Udp6Cfg.HopLimit = 128;
Udp6Cfg.ReceiveTimeout = 0;
Udp6Cfg.TransmitTimeout = 0;
Udp6Cfg.StationPort = Instance->Config->LocalPort;
Udp6Cfg.RemotePort = Instance->Config->InitialServerPort;
CopyMem (
&Udp6Cfg.StationAddress,
&Instance->Config->StationIp,
sizeof(EFI_IPv6_ADDRESS)
);
CopyMem (
&Udp6Cfg.RemoteAddress,
&Instance->Config->ServerIp,
sizeof (EFI_IPv6_ADDRESS)
);
Udp6 = Instance->UdpIo->Protocol.Udp6;
Status = Udp6->Configure (Udp6, &Udp6Cfg);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
ON_EXIT:
if (EFI_ERROR (Status)) {
if (Instance->Config != NULL) {
FreePool (Instance->Config);
Instance->Config = NULL;
}
if (Instance->UdpIo != NULL) {
UdpIoFreeIo (Instance->UdpIo);
Instance->UdpIo = NULL;
}
}
gBS->RestoreTPL (OldTpl);
return Status;
}
/**
Get the information of the download from the server.
The GetInfo() function assembles an MTFTPv6 request packet
with options, sends it to the MTFTPv6 server, and may return
an MTFTPv6 OACK, MTFTPv6 ERROR, or ICMP ERROR packet. Retries
occur only if no response packets are received from the MTFTPv6
server before the timeout expires.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] OverrideData Data that is used to override the existing parameters. If NULL, the
default parameters that were set in the EFI_MTFTP6_PROTOCOL.Configure()
function are used.
@param[in] Filename Pointer to ASCIIZ file name string.
@param[in] ModeStr Pointer to ASCIIZ mode string. If NULL, octet will be used.
@param[in] OptionCount Number of option/value string pairs in OptionList.
@param[in] OptionList Pointer to array of option/value string pairs. Ignored if
OptionCount is zero.
@param[out] PacketLength The number of bytes in the returned packet.
@param[out] Packet The pointer to the received packet. This buffer must be freed by
the caller.
@retval EFI_SUCCESS An MTFTPv6 OACK packet was received and is in the Packet.
Note: It does not match the UEFI 2.3 Specification.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- This is NULL.
- Filename is NULL.
- OptionCount is not zero and OptionList is NULL.
- One or more options in OptionList have wrong format.
- PacketLength is NULL.
- OverrideData.ServerIp is not valid unicast IPv6 addresses.
@retval EFI_UNSUPPORTED One or more options in the OptionList are unsupported by
this implementation.
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
address for this instance, but no source address was available for use.
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received and is in the Packet.
@retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received and the Packet is set to NULL.
Note: It is not defined in UEFI 2.3 Specification.
@retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received and the Packet is set to NULL.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received and the Packet is set to NULL.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received and the Packet is set to NULL.
@retval EFI_ICMP_ERROR Some other ICMP ERROR packet was received and the Packet is set to NULL.
Note: It does not match the UEFI 2.3 Specification.
@retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received and is in the Packet.
@retval EFI_TIMEOUT No responses were received from the MTFTPv6 server.
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
@retval EFI_NO_MEDIA There was a media error.
**/
EFI_STATUS
EFIAPI
EfiMtftp6GetInfo (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_OVERRIDE_DATA *OverrideData OPTIONAL,
IN UINT8 *Filename,
IN UINT8 *ModeStr OPTIONAL,
IN UINT8 OptionCount,
IN EFI_MTFTP6_OPTION *OptionList OPTIONAL,
OUT UINT32 *PacketLength,
OUT EFI_MTFTP6_PACKET **Packet OPTIONAL
)
{
EFI_STATUS Status;
EFI_MTFTP6_TOKEN Token;
MTFTP6_GETINFO_CONTEXT Context;
if (This == NULL ||
Filename == NULL ||
PacketLength == NULL ||
(OptionCount != 0 && OptionList == NULL) ||
(OverrideData != NULL && !NetIp6IsValidUnicast (&OverrideData->ServerIp))
) {
return EFI_INVALID_PARAMETER;
}
if (Packet != NULL) {
*Packet = NULL;
}
*PacketLength = 0;
Context.Packet = Packet;
Context.PacketLen = PacketLength;
Context.Status = EFI_SUCCESS;
//
// Fill fields of the Token for GetInfo operation.
//
Token.Status = EFI_SUCCESS;
Token.Event = NULL;
Token.OverrideData = OverrideData;
Token.Filename = Filename;
Token.ModeStr = ModeStr;
Token.OptionCount = OptionCount;
Token.OptionList = OptionList;
Token.BufferSize = 0;
Token.Buffer = NULL;
Token.Context = &Context;
Token.CheckPacket = Mtftp6CheckPacket;
Token.TimeoutCallback = NULL;
Token.PacketNeeded = NULL;
//
// Start the GetInfo operation by issue the Token.
//
Status = Mtftp6OperationStart (This, &Token, EFI_MTFTP6_OPCODE_RRQ);
if (Status == EFI_ABORTED) {
//
// Return the status if failed to issue.
//
return Context.Status;
}
return Status;
}
/**
Parse the options in an MTFTPv6 OACK packet.
The ParseOptions() function parses the option fields in an MTFTPv6 OACK
packet and returns the number of options that were found, and optionally,
a list of pointers to the options in the packet. If one or more of the
option fields are not valid, then EFI_PROTOCOL_ERROR is returned and
*OptionCount and *OptionList stop at the last valid option.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] PacketLen Length of the OACK packet to be parsed.
@param[in] Packet Pointer to the OACK packet to be parsed.
@param[out] OptionCount Pointer to the number of options in the following OptionList.
@param[out] OptionList Pointer to EFI_MTFTP6_OPTION storage. Each pointer in the
OptionList points to the corresponding MTFTP option buffer
in the Packet. Call the EFI Boot Service FreePool() to
release the OptionList if the options in this OptionList
are not needed anymore.
@retval EFI_SUCCESS The OACK packet was valid and the OptionCount and
OptionList parameters have been updated.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- PacketLen is 0.
- Packet is NULL or Packet is not a valid MTFTPv6 packet.
- OptionCount is NULL.
@retval EFI_NOT_FOUND No options were found in the OACK packet.
@retval EFI_OUT_OF_RESOURCES Storage for the OptionList array can not be allocated.
@retval EFI_PROTOCOL_ERROR One or more of the option fields is invalid.
**/
EFI_STATUS
EFIAPI
EfiMtftp6ParseOptions (
IN EFI_MTFTP6_PROTOCOL *This,
IN UINT32 PacketLen,
IN EFI_MTFTP6_PACKET *Packet,
OUT UINT32 *OptionCount,
OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL
)
{
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
return Mtftp6ParseStart (Packet, PacketLen, OptionCount, OptionList);
}
/**
Download a file from an MTFTPv6 server.
The ReadFile() function is used to initialize and start an MTFTPv6 download
process, and optionally, wait for completion. When the download operation
completes, whether successfully or not, the Token.Status field is updated
by the EFI MTFTPv6 Protocol driver, and then Token.Event is signaled if it
is not NULL.
Data can be downloaded from the MTFTPv6 server into either of the following
locations:
- A fixed buffer that is pointed to by Token.Buffer
- A download service function that is pointed to by Token.CheckPacket.
If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
will be called first. If the call is successful, the packet will be stored
in Token.Buffer.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] Token Pointer to the token structure to provide the parameters that are
used in this operation.
@retval EFI_SUCCESS The data file has been transferred successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_BUFFER_TOO_SMALL BufferSize is not zero but not large enough to hold the
downloaded data in downloading process.
Note: It does not match the UEFI 2.3 Specification.
@retval EFI_ABORTED Current operation is aborted by user.
@retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_ICMP_ERROR An ICMP ERROR packet was received.
@retval EFI_TIMEOUT No responses were received from the MTFTPv6 server.
@retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received.
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
@retval EFI_NO_MEDIA There was a media error.
**/
EFI_STATUS
EFIAPI
EfiMtftp6ReadFile (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_TOKEN *Token
)
{
return Mtftp6OperationStart (This, Token, EFI_MTFTP6_OPCODE_RRQ);
}
/**
Send a file to an MTFTPv6 server.
The WriteFile() function is used to initialize an uploading operation
with the given option list and optionally wait for completion. If one
or more of the options is not supported by the server, the unsupported
options are ignored and a standard TFTP process starts instead. When
the upload process completes, whether successfully or not, Token.Event
is signaled, and the EFI MTFTPv6 Protocol driver updates Token.Status.
The caller can supply the data to be uploaded in the following two modes:
- Through the user-provided buffer
- Through a callback function
With the user-provided buffer, the Token.BufferSize field indicates
the length of the buffer, and the driver will upload the data in the
buffer. With an EFI_MTFTP6_PACKET_NEEDED callback function, the driver
will call this callback function to get more data from the user to upload.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] Token Pointer to the token structure to provide the parameters that are
used in this operation.
@retval EFI_SUCCESS The upload session has started.
@retval EFI_UNSUPPORTED The operation is not supported by this implementation.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- This is NULL.
- Token is NULL.
- Token.Filename is NULL.
- Token.OptionCount is not zero and Token.OptionList is NULL.
- One or more options in Token.OptionList have wrong format.
- Token.Buffer and Token.PacketNeeded are both NULL.
- Token.OverrideData.ServerIp is not a valid unicast IPv6 address.
@retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not
supported by this implementation.
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
address for this instance, but no source address was available for use.
@retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
**/
EFI_STATUS
EFIAPI
EfiMtftp6WriteFile (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_TOKEN *Token
)
{
return Mtftp6OperationStart (This, Token, EFI_MTFTP6_OPCODE_WRQ);
}
/**
Download a data file directory from an MTFTPv6 server.
The ReadDirectory() function is used to return a list of files on the
MTFTPv6 server that are logically (or operationally) related to
Token.Filename. The directory request packet that is sent to the server
is built with the option list that was provided by the caller, if present.
The file information that the server returns is put into either of
the following locations:
- A fixed buffer that is pointed to by Token.Buffer.
- A download service function that is pointed to by Token.CheckPacket.
If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
will be called first. If the call is successful, the packet will be stored
in Token.Buffer.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] Token Pointer to the token structure to provide the parameters that are
used in this operation.
@retval EFI_SUCCESS The MTFTPv6 related file "directory" has been downloaded.
@retval EFI_UNSUPPORTED The EFI MTFTPv6 Protocol driver does not support this function.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- This is NULL.
- Token is NULL.
- Token.Filename is NULL.
- Token.OptionCount is not zero and Token.OptionList is NULL.
- One or more options in Token.OptionList have wrong format.
- Token.Buffer and Token.CheckPacket are both NULL.
- Token.OverrideData.ServerIp is not valid unicast IPv6 addresses.
@retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not
supported by this implementation.
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
address for this instance, but no source address was available for use.
@retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
**/
EFI_STATUS
EFIAPI
EfiMtftp6ReadDirectory (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_TOKEN *Token
)
{
return Mtftp6OperationStart (This, Token, EFI_MTFTP6_OPCODE_DIR);
}
/**
Polls for incoming data packets and processes outgoing data packets.
The Poll() function can be used by network drivers and applications
to increase the rate that data packets are moved between the
communications device and the transmit and receive queues. In some
systems, the periodic timer event in the managed network driver may
not poll the underlying communications device fast enough to transmit
and/or receive all data packets without missing incoming packets or
dropping outgoing packets. Drivers and applications that are
experiencing packet loss should try calling the Poll() function
more often.
@param[in] This The MTFTP6 protocol instance.
@retval EFI_SUCCESS Incoming or outgoing data was processed.
@retval EFI_NOT_STARTED This EFI MTFTPv6 Protocol instance has not been started.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.
Consider increasing the polling rate.
**/
EFI_STATUS
EFIAPI
EfiMtftp6Poll (
IN EFI_MTFTP6_PROTOCOL *This
)
{
MTFTP6_INSTANCE *Instance;
EFI_UDP6_PROTOCOL *Udp6;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Instance = MTFTP6_INSTANCE_FROM_THIS (This);
//
// Check the instance whether configured or in destory.
//
if (Instance->Config == NULL) {
return EFI_NOT_STARTED;
} else if (Instance->InDestory) {
return EFI_DEVICE_ERROR;
}
Udp6 = Instance->UdpIo->Protocol.Udp6;
return Udp6->Poll (Udp6);
}

View File

@@ -0,0 +1,469 @@
/** @file
Mtftp6 internal data structure and definition declaration.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_MTFTP6_IMPL_H__
#define __EFI_MTFTP6_IMPL_H__
#include <Uefi.h>
#include <Protocol/Udp6.h>
#include <Protocol/Mtftp6.h>
#include <Protocol/ServiceBinding.h>
#include <Protocol/DriverBinding.h>
#include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Library/NetLib.h>
typedef struct _MTFTP6_SERVICE MTFTP6_SERVICE;
typedef struct _MTFTP6_INSTANCE MTFTP6_INSTANCE;
#include "Mtftp6Driver.h"
#include "Mtftp6Option.h"
#include "Mtftp6Support.h"
#define MTFTP6_SERVICE_SIGNATURE SIGNATURE_32 ('M', 'F', '6', 'S')
#define MTFTP6_INSTANCE_SIGNATURE SIGNATURE_32 ('M', 'F', '6', 'I')
#define MTFTP6_DEFAULT_SERVER_CMD_PORT 69
#define MTFTP6_DEFAULT_TIMEOUT 3
#define MTFTP6_GET_MAPPING_TIMEOUT 3
#define MTFTP6_DEFAULT_MAX_RETRY 5
#define MTFTP6_DEFAULT_BLK_SIZE 512
#define MTFTP6_TICK_PER_SECOND 10000000U
#define MTFTP6_SERVICE_FROM_THIS(a) CR (a, MTFTP6_SERVICE, ServiceBinding, MTFTP6_SERVICE_SIGNATURE)
#define MTFTP6_INSTANCE_FROM_THIS(a) CR (a, MTFTP6_INSTANCE, Mtftp6, MTFTP6_INSTANCE_SIGNATURE)
extern EFI_MTFTP6_PROTOCOL gMtftp6ProtocolTemplate;
typedef struct _MTFTP6_GETINFO_CONTEXT{
EFI_MTFTP6_PACKET **Packet;
UINT32 *PacketLen;
EFI_STATUS Status;
} MTFTP6_GETINFO_CONTEXT;
//
// Control block for MTFTP6 instance, it's per configuration data.
//
struct _MTFTP6_INSTANCE {
UINT32 Signature;
EFI_HANDLE Handle;
LIST_ENTRY Link;
EFI_MTFTP6_PROTOCOL Mtftp6;
MTFTP6_SERVICE *Service;
EFI_MTFTP6_CONFIG_DATA *Config;
EFI_MTFTP6_TOKEN *Token;
MTFTP6_EXT_OPTION_INFO ExtInfo;
UINT16 BlkSize;
UINT16 LastBlk;
LIST_ENTRY BlkList;
EFI_IPv6_ADDRESS ServerIp;
UINT16 ServerCmdPort;
UINT16 ServerDataPort;
UDP_IO *UdpIo;
EFI_IPv6_ADDRESS McastIp;
UINT16 McastPort;
UDP_IO *McastUdpIo;
NET_BUF *LastPacket;
UINT32 CurRetry;
UINT32 MaxRetry;
UINT32 PacketToLive;
UINT32 Timeout;
EFI_TPL OldTpl;
BOOLEAN IsTransmitted;
BOOLEAN IsMaster;
BOOLEAN InDestory;
};
//
// Control block for MTFTP6 service, it's per Nic handle.
//
struct _MTFTP6_SERVICE {
UINT32 Signature;
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
EFI_HANDLE Controller;
EFI_HANDLE Image;
UINT16 ChildrenNum;
LIST_ENTRY Children;
//
// It is used to be as internal calculagraph for all instances.
//
EFI_EVENT Timer;
//
// It is used to maintain the parent-child relationship between
// mtftp driver and udp driver.
//
UDP_IO *DummyUdpIo;
BOOLEAN InDestory;
};
/**
Returns the current operating mode data for the MTFTP6 instance.
The GetModeData() function returns the current operating mode and
cached data packet for the MTFTP6 instance.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[out] ModeData The buffer in which the EFI MTFTPv6 Protocol driver mode
data is returned.
@retval EFI_SUCCESS The configuration data was returned successfully.
@retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.
@retval EFI_INVALID_PARAMETER This is NULL, or ModeData is NULL.
**/
EFI_STATUS
EFIAPI
EfiMtftp6GetModeData (
IN EFI_MTFTP6_PROTOCOL *This,
OUT EFI_MTFTP6_MODE_DATA *ModeData
);
/**
Initializes, changes, or resets the default operational setting for
this EFI MTFTPv6 Protocol driver instance.
The Configure() function is used to set and change the configuration
data for this EFI MTFTPv6 Protocol driver instance. The configuration
data can be reset to startup defaults by calling Configure() with
MtftpConfigData set to NULL. Whenever the instance is reset, any
pending operation is aborted. By changing the EFI MTFTPv6 Protocol
driver instance configuration data, the client can connect to
different MTFTPv6 servers. The configuration parameters in
MtftpConfigData are used as the default parameters in later MTFTPv6
operations and can be overridden in later operations.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] MtftpConfigData Pointer to the configuration data structure.
@retval EFI_SUCCESS The EFI MTFTPv6 Protocol instance was configured successfully.
@retval EFI_INVALID_PARAMETER One or more following conditions are TRUE:
- This is NULL.
- MtftpConfigData.StationIp is neither zero nor one
of the configured IP addresses in the underlying IPv6 driver.
- MtftpCofigData.ServerIp is not a valid IPv6 unicast address.
Note: It does not match the UEFI 2.3 Specification.
@retval EFI_ACCESS_DENIED - The configuration could not be changed at this time because there
is some MTFTP background operation in progress.
- MtftpCofigData.LocalPort is already in use.
Note: It does not match the UEFI 2.3 Specification.
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
address for this instance, but no source address was available for use.
@retval EFI_OUT_OF_RESOURCES The EFI MTFTPv6 Protocol driver instance data could not be
allocated.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI
MTFTPv6 Protocol driver instance is not configured.
Note: It is not defined in the UEFI 2.3 Specification.
**/
EFI_STATUS
EFIAPI
EfiMtftp6Configure (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_CONFIG_DATA *MtftpConfigData OPTIONAL
);
/**
Get the information of the download from the server.
The GetInfo() function assembles an MTFTPv6 request packet
with options, sends it to the MTFTPv6 server, and may return
an MTFTPv6 OACK, MTFTPv6 ERROR, or ICMP ERROR packet. Retries
occur only if no response packets are received from the MTFTPv6
server before the timeout expires.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] OverrideData Data that is used to override the existing parameters. If NULL, the
default parameters that were set in the EFI_MTFTP6_PROTOCOL.Configure()
function are used.
@param[in] Filename Pointer to ASCIIZ file name string.
@param[in] ModeStr Pointer to ASCIIZ mode string. If NULL, octet will be used
@param[in] OptionCount Number of option/value string pairs in OptionList.
@param[in] OptionList Pointer to array of option/value string pairs. Ignored if
OptionCount is zero.
@param[out] PacketLength The number of bytes in the returned packet.
@param[out] Packet The pointer to the received packet. This buffer must be freed by
the caller.
@retval EFI_SUCCESS An MTFTPv6 OACK packet was received and is in the Packet.
Note: It does not match the UEFI 2.3 Specification.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- This is NULL.
- Filename is NULL.
- OptionCount is not zero and OptionList is NULL.
- One or more options in OptionList have wrong format.
- PacketLength is NULL.
- OverrideData.ServerIp is not a valid unicast IPv6 address.
@retval EFI_UNSUPPORTED One or more options in the OptionList are unsupported by
this implementation.
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
address for this instance, but no source address was available for use.
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received and is in the Packet.
@retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received, and the Packet is set to NULL.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received, and the Packet is set to NULL.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received, and the Packet is set to NULL.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received, and the Packet is set to NULL.
@retval EFI_ICMP_ERROR Some other ICMP ERROR packet was received, and the Packet is set to NULL.
Note: It does not match the UEFI 2.3 Specification.
@retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received and is in the Packet.
@retval EFI_TIMEOUT No responses were received from the MTFTPv6 server.
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
**/
EFI_STATUS
EFIAPI
EfiMtftp6GetInfo (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_OVERRIDE_DATA *OverrideData OPTIONAL,
IN UINT8 *Filename,
IN UINT8 *ModeStr OPTIONAL,
IN UINT8 OptionCount,
IN EFI_MTFTP6_OPTION *OptionList OPTIONAL,
OUT UINT32 *PacketLength,
OUT EFI_MTFTP6_PACKET **Packet OPTIONAL
);
/**
Parse the options in an MTFTPv6 OACK packet.
The ParseOptions() function parses the option fields in an MTFTPv6 OACK
packet and returns the number of options that were found, and optionally,
a list of pointers to the options in the packet. If one or more of the
option fields are not valid, then EFI_PROTOCOL_ERROR is returned and
*OptionCount and *OptionList stop at the last valid option.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] PacketLen Length of the OACK packet to be parsed.
@param[in] Packet Pointer to the OACK packet to be parsed.
@param[out] OptionCount Pointer to the number of options in the following OptionList.
@param[out] OptionList Pointer to EFI_MTFTP6_OPTION storage. Each pointer in the
OptionList points to the corresponding MTFTP option buffer
in the Packet. Call the EFI Boot Service FreePool() to
release the OptionList if the options in this OptionList
are not needed any more.
@retval EFI_SUCCESS The OACK packet was valid and the OptionCount, and
OptionList parameters have been updated.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- PacketLen is 0.
- Packet is NULL or Packet is not a valid MTFTPv6 packet.
- OptionCount is NULL.
@retval EFI_NOT_FOUND No options were found in the OACK packet.
@retval EFI_OUT_OF_RESOURCES Storage for the OptionList array can not be allocated.
@retval EFI_PROTOCOL_ERROR One or more of the option fields is invalid.
**/
EFI_STATUS
EFIAPI
EfiMtftp6ParseOptions (
IN EFI_MTFTP6_PROTOCOL *This,
IN UINT32 PacketLen,
IN EFI_MTFTP6_PACKET *Packet,
OUT UINT32 *OptionCount,
OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL
);
/**
Download a file from an MTFTPv6 server.
The ReadFile() function is used to initialize and start an MTFTPv6 download
process and optionally wait for completion. When the download operation
completes, whether successfully or not, the Token.Status field is updated
by the EFI MTFTPv6 Protocol driver, and then Token.Event is signaled if it
is not NULL.
Data can be downloaded from the MTFTPv6 server into either of the following
locations:
- A fixed buffer that is pointed to by Token.Buffer.
- A download service function that is pointed to by Token.CheckPacket.
If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
will be called first. If the call is successful, the packet will be stored
in Token.Buffer.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] Token Pointer to the token structure to provide the parameters that are
used in this operation.
@retval EFI_SUCCESS The data file has been transferred successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_BUFFER_TOO_SMALL BufferSize is not zero but not large enough to hold the
downloaded data in downloading process.
Note: It does not match the UEFI 2.3 Specification.
@retval EFI_ABORTED Current operation is aborted by user.
@retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received.
Note: It is not defined in the UEFI 2.3 Specification.
@retval EFI_ICMP_ERROR An ICMP ERROR packet was received.
@retval EFI_TIMEOUT No responses were received from the MTFTPv6 server.
@retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received.
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
**/
EFI_STATUS
EFIAPI
EfiMtftp6ReadFile (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_TOKEN *Token
);
/**
Send a file to an MTFTPv6 server.
The WriteFile() function is used to initialize an uploading operation
with the given option list, and optionally, wait for completion. If one
or more of the options is not supported by the server, the unsupported
options are ignored and a standard TFTP process starts instead. When
the upload process completes, whether successfully or not, Token.Event
is signaled, and the EFI MTFTPv6 Protocol driver updates Token.Status.
The caller can supply the data to be uploaded in the following two modes:
- Through the user-provided buffer.
- Through a callback function.
With the user-provided buffer, the Token.BufferSize field indicates
the length of the buffer, and the driver will upload the data in the
buffer. With an EFI_MTFTP6_PACKET_NEEDED callback function, the driver
will call this callback function to get more data from the user to upload.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] Token Pointer to the token structure to provide the parameters that are
used in this operation.
@retval EFI_SUCCESS The upload session has started.
@retval EFI_UNSUPPORTED The operation is not supported by this implementation.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- This is NULL.
- Token is NULL.
- Token.Filename is NULL.
- Token.OptionCount is not zero and Token.OptionList is NULL.
- One or more options in Token.OptionList have wrong format.
- Token.Buffer and Token.PacketNeeded are both NULL.
- Token.OverrideData.ServerIp is not valid unicast IPv6 addresses.
@retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not
supported by this implementation.
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
address for this instance, but no source address was available for use.
@retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
**/
EFI_STATUS
EFIAPI
EfiMtftp6WriteFile (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_TOKEN *Token
);
/**
Download a data file directory from an MTFTPv6 server.
The ReadDirectory() function is used to return a list of files on the
MTFTPv6 server that are logically (or operationally) related to
Token.Filename. The directory request packet that is sent to the server
is built with the option list that was provided by caller, if present.
The file information that the server returns is put into either of
the following locations:
- A fixed buffer that is pointed to by Token.Buffer.
- A download service function that is pointed to by Token.CheckPacket.
If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
will be called first. If the call is successful, the packet will be stored
in Token.Buffer.
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
@param[in] Token Pointer to the token structure to provide the parameters that are
used in this operation.
@retval EFI_SUCCESS The MTFTPv6 related file "directory" has been downloaded.
@retval EFI_UNSUPPORTED The EFI MTFTPv6 Protocol driver does not support this function.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- This is NULL.
- Token is NULL.
- Token.Filename is NULL.
- Token.OptionCount is not zero and Token.OptionList is NULL.
- One or more options in Token.OptionList have wrong format.
- Token.Buffer and Token.CheckPacket are both NULL.
- Token.OverrideData.ServerIp is not valid unicast IPv6 addresses.
@retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not
supported by this implementation.
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
address for this instance, but no source address was available for use.
@retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
**/
EFI_STATUS
EFIAPI
EfiMtftp6ReadDirectory (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_TOKEN *Token
);
/**
Polls for incoming data packets and processes outgoing data packets.
The Poll() function can be used by network drivers and applications
to increase the rate that data packets are moved between the
communications device and the transmit and receive queues.In some
systems, the periodic timer event in the managed network driver may
not poll the underlying communications device fast enough to transmit
and/or receive all data packets without missing incoming packets or
dropping outgoing packets. Drivers and applications that are
experiencing packet loss should try calling the Poll() function
more often.
@param[in] This The MTFTP6 protocol instance.
@retval EFI_SUCCESS Incoming or outgoing data was processed.
@retval EFI_NOT_STARTED This EFI MTFTPv6 Protocol instance has not been started.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.
Consider increasing the polling rate.
**/
EFI_STATUS
EFIAPI
EfiMtftp6Poll (
IN EFI_MTFTP6_PROTOCOL *This
);
#endif

View File

@@ -0,0 +1,416 @@
/** @file
Mtftp6 option parse functions implementation.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Mtftp6Impl.h"
CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM] = {
"blksize",
"timeout",
"tsize",
"multicast"
};
/**
Parse the NULL terminated ASCII string of multicast option.
@param[in] Str The pointer to the Ascii string of multicast option.
@param[in] ExtInfo The pointer to the option information to be filled.
@retval EFI_SUCCESS Parse the multicast option successfully.
@retval EFI_INVALID_PARAMETER The string is malformatted.
@retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of
resources.
**/
EFI_STATUS
Mtftp6ParseMcastOption (
IN UINT8 *Str,
IN MTFTP6_EXT_OPTION_INFO *ExtInfo
)
{
EFI_STATUS Status;
UINT32 Num;
CHAR8 *Ip6Str;
CHAR8 *TempStr;
//
// The multicast option is formated like "addr,port,mc"
// The server can also omit the ip and port, use ",,1"
//
if (*Str == ',') {
ZeroMem (&ExtInfo->McastIp, sizeof (EFI_IPv6_ADDRESS));
} else {
Ip6Str = (CHAR8 *) AllocateCopyPool (AsciiStrSize ((CHAR8 *) Str), Str);
if (Ip6Str == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// The IPv6 address locates before comma in the input Str.
//
TempStr = Ip6Str;
while ((*TempStr != '\0') && (*TempStr != ',')) {
TempStr++;
}
*TempStr = '\0';
Status = NetLibAsciiStrToIp6 (Ip6Str, &ExtInfo->McastIp);
FreePool (Ip6Str);
if (EFI_ERROR (Status)) {
return Status;
}
while ((*Str != '\0') && (*Str != ',')) {
Str++;
}
}
if (*Str != ',') {
return EFI_INVALID_PARAMETER;
}
Str++;
//
// Convert the port setting. the server can send us a port number or
// empty string. such as the port in ",,1"
//
if (*Str == ',') {
ExtInfo->McastPort = 0;
} else {
Num = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Str);
if (Num > 65535) {
return EFI_INVALID_PARAMETER;
}
ExtInfo->McastPort = (UINT16) Num;
while (NET_IS_DIGIT (*Str)) {
Str++;
}
}
if (*Str != ',') {
return EFI_INVALID_PARAMETER;
}
Str++;
//
// Check the master/slave setting, 1 for master, 0 for slave.
//
Num = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Str);
if (Num != 0 && Num != 1) {
return EFI_INVALID_PARAMETER;
}
ExtInfo->IsMaster = (BOOLEAN) (Num == 1);
while (NET_IS_DIGIT (*Str)) {
Str++;
}
if (*Str != '\0') {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
/**
Parse the MTFTP6 extesion options.
@param[in] Options The pointer to the extension options list.
@param[in] Count The num of the extension options.
@param[in] IsRequest If FALSE, the extension options is included
by a request packet.
@param[in] ExtInfo The pointer to the option information to be filled.
@retval EFI_SUCCESS Parse the multicast option successfully.
@retval EFI_INVALID_PARAMETER There is one option is malformatted at least.
@retval EFI_UNSUPPORTED There is one option is not supported at least.
**/
EFI_STATUS
Mtftp6ParseExtensionOption (
IN EFI_MTFTP6_OPTION *Options,
IN UINT32 Count,
IN BOOLEAN IsRequest,
IN MTFTP6_EXT_OPTION_INFO *ExtInfo
)
{
EFI_STATUS Status;
EFI_MTFTP6_OPTION *Opt;
UINT32 Index;
UINT32 Value;
ExtInfo->BitMap = 0;
for (Index = 0; Index < Count; Index++) {
Opt = Options + Index;
if (Opt->OptionStr == NULL || Opt->ValueStr == NULL) {
return EFI_INVALID_PARAMETER;
}
if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "blksize") == 0) {
//
// block size option, valid value is between [8, 65464]
//
Value = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr);
if ((Value < 8) || (Value > 65464)) {
return EFI_INVALID_PARAMETER;
}
ExtInfo->BlkSize = (UINT16) Value;
ExtInfo->BitMap |= MTFTP6_OPT_BLKSIZE_BIT;
} else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "timeout") == 0) {
//
// timeout option, valid value is between [1, 255]
//
Value = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr);
if (Value < 1 || Value > 255) {
return EFI_INVALID_PARAMETER;
}
ExtInfo->Timeout = (UINT8) Value;
ExtInfo->BitMap |= MTFTP6_OPT_TIMEOUT_BIT;
} else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "tsize") == 0) {
//
// tsize option, the biggest transfer supported is 4GB with block size option
//
ExtInfo->Tsize = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr);
ExtInfo->BitMap |= MTFTP6_OPT_TSIZE_BIT;
} else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "multicast") == 0) {
//
// Multicast option, if it is a request, the value must be a zero string,
// otherwise, it must be like "addr,port,mc" string, mc indicates master.
//
if (!IsRequest) {
Status = Mtftp6ParseMcastOption (Opt->ValueStr, ExtInfo);
if (EFI_ERROR (Status)) {
return Status;
}
} else if (*(Opt->ValueStr) != '\0') {
return EFI_INVALID_PARAMETER;
}
ExtInfo->BitMap |= MTFTP6_OPT_MCAST_BIT;
} else if (IsRequest) {
//
// If it's a request, unsupported; else if it's a reply, ignore.
//
return EFI_UNSUPPORTED;
}
}
return EFI_SUCCESS;
}
/**
Go through the packet to fill the options array with the start
addresses of each MTFTP option name/value pair.
@param[in] Packet The packet to be checked.
@param[in] PacketLen The length of the packet.
@param[in, out] Count The num of the Options on input.
The actual one on output.
@param[in] Options The option array to be filled.
It is optional.
@retval EFI_SUCCESS The packet has been parsed successfully.
@retval EFI_INVALID_PARAMETER The packet is malformatted.
@retval EFI_BUFFER_TOO_SMALL The Options array is too small.
@retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received.
**/
EFI_STATUS
Mtftp6ParsePacketOption (
IN EFI_MTFTP6_PACKET *Packet,
IN UINT32 PacketLen,
IN OUT UINT32 *Count,
IN EFI_MTFTP6_OPTION *Options OPTIONAL
)
{
UINT8 *Cur;
UINT8 *Last;
UINT8 Num;
UINT8 *Name;
UINT8 *Value;
Num = 0;
Cur = (UINT8 *) Packet + MTFTP6_OPCODE_LEN;
Last = (UINT8 *) Packet + PacketLen - 1;
//
// process option name and value pairs.
// The last byte is always zero.
//
while (Cur < Last) {
Name = Cur;
while (*Cur != 0) {
Cur++;
}
if (Cur == Last) {
return EFI_PROTOCOL_ERROR;
}
Value = ++Cur;
while (*Cur != 0) {
Cur++;
}
Num++;
if (Options != NULL && Num <= *Count) {
Options[Num - 1].OptionStr = Name;
Options[Num - 1].ValueStr = Value;
}
Cur++;
}
//
// Return buffer too small if the buffer passed-in isn't enough.
//
if (*Count < Num || Options == NULL) {
*Count = Num;
return EFI_BUFFER_TOO_SMALL;
}
*Count = Num;
return EFI_SUCCESS;
}
/**
Go through the packet, generate option list array and fill it
by the result of parse options.
@param[in] Packet The packet to be checked.
@param[in] PacketLen The length of the packet.
@param[in, out] OptionCount The num of the Options on input.
The actual one on output.
@param[out] OptionList The option list array to be generated
and filled. It is optional.
@retval EFI_SUCCESS The packet has been parsed successfully.
@retval EFI_INVALID_PARAMETER The packet is malformatted.
@retval EFI_PROTOCOL_ERROR There is one option is malformatted at least.
@retval EFI_NOT_FOUND The packet has no options.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array.
@retval EFI_BUFFER_TOO_SMALL The size of option list array is too small.
**/
EFI_STATUS
Mtftp6ParseStart (
IN EFI_MTFTP6_PACKET *Packet,
IN UINT32 PacketLen,
IN OUT UINT32 *OptionCount,
OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL
)
{
EFI_STATUS Status;
if (PacketLen == 0 || Packet == NULL || OptionCount == NULL) {
return EFI_INVALID_PARAMETER;
}
*OptionCount = 0;
if (OptionList != NULL) {
*OptionList = NULL;
}
if (NTOHS (Packet->OpCode) != EFI_MTFTP6_OPCODE_OACK) {
return EFI_INVALID_PARAMETER;
}
//
// The last byte must be zero to terminate the options.
//
if (*((UINT8 *) Packet + PacketLen - 1) != 0) {
return EFI_PROTOCOL_ERROR;
}
//
// Parse packet with NULL buffer for the first time to get the number
// of options in the packet.
//
Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, NULL);
if (Status != EFI_BUFFER_TOO_SMALL) {
return Status;
}
//
// Return not found if there is no option parsed.
//
if (*OptionCount == 0) {
return EFI_NOT_FOUND;
}
//
// Only need parse out the number of options.
//
if (OptionList == NULL) {
return EFI_SUCCESS;
}
//
// Allocate the buffer according to the option number parsed before.
//
*OptionList = AllocateZeroPool (*OptionCount * sizeof (EFI_MTFTP6_OPTION));
if (*OptionList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Parse packet with allocated buffer for the second time to fill the pointer array
// of the options in the packet.
//
Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, *OptionList);
if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,148 @@
/** @file
Mtftp6 option parse functions declaration.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_MTFTP6_OPTION_H__
#define __EFI_MTFTP6_OPTION_H__
#include <Uefi.h>
#include <Protocol/ServiceBinding.h>
#include <Library/NetLib.h>
#include <Library/UdpIoLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#define MTFTP6_SUPPORTED_OPTIONS_NUM 4
#define MTFTP6_OPCODE_LEN 2
#define MTFTP6_ERRCODE_LEN 2
#define MTFTP6_BLKNO_LEN 2
#define MTFTP6_DATA_HEAD_LEN 4
//
// The bit map definition for Mtftp6 extension options.
//
#define MTFTP6_OPT_BLKSIZE_BIT 0x01
#define MTFTP6_OPT_TIMEOUT_BIT 0x02
#define MTFTP6_OPT_TSIZE_BIT 0x04
#define MTFTP6_OPT_MCAST_BIT 0x08
extern CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM];
typedef struct {
UINT16 BlkSize;
UINT8 Timeout;
UINT32 Tsize;
EFI_IPv6_ADDRESS McastIp;
UINT16 McastPort;
BOOLEAN IsMaster;
UINT32 BitMap;
} MTFTP6_EXT_OPTION_INFO;
/**
Parse the Ascii string of multi-cast option.
@param[in] Str The pointer to the Ascii string of multi-cast option.
@param[in] ExtInfo The pointer to the option information to be filled.
@retval EFI_SUCCESS Parse the multicast option successfully.
@retval EFI_INVALID_PARAMETER The string is malformatted.
**/
EFI_STATUS
Mtftp6ParseMcastOption (
IN UINT8 *Str,
IN MTFTP6_EXT_OPTION_INFO *ExtInfo
);
/**
Parse the MTFTP6 extesion options.
@param[in] Options The pointer to the extension options list.
@param[in] Count The num of the extension options.
@param[in] IsRequest If FALSE, the extension options is included
by a request packet.
@param[in] ExtInfo The pointer to the option information to be filled.
@retval EFI_SUCCESS Parse the multi-cast option successfully.
@retval EFI_INVALID_PARAMETER An option is malformatted.
@retval EFI_UNSUPPORTED An option is not supported.
**/
EFI_STATUS
Mtftp6ParseExtensionOption (
IN EFI_MTFTP6_OPTION *Options,
IN UINT32 Count,
IN BOOLEAN IsRequest,
IN MTFTP6_EXT_OPTION_INFO *ExtInfo
);
/**
Go through the packet to fill the options array with the start
addresses of each MTFTP option name/value pair.
@param[in] Packet The packet to be checked.
@param[in] PacketLen The length of the packet.
@param[in, out] Count The num of the Options on input.
The actual one on output.
@param[in] Options The option array to be filled
it's optional.
@retval EFI_SUCCESS The packet has been parsed successfully.
@retval EFI_INVALID_PARAMETER The packet is malformatted
@retval EFI_BUFFER_TOO_SMALL The Options array is too small
@retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received.
**/
EFI_STATUS
Mtftp6ParsePacketOption (
IN EFI_MTFTP6_PACKET *Packet,
IN UINT32 PacketLen,
IN OUT UINT32 *Count,
IN EFI_MTFTP6_OPTION *Options OPTIONAL
);
/**
Go through the packet, generate option list array and fill it
by the result of parse options.
@param[in] Packet The packet to be checked.
@param[in] PacketLen The length of the packet.
@param[in, out] OptionCount The num of the Options on input.
The actual one on output.
@param[out] OptionList The option list array to be generated
and filled. It is optional.
@retval EFI_SUCCESS The packet has been parsed successfully.
@retval EFI_INVALID_PARAMETER The packet is malformatted.
@retval EFI_PROTOCOL_ERROR An option is malformatted.
@retval EFI_NOT_FOUND The packet has no options.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array.
@retval EFI_BUFFER_TOO_SMALL The size of option list array is too small.
**/
EFI_STATUS
Mtftp6ParseStart (
IN EFI_MTFTP6_PACKET *Packet,
IN UINT32 PacketLen,
IN OUT UINT32 *OptionCount,
OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL
);
#endif

View File

@@ -0,0 +1,900 @@
/** @file
Mtftp6 Rrq process functions implementation.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Mtftp6Impl.h"
/**
Build and send a ACK packet for download.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] BlockNum The block number to be acked.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the packet.
@retval EFI_SUCCESS The ACK has been sent.
@retval Others Failed to send the ACK.
**/
EFI_STATUS
Mtftp6RrqSendAck (
IN MTFTP6_INSTANCE *Instance,
IN UINT16 BlockNum
)
{
EFI_MTFTP6_PACKET *Ack;
NET_BUF *Packet;
//
// Allocate net buffer to create ack packet.
//
Packet = NetbufAlloc (sizeof (EFI_MTFTP6_ACK_HEADER));
if (Packet == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Ack = (EFI_MTFTP6_PACKET *) NetbufAllocSpace (
Packet,
sizeof (EFI_MTFTP6_ACK_HEADER),
FALSE
);
ASSERT (Ack != NULL);
Ack->Ack.OpCode = HTONS (EFI_MTFTP6_OPCODE_ACK);
Ack->Ack.Block[0] = HTONS (BlockNum);
//
// Reset current retry count of the instance.
//
Instance->CurRetry = 0;
return Mtftp6TransmitPacket (Instance, Packet);
}
/**
Deliver the received data block to the user, which can be saved
in the user provide buffer or through the CheckPacket callback.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Packet The pointer to the received packet.
@param[in] Len The packet length.
@param[out] UdpPacket The net buf of the received packet.
@retval EFI_SUCCESS The data was saved successfully.
@retval EFI_ABORTED The user tells to abort by return an error through
CheckPacket.
@retval EFI_BUFFER_TOO_SMALL The user's buffer is too small, and buffer length is
updated to the actual buffer size needed.
**/
EFI_STATUS
Mtftp6RrqSaveBlock (
IN MTFTP6_INSTANCE *Instance,
IN EFI_MTFTP6_PACKET *Packet,
IN UINT32 Len,
OUT NET_BUF **UdpPacket
)
{
EFI_MTFTP6_TOKEN *Token;
EFI_STATUS Status;
UINT16 Block;
UINT64 Start;
UINT32 DataLen;
UINT64 TotalBlock;
BOOLEAN Completed;
Completed = FALSE;
Token = Instance->Token;
Block = NTOHS (Packet->Data.Block);
DataLen = Len - MTFTP6_DATA_HEAD_LEN;
//
// This is the last block, save the block num
//
if (DataLen < Instance->BlkSize) {
Completed = TRUE;
Instance->LastBlk = Block;
Mtftp6SetLastBlockNum (&Instance->BlkList, Block);
}
//
// Remove this block number from the file hole. If Mtftp6RemoveBlockNum
// returns EFI_NOT_FOUND, the block has been saved, don't save it again.
// Note that : For bigger files, allowing the block counter to roll over
// to accept transfers of unlimited size. So TotalBlock is memorised as
// continuous block counter.
//
Status = Mtftp6RemoveBlockNum (&Instance->BlkList, Block, Completed, &TotalBlock);
if (Status == EFI_NOT_FOUND) {
return EFI_SUCCESS;
} else if (EFI_ERROR (Status)) {
return Status;
}
if (Token->CheckPacket != NULL) {
//
// Callback to the check packet routine with the received packet.
//
Status = Token->CheckPacket (&Instance->Mtftp6, Token, (UINT16) Len, Packet);
if (EFI_ERROR (Status)) {
//
// Free the received packet before send new packet in ReceiveNotify,
// since the Udp6Io might need to be reconfigured.
//
NetbufFree (*UdpPacket);
*UdpPacket = NULL;
//
// Send the Mtftp6 error message if user aborted the current session.
//
Mtftp6SendError (
Instance,
EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
(UINT8 *) "User aborted download"
);
return EFI_ABORTED;
}
}
if (Token->Buffer != NULL) {
Start = MultU64x32 (TotalBlock - 1, Instance->BlkSize);
if (Start + DataLen <= Token->BufferSize) {
CopyMem ((UINT8 *) Token->Buffer + Start, Packet->Data.Data, DataLen);
//
// Update the file size when received the last block
//
if ((Instance->LastBlk == Block) && Completed) {
Token->BufferSize = Start + DataLen;
}
} else if (Instance->LastBlk != 0) {
//
// Don't save the data if the buffer is too small, return
// EFI_BUFFER_TOO_SMALL if received the last packet. This
// will give a accurate file length.
//
Token->BufferSize = Start + DataLen;
//
// Free the received packet before send new packet in ReceiveNotify,
// since the udpio might need to be reconfigured.
//
NetbufFree (*UdpPacket);
*UdpPacket = NULL;
//
// Send the Mtftp6 error message if no enough buffer.
//
Mtftp6SendError (
Instance,
EFI_MTFTP6_ERRORCODE_DISK_FULL,
(UINT8 *) "User provided memory block is too small"
);
return EFI_BUFFER_TOO_SMALL;
}
}
return EFI_SUCCESS;
}
/**
Process the received data packets. It will save the block
then send back an ACK if it is active.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Packet The pointer to the received packet.
@param[in] Len The length of the packet.
@param[out] UdpPacket The net buf of received packet.
@param[out] IsCompleted If TRUE, the download has been completed.
Otherwise, the download has not been completed.
@retval EFI_SUCCESS The data packet was successfully processed.
@retval EFI_ABORTED The download was aborted by the user.
@retval EFI_BUFFER_TOO_SMALL The user-provided buffer is too small.
**/
EFI_STATUS
Mtftp6RrqHandleData (
IN MTFTP6_INSTANCE *Instance,
IN EFI_MTFTP6_PACKET *Packet,
IN UINT32 Len,
OUT NET_BUF **UdpPacket,
OUT BOOLEAN *IsCompleted
)
{
EFI_STATUS Status;
UINT16 BlockNum;
INTN Expected;
*IsCompleted = FALSE;
BlockNum = NTOHS (Packet->Data.Block);
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
ASSERT (Expected >= 0);
//
// If we are active and received an unexpected packet, retransmit
// the last ACK then restart receiving. If we are passive, save
// the block.
//
if (Instance->IsMaster && (Expected != BlockNum)) {
//
// Free the received packet before send new packet in ReceiveNotify,
// since the udpio might need to be reconfigured.
//
NetbufFree (*UdpPacket);
*UdpPacket = NULL;
Mtftp6TransmitPacket (Instance, Instance->LastPacket);
return EFI_SUCCESS;
}
Status = Mtftp6RrqSaveBlock (Instance, Packet, Len, UdpPacket);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Reset the passive client's timer whenever it received a valid data packet.
//
if (!Instance->IsMaster) {
Instance->PacketToLive = Instance->Timeout * 2;
}
//
// Check whether we have received all the blocks. Send the ACK if we
// are active (unicast client or master client for multicast download).
// If we have received all the blocks, send an ACK even if we are passive
// to tell the server that we are done.
//
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
if (Instance->IsMaster || Expected < 0) {
if (Expected < 0) {
//
// If we are passive client, then the just received Block maybe
// isn't the last block. We need to send an ACK to the last block
// to inform the server that we are done. If we are active client,
// the Block == Instance->LastBlock.
//
BlockNum = Instance->LastBlk;
*IsCompleted = TRUE;
} else {
BlockNum = (UINT16) (Expected - 1);
}
//
// Free the received packet before send new packet in ReceiveNotify,
// since the udpio might need to be reconfigured.
//
NetbufFree (*UdpPacket);
*UdpPacket = NULL;
Mtftp6RrqSendAck (Instance, BlockNum);
}
return EFI_SUCCESS;
}
/**
Validate whether the options received in the server's OACK packet is valid.
The options are valid only if:
1. The server doesn't include options not requested by us.
2. The server can only use smaller blksize than that is requested.
3. The server can only use the same timeout as requested.
4. The server doesn't change its multicast channel.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] ReplyInfo The pointer to options information in reply packet.
@param[in] RequestInfo The pointer to requested options info.
@retval TRUE If the option in the OACK is valid.
@retval FALSE If the option is invalid.
**/
BOOLEAN
Mtftp6RrqOackValid (
IN MTFTP6_INSTANCE *Instance,
IN MTFTP6_EXT_OPTION_INFO *ReplyInfo,
IN MTFTP6_EXT_OPTION_INFO *RequestInfo
)
{
//
// It is invalid for server to return options we don't request
//
if ((ReplyInfo->BitMap & ~RequestInfo->BitMap) != 0) {
return FALSE;
}
//
// Server can only specify a smaller block size to be used and
// return the timeout matches that requested.
//
if ((((ReplyInfo->BitMap & MTFTP6_OPT_BLKSIZE_BIT) != 0) && (ReplyInfo->BlkSize > RequestInfo->BlkSize)) ||
(((ReplyInfo->BitMap & MTFTP6_OPT_TIMEOUT_BIT) != 0) && (ReplyInfo->Timeout != RequestInfo->Timeout))
) {
return FALSE;
}
//
// The server can send ",,master" to client to change its master
// setting. But if it use the specific multicast channel, it can't
// change the setting.
//
if (((ReplyInfo->BitMap & MTFTP6_OPT_MCAST_BIT) != 0) && !NetIp6IsUnspecifiedAddr (&Instance->McastIp)) {
if (!NetIp6IsUnspecifiedAddr (&ReplyInfo->McastIp) && CompareMem (
&ReplyInfo->McastIp,
&Instance->McastIp,
sizeof (EFI_IPv6_ADDRESS)
) != 0) {
return FALSE;
}
if ((ReplyInfo->McastPort != 0) && (ReplyInfo->McastPort != Instance->McastPort)) {
return FALSE;
}
}
return TRUE;
}
/**
Configure Udp6Io to receive a packet from a multicast address.
@param[in] McastIo The pointer to the mcast Udp6Io.
@param[in] Context The pointer to the context.
@retval EFI_SUCCESS The mcast Udp6Io was successfully configured.
@retval Others Failed to configure the Udp6Io.
**/
EFI_STATUS
EFIAPI
Mtftp6RrqConfigMcastUdpIo (
IN UDP_IO *McastIo,
IN VOID *Context
)
{
EFI_STATUS Status;
EFI_UDP6_PROTOCOL *Udp6;
EFI_UDP6_CONFIG_DATA *Udp6Cfg;
EFI_IPv6_ADDRESS Group;
MTFTP6_INSTANCE *Instance;
Udp6 = McastIo->Protocol.Udp6;
Udp6Cfg = &(McastIo->Config.Udp6);
Instance = (MTFTP6_INSTANCE *) Context;
//
// Set the configure data for the mcast Udp6Io.
//
ZeroMem (Udp6Cfg, sizeof (EFI_UDP6_CONFIG_DATA));
Udp6Cfg->AcceptPromiscuous = FALSE;
Udp6Cfg->AcceptAnyPort = FALSE;
Udp6Cfg->AllowDuplicatePort = FALSE;
Udp6Cfg->TrafficClass = 0;
Udp6Cfg->HopLimit = 128;
Udp6Cfg->ReceiveTimeout = 0;
Udp6Cfg->TransmitTimeout = 0;
Udp6Cfg->StationPort = Instance->McastPort;
Udp6Cfg->RemotePort = 0;
CopyMem (
&Udp6Cfg->RemoteAddress,
&Instance->ServerIp,
sizeof (EFI_IPv6_ADDRESS)
);
//
// Configure the mcast Udp6Io.
//
Status = Udp6->Configure (Udp6, Udp6Cfg);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Join the multicast group
//
CopyMem (&Group, &Instance->McastIp, sizeof (EFI_IPv6_ADDRESS));
return Udp6->Groups (Udp6, TRUE, &Group);
}
/**
Process the OACK packet for Rrq.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Packet The pointer to the received packet.
@param[in] Len The length of the packet.
@param[out] UdpPacket The net buf of received packet.
@param[out] IsCompleted If TRUE, the download has been completed.
Otherwise, the download has not been completed.
@retval EFI_DEVICE_ERROR Failed to create/start a multicast Udp6 child.
@retval EFI_TFTP_ERROR An error happened during the process.
@retval EFI_SUCCESS The OACK packet successfully processed.
**/
EFI_STATUS
Mtftp6RrqHandleOack (
IN MTFTP6_INSTANCE *Instance,
IN EFI_MTFTP6_PACKET *Packet,
IN UINT32 Len,
OUT NET_BUF **UdpPacket,
OUT BOOLEAN *IsCompleted
)
{
EFI_MTFTP6_OPTION *Options;
UINT32 Count;
MTFTP6_EXT_OPTION_INFO ExtInfo;
EFI_STATUS Status;
INTN Expected;
*IsCompleted = FALSE;
//
// If already started the master download, don't change the
// setting. Master download always succeeds.
//
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
ASSERT (Expected != -1);
if (Instance->IsMaster && Expected != 1) {
return EFI_SUCCESS;
}
ZeroMem (&ExtInfo, sizeof (MTFTP6_EXT_OPTION_INFO));
//
// Parse the options in the packet.
//
Status = Mtftp6ParseStart (Packet, Len, &Count, &Options);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Parse the extensive options in the packet.
//
Status = Mtftp6ParseExtensionOption (Options, Count, FALSE, &ExtInfo);
if (EFI_ERROR (Status) || !Mtftp6RrqOackValid (Instance, &ExtInfo, &Instance->ExtInfo)) {
//
// Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES.
//
if (Status != EFI_OUT_OF_RESOURCES) {
//
// Free the received packet before send new packet in ReceiveNotify,
// since the udpio might need to be reconfigured.
//
NetbufFree (*UdpPacket);
*UdpPacket = NULL;
//
// Send the Mtftp6 error message if invalid packet.
//
Mtftp6SendError (
Instance,
EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
(UINT8 *) "Mal-formated OACK packet"
);
}
return EFI_TFTP_ERROR;
}
if ((ExtInfo.BitMap & MTFTP6_OPT_MCAST_BIT) != 0) {
//
// Save the multicast info. Always update the Master, only update the
// multicast IP address, block size, timeoute at the first time. If IP
// address is updated, create a UDP child to receive the multicast.
//
Instance->IsMaster = ExtInfo.IsMaster;
if (NetIp6IsUnspecifiedAddr (&Instance->McastIp)) {
if (NetIp6IsUnspecifiedAddr (&ExtInfo.McastIp) || ExtInfo.McastPort == 0) {
//
// Free the received packet before send new packet in ReceiveNotify,
// since the udpio might need to be reconfigured.
//
NetbufFree (*UdpPacket);
*UdpPacket = NULL;
//
// Send the Mtftp6 error message if invalid multi-cast setting.
//
Mtftp6SendError (
Instance,
EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
(UINT8 *) "Illegal multicast setting"
);
return EFI_TFTP_ERROR;
}
//
// Create a UDP child then start receive the multicast from it.
//
CopyMem (
&Instance->McastIp,
&ExtInfo.McastIp,
sizeof (EFI_IP_ADDRESS)
);
Instance->McastPort = ExtInfo.McastPort;
Instance->McastUdpIo = UdpIoCreateIo (
Instance->Service->Controller,
Instance->Service->Image,
Mtftp6RrqConfigMcastUdpIo,
UDP_IO_UDP6_VERSION,
Instance
);
if (Instance->McastUdpIo == NULL) {
return EFI_DEVICE_ERROR;
}
Status = UdpIoRecvDatagram (
Instance->McastUdpIo,
Mtftp6RrqInput,
Instance,
0
);
if (EFI_ERROR (Status)) {
//
// Free the received packet before send new packet in ReceiveNotify,
// since the udpio might need to be reconfigured.
//
NetbufFree (*UdpPacket);
*UdpPacket = NULL;
//
// Send the Mtftp6 error message if failed to create Udp6Io to receive.
//
Mtftp6SendError (
Instance,
EFI_MTFTP6_ERRORCODE_ACCESS_VIOLATION,
(UINT8 *) "Failed to create socket to receive multicast packet"
);
return Status;
}
//
// Update the parameters used.
//
if (ExtInfo.BlkSize != 0) {
Instance->BlkSize = ExtInfo.BlkSize;
}
if (ExtInfo.Timeout != 0) {
Instance->Timeout = ExtInfo.Timeout;
}
}
} else {
Instance->IsMaster = TRUE;
if (ExtInfo.BlkSize != 0) {
Instance->BlkSize = ExtInfo.BlkSize;
}
if (ExtInfo.Timeout != 0) {
Instance->Timeout = ExtInfo.Timeout;
}
}
//
// Free the received packet before send new packet in ReceiveNotify,
// since the udpio might need to be reconfigured.
//
NetbufFree (*UdpPacket);
*UdpPacket = NULL;
//
// Send an ACK to (Expected - 1) which is 0 for unicast download,
// or tell the server we want to receive the Expected block.
//
return Mtftp6RrqSendAck (Instance, (UINT16) (Expected - 1));
}
/**
The packet process callback for Mtftp6 download.
@param[in] UdpPacket The pointer to the packet received.
@param[in] UdpEpt The pointer to the Udp6 access point.
@param[in] IoStatus The status from Udp6 instance.
@param[in] Context The pointer to the context.
**/
VOID
EFIAPI
Mtftp6RrqInput (
IN NET_BUF *UdpPacket,
IN UDP_END_POINT *UdpEpt,
IN EFI_STATUS IoStatus,
IN VOID *Context
)
{
MTFTP6_INSTANCE *Instance;
EFI_MTFTP6_PACKET *Packet;
BOOLEAN IsCompleted;
BOOLEAN IsMcast;
EFI_STATUS Status;
UINT16 Opcode;
UINT32 TotalNum;
UINT32 Len;
Instance = (MTFTP6_INSTANCE *) Context;
NET_CHECK_SIGNATURE (Instance, MTFTP6_INSTANCE_SIGNATURE);
Status = EFI_SUCCESS;
Packet = NULL;
IsCompleted = FALSE;
IsMcast = FALSE;
TotalNum = 0;
//
// Return error status if Udp6 instance failed to receive.
//
if (EFI_ERROR (IoStatus)) {
Status = IoStatus;
goto ON_EXIT;
}
ASSERT (UdpPacket != NULL);
if (UdpPacket->TotalSize < MTFTP6_OPCODE_LEN) {
goto ON_EXIT;
}
//
// Find the port this packet is from to restart receive correctly.
//
if (CompareMem (
Ip6Swap128 (&UdpEpt->LocalAddr.v6),
&Instance->McastIp,
sizeof (EFI_IPv6_ADDRESS)
) == 0) {
IsMcast = TRUE;
} else {
IsMcast = FALSE;
}
//
// Client send initial request to server's listening port. Server
// will select a UDP port to communicate with the client. The server
// is required to use the same port as RemotePort to multicast the
// data.
//
if (UdpEpt->RemotePort != Instance->ServerDataPort) {
if (Instance->ServerDataPort != 0) {
goto ON_EXIT;
} else {
//
// For the subsequent exchange of requests, reconfigure the udpio as
// (serverip, serverport, localip, localport).
// Ususally, the client set serverport as 0 to receive and reset it
// once the first packet arrives to send ack.
//
Instance->ServerDataPort = UdpEpt->RemotePort;
}
}
//
// Copy the MTFTP packet to a continuous buffer if it isn't already so.
//
Len = UdpPacket->TotalSize;
TotalNum = UdpPacket->BlockOpNum;
if (TotalNum > 1) {
Packet = AllocateZeroPool (Len);
if (Packet == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet);
} else {
Packet = (EFI_MTFTP6_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);
ASSERT (Packet != NULL);
}
Opcode = NTOHS (Packet->OpCode);
//
// Callback to the user's CheckPacket if provided. Abort the transmission
// if CheckPacket returns an EFI_ERROR code.
//
if ((Instance->Token->CheckPacket != NULL) &&
(Opcode == EFI_MTFTP6_OPCODE_OACK || Opcode == EFI_MTFTP6_OPCODE_ERROR)
) {
Status = Instance->Token->CheckPacket (
&Instance->Mtftp6,
Instance->Token,
(UINT16) Len,
Packet
);
if (EFI_ERROR (Status)) {
//
// Send an error message to the server to inform it
//
if (Opcode != EFI_MTFTP6_OPCODE_ERROR) {
//
// Free the received packet before send new packet in ReceiveNotify,
// since the udpio might need to be reconfigured.
//
NetbufFree (UdpPacket);
UdpPacket = NULL;
//
// Send the Mtftp6 error message if user aborted the current session.
//
Mtftp6SendError (
Instance,
EFI_MTFTP6_ERRORCODE_REQUEST_DENIED,
(UINT8 *) "User aborted the transfer"
);
}
Status = EFI_ABORTED;
goto ON_EXIT;
}
}
//
// Switch the process routines by the operation code.
//
switch (Opcode) {
case EFI_MTFTP6_OPCODE_DATA:
if ((Len > (UINT32) (MTFTP6_DATA_HEAD_LEN + Instance->BlkSize)) || (Len < (UINT32) MTFTP6_DATA_HEAD_LEN)) {
goto ON_EXIT;
}
//
// Handle the data packet of Rrq.
//
Status = Mtftp6RrqHandleData (
Instance,
Packet,
Len,
&UdpPacket,
&IsCompleted
);
break;
case EFI_MTFTP6_OPCODE_OACK:
if (IsMcast || Len <= MTFTP6_OPCODE_LEN) {
goto ON_EXIT;
}
//
// Handle the Oack packet of Rrq.
//
Status = Mtftp6RrqHandleOack (
Instance,
Packet,
Len,
&UdpPacket,
&IsCompleted
);
break;
default:
//
// Drop and return eror if received error message.
//
Status = EFI_TFTP_ERROR;
break;
}
ON_EXIT:
//
// Free the resources, then if !EFI_ERROR (Status), restart the
// receive, otherwise end the session.
//
if (Packet != NULL && TotalNum > 1) {
FreePool (Packet);
}
if (UdpPacket != NULL) {
NetbufFree (UdpPacket);
}
if (!EFI_ERROR (Status) && !IsCompleted) {
if (IsMcast) {
Status = UdpIoRecvDatagram (
Instance->McastUdpIo,
Mtftp6RrqInput,
Instance,
0
);
} else {
Status = UdpIoRecvDatagram (
Instance->UdpIo,
Mtftp6RrqInput,
Instance,
0
);
}
}
//
// Clean up the current session if failed to continue.
//
if (EFI_ERROR (Status) || IsCompleted) {
Mtftp6OperationClean (Instance, Status);
}
}
/**
Start the Mtftp6 instance to download. It first initializes some
of the internal states, then builds and sends an RRQ reqeuest packet.
Finally, it starts receive for the downloading.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Operation The operation code of current packet.
@retval EFI_SUCCESS The Mtftp6 is started to download.
@retval Others Failed to start to download.
**/
EFI_STATUS
Mtftp6RrqStart (
IN MTFTP6_INSTANCE *Instance,
IN UINT16 Operation
)
{
EFI_STATUS Status;
//
// The valid block number range are [1, 0xffff]. For example:
// the client sends an RRQ request to the server, the server
// transfers the DATA1 block. If option negoitation is ongoing,
// the server will send back an OACK, then client will send ACK0.
//
Status = Mtftp6InitBlockRange (&Instance->BlkList, 1, 0xffff);
if (EFI_ERROR (Status)) {
return Status;
}
Status = Mtftp6SendRequest (Instance, Operation);
if (EFI_ERROR (Status)) {
return Status;
}
return UdpIoRecvDatagram (
Instance->UdpIo,
Mtftp6RrqInput,
Instance,
0
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,359 @@
/** @file
Mtftp6 support functions declaration.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_MTFTP6_SUPPORT_H__
#define __EFI_MTFTP6_SUPPORT_H__
//
// The structure representing a range of block numbers, [Start, End].
// It is used to remember the holes in the MTFTP block space. If all
// the holes are filled in, then the download or upload has completed.
//
typedef struct {
LIST_ENTRY Link;
INTN Start;
INTN End;
INTN Round;
INTN Bound;
} MTFTP6_BLOCK_RANGE;
/**
Initialize the block range for either RRQ or WRQ. RRQ and WRQ have
different requirements for Start and End. For example, during startup,
WRQ initializes its whole valid block range to [0, 0xffff]. This
is because the server will send an ACK0 to inform the user to start the
upload. When the client receives an ACK0, it will remove 0 from the range,
get the next block number, which is 1, then upload the BLOCK1. For RRQ
without option negotiation, the server will directly send us the BLOCK1
in response to the client's RRQ. When BLOCK1 is received, the client will
remove it from the block range and send an ACK. It also works if there
is option negotiation.
@param[in] Head The block range head to initialize.
@param[in] Start The Start block number.
@param[in] End The last block number.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for initial block range.
@retval EFI_SUCCESS The initial block range is created.
**/
EFI_STATUS
Mtftp6InitBlockRange (
IN LIST_ENTRY *Head,
IN UINT16 Start,
IN UINT16 End
);
/**
Get the first valid block number on the range list.
@param[in] Head The block range head.
@retval ==-1 If the block range is empty.
@retval >-1 The first valid block number.
**/
INTN
Mtftp6GetNextBlockNum (
IN LIST_ENTRY *Head
);
/**
Set the last block number of the block range list. It
removes all the blocks after the Last. MTFTP initialize the
block range to the maximum possible range, such as [0, 0xffff]
for WRQ. When it gets the last block number, it calls
this function to set the last block number.
@param[in] Head The block range list.
@param[in] Last The last block number.
**/
VOID
Mtftp6SetLastBlockNum (
IN LIST_ENTRY *Head,
IN UINT16 Last
);
/**
Remove the block number from the block range list.
@param[in] Head The block range list to remove from.
@param[in] Num The block number to remove.
@param[in] Completed Whether Num is the last block number
@param[out] TotalBlock The continuous block number in all
@retval EFI_NOT_FOUND The block number isn't in the block range list.
@retval EFI_SUCCESS The block number has been removed from the list.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
**/
EFI_STATUS
Mtftp6RemoveBlockNum (
IN LIST_ENTRY *Head,
IN UINT16 Num,
IN BOOLEAN Completed,
OUT UINT64 *TotalBlock
);
/**
Build and transmit the request packet for the Mtftp6 instance.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Operation The operation code of this packet.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the request.
@retval EFI_SUCCESS The request was built and sent.
@retval Others Failed to transmit the packet.
**/
EFI_STATUS
Mtftp6SendRequest (
IN MTFTP6_INSTANCE *Instance,
IN UINT16 Operation
);
/**
Build and send an error packet.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] ErrCode The error code in the packet.
@param[in] ErrInfo The error message in the packet.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the error packet.
@retval EFI_SUCCESS The error packet was transmitted.
@retval Others Failed to transmit the packet.
**/
EFI_STATUS
Mtftp6SendError (
IN MTFTP6_INSTANCE *Instance,
IN UINT16 ErrCode,
IN UINT8* ErrInfo
);
/**
Send the packet for the Mtftp6 instance.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Packet The pointer to the packet to be sent.
@retval EFI_SUCCESS The packet was sent out
@retval Others Failed to transmit the packet.
**/
EFI_STATUS
Mtftp6TransmitPacket (
IN MTFTP6_INSTANCE *Instance,
IN NET_BUF *Packet
);
/**
Check packet for GetInfo callback routine.
@param[in] This The pointer to the Mtftp6 protocol.
@param[in] Token The pointer to the Mtftp6 token.
@param[in] PacketLen The length of the packet
@param[in] Packet The pointer to the received packet.
@retval EFI_SUCCESS The check process passed successfully.
@retval EFI_ABORTED Abort the Mtftp6 operation.
**/
EFI_STATUS
EFIAPI
Mtftp6CheckPacket (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_TOKEN *Token,
IN UINT16 PacketLen,
IN EFI_MTFTP6_PACKET *Packet
);
/**
The dummy configure routine for create a new Udp6 Io.
@param[in] UdpIo The pointer to the Udp6 Io.
@param[in] Context The pointer to the context.
@retval EFI_SUCCESS The value is always returned.
**/
EFI_STATUS
EFIAPI
Mtftp6ConfigDummyUdpIo (
IN UDP_IO *UdpIo,
IN VOID *Context
);
/**
The configure routine for the Mtftp6 instance to transmit/receive.
@param[in] UdpIo The pointer to the Udp6 Io.
@param[in] ServerIp The pointer to the server address.
@param[in] ServerPort The pointer to the server port.
@param[in] LocalIp The pointer to the local address.
@param[in] LocalPort The pointer to the local port.
@retval EFI_SUCCESS Configure the Udp6 Io for Mtftp6 successfully.
@retval EFI_NO_MAPPING The corresponding Ip6 instance has not been
configured yet.
**/
EFI_STATUS
Mtftp6ConfigUdpIo (
IN UDP_IO *UdpIo,
IN EFI_IPv6_ADDRESS *ServerIp,
IN UINT16 ServerPort,
IN EFI_IPv6_ADDRESS *LocalIp,
IN UINT16 LocalPort
);
/**
Clean up the current Mtftp6 operation.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Result The result to be returned to the user.
**/
VOID
Mtftp6OperationClean (
IN MTFTP6_INSTANCE *Instance,
IN EFI_STATUS Result
);
/**
Start the Mtftp6 instance to perform the operation, such as read file,
write file, and read directory.
@param[in] This The MTFTP session
@param[in] Token The token that encapsulates the user's request.
@param[in] OpCode The operation to perform.
@retval EFI_INVALID_PARAMETER Some of the parameters are invalid.
@retval EFI_NOT_STARTED The MTFTP session hasn't been configured.
@retval EFI_ALREADY_STARTED There is pending operation for the session.
@retval EFI_SUCCESS The operation was successfully started.
**/
EFI_STATUS
Mtftp6OperationStart (
IN EFI_MTFTP6_PROTOCOL *This,
IN EFI_MTFTP6_TOKEN *Token,
IN UINT16 OpCode
);
/**
The timer ticking routine for the Mtftp6 instance.
@param[in] Event The pointer to the ticking event.
@param[in] Context The pointer to the context.
**/
VOID
EFIAPI
Mtftp6OnTimerTick (
IN EFI_EVENT Event,
IN VOID *Context
);
/**
The packet process callback for Mtftp6 upload.
@param[in] UdpPacket The pointer to the packet received.
@param[in] UdpEpt The pointer to the Udp6 access point.
@param[in] IoStatus The status from the Udp6 instance.
@param[in] Context The pointer to the context.
**/
VOID
EFIAPI
Mtftp6WrqInput (
IN NET_BUF *UdpPacket,
IN UDP_END_POINT *UdpEpt,
IN EFI_STATUS IoStatus,
IN VOID *Context
);
/**
Start the Mtftp6 instance to upload. It will first init some states,
then send the WRQ request packet, and start to receive the packet.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Operation The operation code of current packet.
@retval EFI_SUCCESS The Mtftp6 was started to upload.
@retval Others Failed to start to upload.
**/
EFI_STATUS
Mtftp6WrqStart (
IN MTFTP6_INSTANCE *Instance,
IN UINT16 Operation
);
/**
The packet process callback for Mtftp6 download.
@param[in] UdpPacket The pointer to the packet received.
@param[in] UdpEpt The pointer to the Udp6 access point.
@param[in] IoStatus The status from Udp6 instance.
@param[in] Context The pointer to the context.
**/
VOID
EFIAPI
Mtftp6RrqInput (
IN NET_BUF *UdpPacket,
IN UDP_END_POINT *UdpEpt,
IN EFI_STATUS IoStatus,
IN VOID *Context
);
/**
Start the Mtftp6 instance to download. It first initializes some
of the internal states then builds and sends an RRQ reqeuest packet.
Finally, it starts receive for the downloading.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Operation The operation code of current packet.
@retval EFI_SUCCESS The Mtftp6 was started to download.
@retval Others Failed to start to download.
**/
EFI_STATUS
Mtftp6RrqStart (
IN MTFTP6_INSTANCE *Instance,
IN UINT16 Operation
);
#endif

View File

@@ -0,0 +1,602 @@
/** @file
Mtftp6 Wrq process functions implementation.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Mtftp6Impl.h"
/**
Build and send a Mtftp6 data packet for upload.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] BlockNum The block num to be sent.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the packet.
@retval EFI_SUCCESS The data packet was sent.
@retval EFI_ABORTED The user aborted this process.
**/
EFI_STATUS
Mtftp6WrqSendBlock (
IN MTFTP6_INSTANCE *Instance,
IN UINT16 BlockNum
)
{
EFI_MTFTP6_PACKET *Packet;
EFI_MTFTP6_TOKEN *Token;
NET_BUF *UdpPacket;
EFI_STATUS Status;
UINT16 DataLen;
UINT8 *DataBuf;
UINT64 Start;
//
// Allocate net buffer to create data packet.
//
UdpPacket = NetbufAlloc (Instance->BlkSize + MTFTP6_DATA_HEAD_LEN);
if (UdpPacket == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Packet = (EFI_MTFTP6_PACKET *) NetbufAllocSpace (
UdpPacket,
MTFTP6_DATA_HEAD_LEN,
FALSE
);
ASSERT (Packet != NULL);
Packet->Data.OpCode = HTONS (EFI_MTFTP6_OPCODE_DATA);
Packet->Data.Block = HTONS (BlockNum);
//
// Read the block from either the buffer or PacketNeeded callback
//
Token = Instance->Token;
DataLen = Instance->BlkSize;
if (Token->Buffer != NULL) {
Start = MultU64x32 (BlockNum - 1, Instance->BlkSize);
if (Token->BufferSize < Start + Instance->BlkSize) {
DataLen = (UINT16) (Token->BufferSize - Start);
Instance->LastBlk = BlockNum;
Mtftp6SetLastBlockNum (&Instance->BlkList, BlockNum);
}
if (DataLen > 0) {
NetbufAllocSpace (UdpPacket, DataLen, FALSE);
CopyMem (Packet->Data.Data, (UINT8 *) Token->Buffer + Start, DataLen);
}
} else {
//
// Get data from PacketNeeded
//
DataBuf = NULL;
Status = Token->PacketNeeded (&Instance->Mtftp6, Token, &DataLen, (VOID*) &DataBuf);
if (EFI_ERROR (Status) || (DataLen > Instance->BlkSize)) {
if (DataBuf != NULL) {
gBS->FreePool (DataBuf);
}
//
// The received packet has already been freed.
//
Mtftp6SendError (
Instance,
EFI_MTFTP6_ERRORCODE_REQUEST_DENIED,
(UINT8 *) "User aborted the transfer"
);
return EFI_ABORTED;
}
if (DataLen < Instance->BlkSize) {
Instance->LastBlk = BlockNum;
Mtftp6SetLastBlockNum (&Instance->BlkList, BlockNum);
}
if (DataLen > 0) {
NetbufAllocSpace (UdpPacket, DataLen, FALSE);
CopyMem (Packet->Data.Data, DataBuf, DataLen);
gBS->FreePool (DataBuf);
}
}
//
// Reset current retry count of the instance.
//
Instance->CurRetry = 0;
return Mtftp6TransmitPacket (Instance, UdpPacket);
}
/**
Function to handle received ACK packet. If the ACK number matches the
expected block number, with more data pending, send the next
block. Otherwise, tell the caller that we are done.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Packet The pointer to the received packet.
@param[in] Len The length of the packet.
@param[out] UdpPacket The net buf of received packet.
@param[out] IsCompleted If TRUE, the upload has been completed.
Otherwise, the upload has not been completed.
@retval EFI_SUCCESS The ACK packet successfully processed.
@retval EFI_TFTP_ERROR The block number loops back.
@retval Others Failed to transmit the next data packet.
**/
EFI_STATUS
Mtftp6WrqHandleAck (
IN MTFTP6_INSTANCE *Instance,
IN EFI_MTFTP6_PACKET *Packet,
IN UINT32 Len,
OUT NET_BUF **UdpPacket,
OUT BOOLEAN *IsCompleted
)
{
UINT16 AckNum;
INTN Expected;
UINT64 TotalBlock;
*IsCompleted = FALSE;
AckNum = NTOHS (Packet->Ack.Block[0]);
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
ASSERT (Expected >= 0);
//
// Get an unwanted ACK, return EFI_SUCCESS to let Mtftp6WrqInput
// restart receive.
//
if (Expected != AckNum) {
return EFI_SUCCESS;
}
//
// Remove the acked block number, if this is the last block number,
// tell the Mtftp6WrqInput to finish the transfer. This is the last
// block number if the block range are empty..
//
Mtftp6RemoveBlockNum (&Instance->BlkList, AckNum, *IsCompleted, &TotalBlock);
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
if (Expected < 0) {
//
// The block range is empty. It may either because the the last
// block has been ACKed, or the sequence number just looped back,
// that is, there is more than 0xffff blocks.
//
if (Instance->LastBlk == AckNum) {
ASSERT (Instance->LastBlk >= 1);
*IsCompleted = TRUE;
return EFI_SUCCESS;
} else {
//
// Free the received packet before send new packet in ReceiveNotify,
// since the udpio might need to be reconfigured.
//
NetbufFree (*UdpPacket);
*UdpPacket = NULL;
//
// Send the Mtftp6 error message if block number rolls back.
//
Mtftp6SendError (
Instance,
EFI_MTFTP6_ERRORCODE_REQUEST_DENIED,
(UINT8 *) "Block number rolls back, not supported, try blksize option"
);
return EFI_TFTP_ERROR;
}
}
//
// Free the receive buffer before send new packet since it might need
// reconfigure udpio.
//
NetbufFree (*UdpPacket);
*UdpPacket = NULL;
return Mtftp6WrqSendBlock (Instance, (UINT16) Expected);
}
/**
Check whether the received OACK is valid. The OACK is valid
only if:
1. It only include options requested by us.
2. It can only include a smaller block size.
3. It can't change the proposed time out value.
4. Other requirements of the individal MTFTP6 options as required.
@param[in] ReplyInfo The pointer to options information in reply packet.
@param[in] RequestInfo The pointer to requested options information.
@retval TRUE If the option in OACK is valid.
@retval FALSE If the option is invalid.
**/
BOOLEAN
Mtftp6WrqOackValid (
IN MTFTP6_EXT_OPTION_INFO *ReplyInfo,
IN MTFTP6_EXT_OPTION_INFO *RequestInfo
)
{
//
// It is invalid for server to return options we don't request
//
if ((ReplyInfo->BitMap & ~RequestInfo->BitMap) != 0) {
return FALSE;
}
//
// Server can only specify a smaller block size to be used and
// return the timeout matches that requested.
//
if ((((ReplyInfo->BitMap & MTFTP6_OPT_BLKSIZE_BIT) != 0) && (ReplyInfo->BlkSize > RequestInfo->BlkSize)) ||
(((ReplyInfo->BitMap & MTFTP6_OPT_TIMEOUT_BIT) != 0) && (ReplyInfo->Timeout != RequestInfo->Timeout))
) {
return FALSE;
}
return TRUE;
}
/**
Process the OACK packet for Wrq.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Packet The pointer to the received packet.
@param[in] Len The length of the packet.
@param[out] UdpPacket The net buf of received packet.
@param[out] IsCompleted If TRUE, the upload has been completed.
Otherwise, the upload has not been completed.
@retval EFI_SUCCESS The OACK packet successfully processed.
@retval EFI_TFTP_ERROR An TFTP communication error happened.
@retval Others Failed to process the OACK packet.
**/
EFI_STATUS
Mtftp6WrqHandleOack (
IN MTFTP6_INSTANCE *Instance,
IN EFI_MTFTP6_PACKET *Packet,
IN UINT32 Len,
OUT NET_BUF **UdpPacket,
OUT BOOLEAN *IsCompleted
)
{
EFI_MTFTP6_OPTION *Options;
UINT32 Count;
MTFTP6_EXT_OPTION_INFO ExtInfo;
EFI_MTFTP6_PACKET Dummy;
EFI_STATUS Status;
INTN Expected;
*IsCompleted = FALSE;
//
// Ignore the OACK if already started the upload
//
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
if (Expected != 0) {
return EFI_SUCCESS;
}
//
// Parse and validate the options from server
//
ZeroMem (&ExtInfo, sizeof (MTFTP6_EXT_OPTION_INFO));
Status = Mtftp6ParseStart (Packet, Len, &Count, &Options);
if (EFI_ERROR (Status)) {
return Status;
}
Status = Mtftp6ParseExtensionOption (Options, Count, FALSE, &ExtInfo);
if (EFI_ERROR(Status) || !Mtftp6WrqOackValid (&ExtInfo, &Instance->ExtInfo)) {
//
// Don't send a MTFTP error packet when out of resource, it can
// only make it worse.
//
if (Status != EFI_OUT_OF_RESOURCES) {
//
// Free the received packet before send new packet in ReceiveNotify,
// since the udpio might need to be reconfigured.
//
NetbufFree (*UdpPacket);
*UdpPacket = NULL;
//
// Send the Mtftp6 error message if invalid Oack packet received.
//
Mtftp6SendError (
Instance,
EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
(UINT8 *) "Mal-formated OACK packet"
);
}
return EFI_TFTP_ERROR;
}
if (ExtInfo.BlkSize != 0) {
Instance->BlkSize = ExtInfo.BlkSize;
}
if (ExtInfo.Timeout != 0) {
Instance->Timeout = ExtInfo.Timeout;
}
//
// Build a bogus ACK0 packet then pass it to the Mtftp6WrqHandleAck,
// which will start the transmission of the first data block.
//
Dummy.Ack.OpCode = HTONS (EFI_MTFTP6_OPCODE_ACK);
Dummy.Ack.Block[0] = 0;
return Mtftp6WrqHandleAck (
Instance,
&Dummy,
sizeof (EFI_MTFTP6_ACK_HEADER),
UdpPacket,
IsCompleted
);
}
/**
The packet process callback for Mtftp6 upload.
@param[in] UdpPacket The pointer to the packet received.
@param[in] UdpEpt The pointer to the Udp6 access point.
@param[in] IoStatus The status from Udp6 instance.
@param[in] Context The pointer to the context.
**/
VOID
EFIAPI
Mtftp6WrqInput (
IN NET_BUF *UdpPacket,
IN UDP_END_POINT *UdpEpt,
IN EFI_STATUS IoStatus,
IN VOID *Context
)
{
MTFTP6_INSTANCE *Instance;
EFI_MTFTP6_PACKET *Packet;
BOOLEAN IsCompleted;
EFI_STATUS Status;
UINT32 TotalNum;
UINT32 Len;
UINT16 Opcode;
Instance = (MTFTP6_INSTANCE *) Context;
NET_CHECK_SIGNATURE (Instance, MTFTP6_INSTANCE_SIGNATURE);
IsCompleted = FALSE;
Packet = NULL;
Status = EFI_SUCCESS;
TotalNum = 0;
//
// Return error status if Udp6 instance failed to receive.
//
if (EFI_ERROR (IoStatus)) {
Status = IoStatus;
goto ON_EXIT;
}
ASSERT (UdpPacket != NULL);
if (UdpPacket->TotalSize < MTFTP6_OPCODE_LEN) {
goto ON_EXIT;
}
//
// Client send initial request to server's listening port. Server
// will select a UDP port to communicate with the client.
//
if (UdpEpt->RemotePort != Instance->ServerDataPort) {
if (Instance->ServerDataPort != 0) {
goto ON_EXIT;
} else {
Instance->ServerDataPort = UdpEpt->RemotePort;
}
}
//
// Copy the MTFTP packet to a continuous buffer if it isn't already so.
//
Len = UdpPacket->TotalSize;
TotalNum = UdpPacket->BlockOpNum;
if (TotalNum > 1) {
Packet = AllocateZeroPool (Len);
if (Packet == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet);
} else {
Packet = (EFI_MTFTP6_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);
ASSERT (Packet != NULL);
}
Opcode = NTOHS (Packet->OpCode);
//
// Callback to the user's CheckPacket if provided. Abort the transmission
// if CheckPacket returns an EFI_ERROR code.
//
if (Instance->Token->CheckPacket != NULL &&
(Opcode == EFI_MTFTP6_OPCODE_OACK || Opcode == EFI_MTFTP6_OPCODE_ERROR)
) {
Status = Instance->Token->CheckPacket (
&Instance->Mtftp6,
Instance->Token,
(UINT16) Len,
Packet
);
if (EFI_ERROR (Status)) {
//
// Send an error message to the server to inform it
//
if (Opcode != EFI_MTFTP6_OPCODE_ERROR) {
//
// Free the received packet before send new packet in ReceiveNotify,
// since the udpio might need to be reconfigured.
//
NetbufFree (UdpPacket);
UdpPacket = NULL;
//
// Send the Mtftp6 error message if user aborted the current session.
//
Mtftp6SendError (
Instance,
EFI_MTFTP6_ERRORCODE_REQUEST_DENIED,
(UINT8 *) "User aborted the transfer"
);
}
Status = EFI_ABORTED;
goto ON_EXIT;
}
}
//
// Switch the process routines by the operation code.
//
switch (Opcode) {
case EFI_MTFTP6_OPCODE_ACK:
if (Len != MTFTP6_OPCODE_LEN + MTFTP6_BLKNO_LEN) {
goto ON_EXIT;
}
//
// Handle the Ack packet of Wrq.
//
Status = Mtftp6WrqHandleAck (Instance, Packet, Len, &UdpPacket, &IsCompleted);
break;
case EFI_MTFTP6_OPCODE_OACK:
if (Len <= MTFTP6_OPCODE_LEN) {
goto ON_EXIT;
}
//
// Handle the Oack packet of Wrq.
//
Status = Mtftp6WrqHandleOack (Instance, Packet, Len, &UdpPacket, &IsCompleted);
break;
default:
//
// Drop and return eror if received error message.
//
Status = EFI_TFTP_ERROR;
break;
}
ON_EXIT:
//
// Free the resources, then if !EFI_ERROR (Status) and not completed,
// restart the receive, otherwise end the session.
//
if (Packet != NULL && TotalNum > 1) {
FreePool (Packet);
}
if (UdpPacket != NULL) {
NetbufFree (UdpPacket);
}
if (!EFI_ERROR (Status) && !IsCompleted) {
Status = UdpIoRecvDatagram (
Instance->UdpIo,
Mtftp6WrqInput,
Instance,
0
);
}
//
// Clean up the current session if failed to continue.
//
if (EFI_ERROR (Status) || IsCompleted) {
Mtftp6OperationClean (Instance, Status);
}
}
/**
Start the Mtftp6 instance to upload. It will first init some states,
then send the WRQ request packet, and start to receive the packet.
@param[in] Instance The pointer to the Mtftp6 instance.
@param[in] Operation The operation code of the current packet.
@retval EFI_SUCCESS The Mtftp6 was started to upload.
@retval Others Failed to start to upload.
**/
EFI_STATUS
Mtftp6WrqStart (
IN MTFTP6_INSTANCE *Instance,
IN UINT16 Operation
)
{
EFI_STATUS Status;
//
// The valid block number range are [0, 0xffff]. For example:
// the client sends an WRQ request to the server, the server
// ACK with an ACK0 to let client start transfer the first
// packet.
//
Status = Mtftp6InitBlockRange (&Instance->BlkList, 0, 0xffff);
if (EFI_ERROR (Status)) {
return Status;
}
Status = Mtftp6SendRequest (Instance, Operation);
if (EFI_ERROR (Status)) {
return Status;
}
return UdpIoRecvDatagram (
Instance->UdpIo,
Mtftp6WrqInput,
Instance,
0
);
}

21
NetworkPkg/NetworkPkg.dec Normal file
View File

@@ -0,0 +1,21 @@
## @file
#
# This package provides network modules that conform to UEFI 2.2 specification.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available under
# the terms and conditions of the BSD License which accompanies this distribution.
# The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
DEC_SPECIFICATION = 0x00010005
PACKAGE_NAME = NetworkPkg
PACKAGE_GUID = 947988BE-8D5C-471a-893D-AD181C46BEBB
PACKAGE_VERSION = 0.92

95
NetworkPkg/NetworkPkg.dsc Normal file
View File

@@ -0,0 +1,95 @@
## @file
# UEFI 2.2 Network Module Package for All Architectures
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
PLATFORM_NAME = NetworkPkg
PLATFORM_GUID = 3FD34E9B-E90C-44e1-B510-1F632A509F10
PLATFORM_VERSION = 0.92
DSC_SPECIFICATION = 0x00010005
OUTPUT_DIRECTORY = Build/NetworkPkg
SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC|ARM
BUILD_TARGETS = DEBUG|RELEASE
SKUID_IDENTIFIER = DEFAULT
[LibraryClasses]
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf
UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
[LibraryClasses.common.UEFI_DRIVER]
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
[LibraryClasses.common.UEFI_APPLICATION]
DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
FileHandleLib|ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf
ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
[PcdsFeatureFlag]
gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE
gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE
[PcdsFixedAtBuild]
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2f
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000
###################################################################################################
#
# Components Section - list of the modules and components that will be processed by compilation
# tools and the EDK II tools to generate PE32/PE32+/Coff image files.
#
# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
# into firmware volume images. This section is just a list of modules to compile from
# source into UEFI-compliant binaries.
# It is the FDF file that contains information on combining binary files into firmware
# volume images, whose concept is beyond UEFI and is described in PI specification.
# Binary modules do not need to be listed in this section, as they should be
# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),
# Logo (Logo.bmp), and etc.
# There may also be modules listed in this section that are not required in the FDF file,
# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
# generated for it, but the binary will not be put into any firmware volume.
#
###################################################################################################
[Components]
NetworkPkg/IpSecDxe/IpSecDxe.inf
NetworkPkg/Ip6Dxe/Ip6Dxe.inf
NetworkPkg/TcpDxe/TcpDxe.inf
NetworkPkg/Udp6Dxe/Udp6Dxe.inf
NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf
NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf
[Components.IA32, Components.X64, Components.IPF]
NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf
NetworkPkg/Application/Ping6/Ping6.inf
NetworkPkg/Application/IfConfig6/IfConfig6.inf
NetworkPkg/Application/IpsecConfig/IpSecConfig.inf
NetworkPkg/Application/VConfig/VConfig.inf

View File

@@ -0,0 +1,304 @@
/** @file
Implementation of protocols EFI_COMPONENT_NAME_PROTOCOL and
EFI_COMPONENT_NAME2_PROTOCOL.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "TcpMain.h"
//
// EFI Component Name Functions
//
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This, and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language or DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
TcpComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is being managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language, from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language or ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
TcpComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
///
/// EFI Component Name Protocol
///
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gTcpComponentName = {
TcpComponentNameGetDriverName,
TcpComponentNameGetControllerName,
"eng"
};
///
/// EFI Component Name 2 Protocol
///
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gTcpComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) TcpComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) TcpComponentNameGetControllerName,
"en"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mTcpDriverNameTable[] = {
{
"eng;en",
L"TCP Network Service Driver"
},
{
NULL,
NULL
}
};
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This, and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language or DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
TcpComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mTcpDriverNameTable,
DriverName,
(BOOLEAN) (This == &gTcpComponentName)
);
}
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is being managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language, from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language or ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
TcpComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
return EFI_UNSUPPORTED;
}

Some files were not shown because too many files have changed in this diff Show More