/** @file\r
Transmit the IP4 packet.\r
- \r
-Copyright (c) 2005 - 2009, Intel Corporation.<BR>\r
-All rights reserved. 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
-http://opensource.org/licenses/bsd-license.php\r
\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
@retval EFI_NO_MAPPING There is no interface to the destination.\r
@retval EFI_NOT_FOUND There is no route to the destination\r
@retval EFI_SUCCESS The packet is successfully transmitted.\r
+ @retval EFI_BAD_BUFFER_SIZE The length of the IPv4 header + option length +\r
+ total data length is greater than MTU (or greater\r
+ than the maximum packet size if Token.Packet.TxData.\r
+ OverrideData.DoNotFragment is TRUE.)\r
@retval Others Failed to transmit the packet.\r
\r
**/\r
UINT32 Offset;\r
UINT32 Mtu;\r
UINT32 Num;\r
+ BOOLEAN RawData;\r
\r
//\r
// Select an interface/source for system packet, application\r
}\r
\r
//\r
- // Route the packet unless overrided, that is, GateWay isn't zero.\r
+ // Before IPsec process, prepared the IP head.\r
+ // If Ip4Output is transmitting RawData, don't update IPv4 header.\r
//\r
- if (GateWay == IP4_ALLZERO_ADDRESS) {\r
- Dest = Head->Dst;\r
+ HeadLen = sizeof (IP4_HEAD) + ((OptLen + 3) & (~0x03));\r
\r
- if (IP4_IS_BROADCAST (Ip4GetNetCast (Dest, IpIf)) || (Dest == IP4_ALLONE_ADDRESS)) {\r
- //\r
- // Set the gateway to local broadcast if the Dest is\r
- // the broadcast address for the connected network or\r
- // it is local broadcast.\r
- //\r
- GateWay = IP4_ALLONE_ADDRESS;\r
-\r
- } else if (IP4_IS_MULTICAST (Dest)) {\r
- //\r
- // Set the gateway to the destination if it is an multicast\r
- // address. The IP4_INTERFACE won't consult ARP to send local\r
- // broadcast and multicast.\r
- //\r
- GateWay = Head->Dst;\r
-\r
- } else {\r
- //\r
- // Consult the route table to route the packet\r
- //\r
- if (IpInstance == NULL) {\r
- CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src);\r
- } else {\r
- CacheEntry = Ip4Route (IpInstance->RouteTable, Head->Dst, Head->Src);\r
- }\r
-\r
- if (CacheEntry == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- GateWay = CacheEntry->NextHop;\r
- Ip4FreeRouteCacheEntry (CacheEntry);\r
- }\r
+ if ((IpInstance != NULL) && IpInstance->ConfigData.RawData) {\r
+ RawData = TRUE;\r
+ } else {\r
+ Head->HeadLen = (UINT8) (HeadLen >> 2);\r
+ Head->Id = mIp4Id++;\r
+ Head->Ver = 4;\r
+ RawData = FALSE;\r
}\r
\r
//\r
- // TODO: currently Option/OptLen are not included into encryption scope.\r
+ // Call IPsec process.\r
//\r
Status = Ip4IpSecProcessPacket (\r
- IpSb, \r
- Head, \r
- &Packet, \r
- Option, \r
- OptLen, \r
+ IpSb,\r
+ &Head,\r
+ &Packet,\r
+ &Option,\r
+ &OptLen,\r
EfiIPsecOutBound,\r
Context\r
);\r
return Status;\r
}\r
\r
+ Dest = Head->Dst;\r
+ if (IP4_IS_BROADCAST (Ip4GetNetCast (Dest, IpIf)) || (Dest == IP4_ALLONE_ADDRESS)) {\r
+ //\r
+ // Set the gateway to local broadcast if the Dest is\r
+ // the broadcast address for the connected network or\r
+ // it is local broadcast.\r
+ //\r
+ GateWay = IP4_ALLONE_ADDRESS;\r
+\r
+ } else if (IP4_IS_MULTICAST (Dest)) {\r
+ //\r
+ // Set the gateway to the destination if it is an multicast\r
+ // address. The IP4_INTERFACE won't consult ARP to send local\r
+ // broadcast and multicast.\r
+ //\r
+ GateWay = Head->Dst;\r
+\r
+ } else if (GateWay == IP4_ALLZERO_ADDRESS) {\r
+ //\r
+ // Route the packet unless overrided, that is, GateWay isn't zero.\r
+ //\r
+ if (IpInstance == NULL) {\r
+ CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, TRUE);\r
+ } else {\r
+ CacheEntry = Ip4Route (IpInstance->RouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, FALSE);\r
+ //\r
+ // If failed to route the packet by using the instance's route table,\r
+ // try to use the default route table.\r
+ //\r
+ if (CacheEntry == NULL) {\r
+ CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, TRUE);\r
+ }\r
+ }\r
+\r
+ if (CacheEntry == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ GateWay = CacheEntry->NextHop;\r
+ Ip4FreeRouteCacheEntry (CacheEntry);\r
+ }\r
+\r
//\r
// OK, selected the source and route, fragment the packet then send\r
// them. Tag each fragment other than the first one as spawn from it.\r
//\r
- Mtu = IpSb->MaxPacketSize;\r
- HeadLen = sizeof (IP4_HEAD) + ((OptLen + 3) & (~0x03));\r
- Head->Id = mIp4Id++;\r
+ Mtu = IpSb->MaxPacketSize + sizeof (IP4_HEAD);\r
\r
if (Packet->TotalSize + HeadLen > Mtu) {\r
+ //\r
+ // Fragmentation is diabled for RawData mode.\r
+ //\r
+ if (RawData) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
//\r
// Packet is fragmented from the tail to the head, that is, the\r
// first frame sent is the last fragment of the packet. The first\r
Fragment,\r
GateWay,\r
Ip4SysPacketSent,\r
- Packet\r
+ Packet,\r
+ IpSb\r
);\r
\r
if (EFI_ERROR (Status)) {\r
// upper layer's packets.\r
//\r
Ip4PrependHead (Packet, Head, Option, OptLen);\r
- Status = Ip4SendFrame (IpIf, IpInstance, Packet, GateWay, Callback, Context);\r
+ Status = Ip4SendFrame (IpIf, IpInstance, Packet, GateWay, Callback, Context, IpSb);\r
\r
if (EFI_ERROR (Status)) {\r
goto ON_ERROR;\r