4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Implementation of I/O interfaces between TCP and IpIoLib.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync are licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "TcpMain.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet receive callback function provided to IP_IO, used to call
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the proper function to handle the packet received by IP.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Status Result of the receive request.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IcmpErr Valid when Status is EFI_ICMP_ERROR.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] NetSession The IP session for the received packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Pkt Packet received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context The data provided by the user for the received packet when
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the callback is registered in IP_IO_OPEN_DATA::RcvdContext.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This is an optional parameter that may be NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpRxCallback (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_STATUS Status,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 IcmpErr,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_NET_SESSION_DATA *NetSession,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Pkt,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_SUCCESS == Status) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpInput (Pkt, &NetSession->Source, &NetSession->Dest, NetSession->IpVersion);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpIcmpInput (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pkt,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpErr,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NetSession->Source,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NetSession->Dest,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetSession->IpVersion
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send the segment to IP via IpIo function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Nbuf Pointer to the TCP segment to be sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Src Source address of the TCP segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Dest Destination address of the TCP segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Version IP_VERSION_4 or IP_VERSION_6
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 The segment was sent out successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval -1 The segment failed to send.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpSendIpPacket (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Nbuf,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP_ADDRESS *Src,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP_ADDRESS *Dest,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 Version
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP_IO *IpIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP_IO_OVERRIDE Override;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SOCKET *Sock;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID *IpSender;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_PROTO_DATA *TcpProto;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NULL == Tcb) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIo = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSender = IpIoFindSender (&IpIo, Version, Src);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IpSender == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_WARN, "TcpSendIpPacket: No appropriate IpSender.\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Version == IP_VERSION_6) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // It's tricky here. EFI IPv6 Spec don't allow an instance overriding the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // destination address if the dest is already specified through the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // configuration data. Here we get the IpIo we need and use the default IP
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // instance in this IpIo to send the packet. The dest address is configured
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // to be the unspecified address for the default IP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSender = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Sock = Tcb->Sk;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIo = TcpProto->TcpService->IpIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSender = Tcb->IpInfo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Version == IP_VERSION_6) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // It's IPv6 and this TCP segment belongs to a solid TCB, in such case
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the destination address can't be overridden, so reset the Dest to NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dest = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Version == IpIo->IpVersion);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Version == IP_VERSION_4) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Override.Ip4OverrideData.TypeOfService = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Override.Ip4OverrideData.TimeToLive = 255;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Override.Ip4OverrideData.DoNotFragment = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Override.Ip4OverrideData.Protocol = EFI_IP_PROTO_TCP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (&Override.Ip4OverrideData.GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&Override.Ip4OverrideData.SourceAddress, Src, sizeof (EFI_IPv4_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Override.Ip6OverrideData.Protocol = EFI_IP_PROTO_TCP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Override.Ip6OverrideData.HopLimit = 255;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Override.Ip6OverrideData.FlowLabel = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IpIoSend (IpIo, Nbuf, IpSender, NULL, NULL, Dest, &Override);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_ERROR, "TcpSendIpPacket: return %r error\n", Status));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Refresh the remote peer's Neighbor Cache State if already exists.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Neighbor Source address of the TCP segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Timeout Time in 100-ns units that this entry will remain
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync in the neighbor cache. A value of zero means that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the entry is permanent. A value of non-zero means
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync that the entry is dynamic and will be deleted
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync after Timeout.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Successfully updated the neighbor relationship.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NOT_STARTED The IpIo is not configured.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NOT_FOUND This entry is not in the neighbor table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcp6RefreshNeighbor (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP_ADDRESS *Neighbor,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Timeout
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP_IO *IpIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SOCKET *Sock;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_PROTO_DATA *TcpProto;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NULL == Tcb) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIo = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIoFindSender (&IpIo, IP_VERSION_6, Neighbor);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IpIo == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_WARN, "Tcp6AddNeighbor: No appropriate IpIo.\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_NOT_STARTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Sock = Tcb->Sk;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIo = TcpProto->TcpService->IpIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return IpIoRefreshNeighbor (IpIo, Neighbor, Timeout);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync