/** @file\r
\r
-Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
\r
#include "Ip4Impl.h"\r
\r
-EFI_IPSEC_PROTOCOL *mIpSec = NULL;\r
+EFI_IPSEC2_PROTOCOL *mIpSec = NULL;\r
\r
/**\r
Gets the current operational settings for this instance of the EFI IPv4 Protocol driver.\r
IP4_ADDR SubnetMask;\r
IP4_ADDR SubnetAddress;\r
IP4_ADDR GatewayAddress;\r
+ IP4_PROTOCOL *Ip4Instance;\r
+ EFI_ARP_PROTOCOL *Arp;\r
+ LIST_ENTRY *Entry;\r
\r
IpSb = (IP4_SERVICE *) Context;\r
NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
StationAddress = EFI_NTOHL (Data->StationAddress);\r
SubnetMask = EFI_NTOHL (Data->SubnetMask);\r
Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask);\r
-\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
}\r
\r
+ if (IpIf->Arp != NULL) {\r
+ // \r
+ // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address, \r
+ // but some IP children may have referenced the default interface before it is configured,\r
+ // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER.\r
+ //\r
+ Arp = NULL;\r
+ NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {\r
+ Ip4Instance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, AddrLink, IP4_PROTOCOL_SIGNATURE);\r
+ Status = gBS->OpenProtocol (\r
+ IpIf->ArpHandle,\r
+ &gEfiArpProtocolGuid,\r
+ (VOID **) &Arp,\r
+ gIp4DriverBinding.DriverBindingHandle,\r
+ Ip4Instance->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ }\r
+ }\r
+\r
Ip4AddRoute (\r
IpSb->DefaultRouteTable,\r
StationAddress,\r
EFI_STATUS Status;\r
IP4_ADDR Ip;\r
IP4_ADDR Netmask;\r
+ EFI_ARP_PROTOCOL *Arp;\r
\r
IpSb = IpInstance->Service;\r
\r
}\r
\r
IpInstance->Interface = IpIf;\r
+ if (IpIf->Arp != NULL) {\r
+ Arp = NULL;\r
+ Status = gBS->OpenProtocol (\r
+ IpIf->ArpHandle,\r
+ &gEfiArpProtocolGuid,\r
+ (VOID **) &Arp,\r
+ gIp4DriverBinding.DriverBindingHandle,\r
+ IpInstance->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ }\r
InsertTailList (&IpIf->IpInstances, &IpInstance->AddrLink);\r
\r
CopyMem (&IpInstance->ConfigData, Config, sizeof (IpInstance->ConfigData));\r
\r
if (IpInstance->Interface != NULL) {\r
RemoveEntryList (&IpInstance->AddrLink);\r
+ if (IpInstance->Interface->Arp != NULL) {\r
+ gBS->CloseProtocol (\r
+ IpInstance->Interface->ArpHandle,\r
+ &gEfiArpProtocolGuid,\r
+ gIp4DriverBinding.DriverBindingHandle,\r
+ IpInstance->Handle\r
+ );\r
+ }\r
Ip4FreeInterface (IpInstance->Interface, IpInstance);\r
IpInstance->Interface = NULL;\r
}\r
// Validate the configuration first.\r
//\r
if (IpConfigData != NULL) {\r
- //\r
- // This implementation doesn't support RawData\r
- //\r
- if (IpConfigData->RawData) {\r
- Status = EFI_UNSUPPORTED;\r
- goto ON_EXIT;\r
- }\r
-\r
\r
CopyMem (&IpAddress, &IpConfigData->StationAddress, sizeof (IP4_ADDR));\r
CopyMem (&SubnetMask, &IpConfigData->SubnetMask, sizeof (IP4_ADDR));\r
Status = Ip4CleanProtocol (IpInstance);\r
\r
//\r
- // Don't change the state if it is DESTORY, consider the following\r
+ // Don't change the state if it is DESTROY, consider the following\r
// valid sequence: Mnp is unloaded-->Ip Stopped-->Udp Stopped,\r
// Configure (ThisIp, NULL). If the state is changed to UNCONFIGED,\r
// the unload fails miserably.\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Validate the user's token against current station address.\r
\r
- @param[in] Token User's token to validate\r
- @param[in] IpIf The IP4 child's interface.\r
+ @param[in] Token User's token to validate.\r
+ @param[in] IpIf The IP4 child's interface.\r
+ @param[in] RawData Set to TRUE to send unformatted packets.\r
\r
- @retval EFI_INVALID_PARAMETER Some parameters are invalid\r
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
@retval EFI_BAD_BUFFER_SIZE The user's option/data is too long.\r
- @retval EFI_SUCCESS The token is OK\r
+ @retval EFI_SUCCESS The token is valid.\r
\r
**/\r
EFI_STATUS\r
Ip4TxTokenValid (\r
IN EFI_IP4_COMPLETION_TOKEN *Token,\r
- IN IP4_INTERFACE *IpIf\r
+ IN IP4_INTERFACE *IpIf,\r
+ IN BOOLEAN RawData\r
)\r
{\r
EFI_IP4_TRANSMIT_DATA *TxData;\r
TxData = Token->Packet.TxData;\r
\r
//\r
- // Check the IP options: no more than 40 bytes and format is OK\r
- //\r
- if (TxData->OptionsLength != 0) {\r
- if ((TxData->OptionsLength > 40) || (TxData->OptionsBuffer == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (!Ip4OptionIsValid (TxData->OptionsBuffer, TxData->OptionsLength, FALSE)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- //\r
- // Check the fragment table: no empty fragment, and length isn't bogus\r
+ // Check the fragment table: no empty fragment, and length isn't bogus.\r
//\r
if ((TxData->TotalDataLength == 0) || (TxData->FragmentCount == 0)) {\r
return EFI_INVALID_PARAMETER;\r
\r
Offset = TxData->TotalDataLength;\r
\r
+ if (Offset > IP4_MAX_PACKET_SIZE) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
for (Index = 0; Index < TxData->FragmentCount; Index++) {\r
if ((TxData->FragmentTable[Index].FragmentBuffer == NULL) ||\r
(TxData->FragmentTable[Index].FragmentLength == 0)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ //\r
+ // NOTE that OptionsLength/OptionsBuffer/OverrideData are ignored if RawData\r
+ // is TRUE.\r
+ //\r
+ if (RawData) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Check the IP options: no more than 40 bytes and format is OK\r
+ //\r
+ if (TxData->OptionsLength != 0) {\r
+ if ((TxData->OptionsLength > 40) || (TxData->OptionsBuffer == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!Ip4OptionIsValid (TxData->OptionsBuffer, TxData->OptionsLength, FALSE)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
//\r
// Check the source and gateway: they must be a valid unicast.\r
// Gateway must also be on the connected network.\r
EFI_TPL OldTpl;\r
BOOLEAN DontFragment;\r
UINT32 HeadLen;\r
+ UINT8 RawHdrLen;\r
+ UINT32 OptionsLength;\r
+ UINT8 *OptionsBuffer;\r
+ VOID *FirstFragment;\r
\r
if (This == NULL) {\r
return EFI_INVALID_PARAMETER;\r
//\r
// make sure that token is properly formated\r
//\r
- Status = Ip4TxTokenValid (Token, IpIf);\r
+ Status = Ip4TxTokenValid (Token, IpIf, Config->RawData);\r
\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
//\r
TxData = Token->Packet.TxData;\r
\r
- CopyMem (&Head.Dst, &TxData->DestinationAddress, sizeof (IP4_ADDR));\r
- Head.Dst = NTOHL (Head.Dst);\r
+ FirstFragment = NULL;\r
\r
- if (TxData->OverrideData != NULL) {\r
- Override = TxData->OverrideData;\r
- Head.Protocol = Override->Protocol;\r
- Head.Tos = Override->TypeOfService;\r
- Head.Ttl = Override->TimeToLive;\r
- DontFragment = Override->DoNotFragment;\r
+ if (Config->RawData) {\r
+ //\r
+ // When RawData is TRUE, first buffer in FragmentTable points to a raw\r
+ // IPv4 fragment including IPv4 header and options.\r
+ //\r
+ FirstFragment = TxData->FragmentTable[0].FragmentBuffer;\r
+ CopyMem (&RawHdrLen, FirstFragment, sizeof (UINT8));\r
\r
- CopyMem (&Head.Src, &Override->SourceAddress, sizeof (IP4_ADDR));\r
- CopyMem (&GateWay, &Override->GatewayAddress, sizeof (IP4_ADDR));\r
+ RawHdrLen = (UINT8) (RawHdrLen & 0x0f);\r
+ if (RawHdrLen < 5) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ RawHdrLen = (UINT8) (RawHdrLen << 2);\r
+ \r
+ CopyMem (&Head, FirstFragment, IP4_MIN_HEADLEN);\r
+\r
+ Ip4NtohHead (&Head);\r
+ HeadLen = 0;\r
+ DontFragment = IP4_DO_NOT_FRAGMENT (Head.Fragment);\r
+\r
+ if (!DontFragment) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ GateWay = IP4_ALLZERO_ADDRESS;\r
+\r
+ //\r
+ // Get IPv4 options from first fragment.\r
+ //\r
+ if (RawHdrLen == IP4_MIN_HEADLEN) {\r
+ OptionsLength = 0;\r
+ OptionsBuffer = NULL;\r
+ } else {\r
+ OptionsLength = RawHdrLen - IP4_MIN_HEADLEN;\r
+ OptionsBuffer = (UINT8 *) FirstFragment + IP4_MIN_HEADLEN;\r
+ }\r
\r
- Head.Src = NTOHL (Head.Src);\r
- GateWay = NTOHL (GateWay);\r
+ //\r
+ // Trim off IPv4 header and options from first fragment.\r
+ //\r
+ TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment + RawHdrLen;\r
+ TxData->FragmentTable[0].FragmentLength = TxData->FragmentTable[0].FragmentLength - RawHdrLen;\r
} else {\r
- Head.Src = IpIf->Ip;\r
- GateWay = IP4_ALLZERO_ADDRESS;\r
- Head.Protocol = Config->DefaultProtocol;\r
- Head.Tos = Config->TypeOfService;\r
- Head.Ttl = Config->TimeToLive;\r
- DontFragment = Config->DoNotFragment;\r
- }\r
+ CopyMem (&Head.Dst, &TxData->DestinationAddress, sizeof (IP4_ADDR));\r
+ Head.Dst = NTOHL (Head.Dst);\r
+\r
+ if (TxData->OverrideData != NULL) {\r
+ Override = TxData->OverrideData;\r
+ Head.Protocol = Override->Protocol;\r
+ Head.Tos = Override->TypeOfService;\r
+ Head.Ttl = Override->TimeToLive;\r
+ DontFragment = Override->DoNotFragment;\r
+\r
+ CopyMem (&Head.Src, &Override->SourceAddress, sizeof (IP4_ADDR));\r
+ CopyMem (&GateWay, &Override->GatewayAddress, sizeof (IP4_ADDR));\r
+\r
+ Head.Src = NTOHL (Head.Src);\r
+ GateWay = NTOHL (GateWay);\r
+ } else {\r
+ Head.Src = IpIf->Ip;\r
+ GateWay = IP4_ALLZERO_ADDRESS;\r
+ Head.Protocol = Config->DefaultProtocol;\r
+ Head.Tos = Config->TypeOfService;\r
+ Head.Ttl = Config->TimeToLive;\r
+ DontFragment = Config->DoNotFragment;\r
+ }\r
+\r
+ Head.Fragment = IP4_HEAD_FRAGMENT_FIELD (DontFragment, FALSE, 0);\r
+ HeadLen = (TxData->OptionsLength + 3) & (~0x03);\r
\r
- Head.Fragment = IP4_HEAD_FRAGMENT_FIELD (DontFragment, FALSE, 0);\r
- HeadLen = (TxData->OptionsLength + 3) & (~0x03);\r
+ OptionsLength = TxData->OptionsLength;\r
+ OptionsBuffer = (UINT8 *) (TxData->OptionsBuffer);\r
+ }\r
\r
//\r
// If don't fragment and fragment needed, return error\r
// free the IP4_TXTOKEN_WRAP. Now, the token wrap hasn't been\r
// enqueued.\r
//\r
+ if (Config->RawData) {\r
+ //\r
+ // Restore pointer of first fragment in RawData mode.\r
+ //\r
+ TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment;\r
+ }\r
+\r
NetbufFree (Wrap->Packet);\r
goto ON_EXIT;\r
}\r
IpInstance,\r
Wrap->Packet,\r
&Head,\r
- TxData->OptionsBuffer,\r
- TxData->OptionsLength,\r
+ OptionsBuffer,\r
+ OptionsLength,\r
GateWay,\r
Ip4OnPacketSent,\r
Wrap\r
\r
if (EFI_ERROR (Status)) {\r
Wrap->Sent = FALSE;\r
+\r
+ if (Config->RawData) {\r
+ //\r
+ // Restore pointer of first fragment in RawData mode.\r
+ //\r
+ TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment;\r
+ }\r
+\r
NetbufFree (Wrap->Packet);\r
}\r
\r
+ if (Config->RawData) {\r
+ //\r
+ // Restore pointer of first fragment in RawData mode.\r
+ //\r
+ TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment;\r
+ }\r
+\r
ON_EXIT:\r
gBS->RestoreTPL (OldTpl);\r
return Status;\r