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
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
+ return EFI_INVALID_PARAMETER;\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
- Head.Src = NTOHL (Head.Src);\r
- GateWay = NTOHL (GateWay);\r
+ if (!DontFragment) {\r
+ return EFI_INVALID_PARAMETER;\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
+ //\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
- Head.Fragment = IP4_HEAD_FRAGMENT_FIELD (DontFragment, FALSE, 0);\r
- HeadLen = (TxData->OptionsLength + 3) & (~0x03);\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
+ 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