Signed-off-by: Ye Ting <ting.ye@intel.com> Reviewed-by: Ouyang Qian <qian.ouyang@intel.com> Reviewed-by: Fu Siyuan <siyuan.fu@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13606 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			193 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Implementation of I/O interfaces between TCP and IpIoLib.
 | 
						|
 | 
						|
  Copyright (c) 2009 - 2012, 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"
 | 
						|
 | 
						|
/**
 | 
						|
  Packet receive callback function provided to IP_IO, used to call
 | 
						|
  the proper function to handle the packet received by IP.
 | 
						|
 | 
						|
  @param[in] Status        Result of the receive request.
 | 
						|
  @param[in] IcmpErr       Valid when Status is EFI_ICMP_ERROR.
 | 
						|
  @param[in] NetSession    The IP session for the received packet.
 | 
						|
  @param[in] Pkt           Packet received.
 | 
						|
  @param[in] Context       The data provided by the user for the received packet when
 | 
						|
                           the callback is registered in IP_IO_OPEN_DATA::RcvdContext.
 | 
						|
                           This is an optional parameter that may be NULL.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
TcpRxCallback (
 | 
						|
  IN EFI_STATUS                       Status,
 | 
						|
  IN UINT8                            IcmpErr,
 | 
						|
  IN EFI_NET_SESSION_DATA             *NetSession,
 | 
						|
  IN NET_BUF                          *Pkt,
 | 
						|
  IN VOID                             *Context    OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (EFI_SUCCESS == Status) {
 | 
						|
    TcpInput (Pkt, &NetSession->Source, &NetSession->Dest, NetSession->IpVersion);
 | 
						|
  } else {
 | 
						|
    TcpIcmpInput (
 | 
						|
      Pkt,
 | 
						|
      IcmpErr,
 | 
						|
      &NetSession->Source,
 | 
						|
      &NetSession->Dest,
 | 
						|
      NetSession->IpVersion
 | 
						|
      );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Send the segment to IP via IpIo function.
 | 
						|
 | 
						|
  @param[in]  Tcb                Pointer to the TCP_CB of this TCP instance.
 | 
						|
  @param[in]  Nbuf               Pointer to the TCP segment to be sent.
 | 
						|
  @param[in]  Src                Source address of the TCP segment.
 | 
						|
  @param[in]  Dest               Destination address of the TCP segment.
 | 
						|
  @param[in]  Version            IP_VERSION_4 or IP_VERSION_6
 | 
						|
 | 
						|
  @retval 0                      The segment was sent out successfully.
 | 
						|
  @retval -1                     The segment failed to send.
 | 
						|
 | 
						|
**/
 | 
						|
INTN
 | 
						|
TcpSendIpPacket (
 | 
						|
  IN TCP_CB          *Tcb,
 | 
						|
  IN NET_BUF         *Nbuf,
 | 
						|
  IN EFI_IP_ADDRESS  *Src,
 | 
						|
  IN EFI_IP_ADDRESS  *Dest,
 | 
						|
  IN UINT8           Version
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS       Status;
 | 
						|
  IP_IO            *IpIo;
 | 
						|
  IP_IO_OVERRIDE   Override;
 | 
						|
  SOCKET           *Sock;
 | 
						|
  VOID             *IpSender;
 | 
						|
  TCP_PROTO_DATA  *TcpProto;
 | 
						|
 | 
						|
  if (NULL == Tcb) {
 | 
						|
 | 
						|
    IpIo     = NULL;
 | 
						|
    IpSender = IpIoFindSender (&IpIo, Version, Src);
 | 
						|
 | 
						|
    if (IpSender == NULL) {
 | 
						|
      DEBUG ((EFI_D_WARN, "TcpSendIpPacket: No appropriate IpSender.\n"));
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Version == IP_VERSION_6) {
 | 
						|
      //
 | 
						|
      // It's tricky here. EFI IPv6 Spec don't allow an instance overriding the
 | 
						|
      // destination address if the dest is already specified through the
 | 
						|
      // configuration data. Here we get the IpIo we need and use the default IP
 | 
						|
      // instance in this IpIo to send the packet. The dest address is configured
 | 
						|
      // to be the unspecified address for the default IP instance.
 | 
						|
      //
 | 
						|
      IpSender = NULL;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
 | 
						|
    Sock     = Tcb->Sk;
 | 
						|
    TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
 | 
						|
    IpIo     = TcpProto->TcpService->IpIo;
 | 
						|
    IpSender = Tcb->IpInfo;
 | 
						|
 | 
						|
    if (Version == IP_VERSION_6) {
 | 
						|
      //
 | 
						|
      // It's IPv6 and this TCP segment belongs to a solid TCB, in such case
 | 
						|
      // the destination address can't be overridden, so reset the Dest to NULL.
 | 
						|
      //
 | 
						|
      if (!Tcb->RemoteIpZero) {
 | 
						|
        Dest = NULL;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT (Version == IpIo->IpVersion);
 | 
						|
 | 
						|
  if (Version == IP_VERSION_4) {
 | 
						|
    Override.Ip4OverrideData.TypeOfService = 0;
 | 
						|
    Override.Ip4OverrideData.TimeToLive    = 255;
 | 
						|
    Override.Ip4OverrideData.DoNotFragment = FALSE;
 | 
						|
    Override.Ip4OverrideData.Protocol      = EFI_IP_PROTO_TCP;
 | 
						|
    ZeroMem (&Override.Ip4OverrideData.GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
    CopyMem (&Override.Ip4OverrideData.SourceAddress, Src, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
  } else {
 | 
						|
    Override.Ip6OverrideData.Protocol  = EFI_IP_PROTO_TCP;
 | 
						|
    Override.Ip6OverrideData.HopLimit  = 255;
 | 
						|
    Override.Ip6OverrideData.FlowLabel = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = IpIoSend (IpIo, Nbuf, IpSender, NULL, NULL, Dest, &Override);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "TcpSendIpPacket: return %r error\n", Status));
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Refresh the remote peer's Neighbor Cache State if already exists.
 | 
						|
 | 
						|
  @param[in]  Tcb                Pointer to the TCP_CB of this TCP instance.
 | 
						|
  @param[in]  Neighbor           Source address of the TCP segment.
 | 
						|
  @param[in]  Timeout            Time in 100-ns units that this entry will remain
 | 
						|
                                 in the neighbor cache. A value of zero means that
 | 
						|
                                 the entry  is permanent. A value of non-zero means
 | 
						|
                                 that the entry is dynamic and will be deleted
 | 
						|
                                 after Timeout.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Successfully updated the neighbor relationship.
 | 
						|
  @retval EFI_NOT_STARTED        The IpIo is not configured.
 | 
						|
  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate some resources.
 | 
						|
  @retval EFI_NOT_FOUND          This entry is not in the neighbor table.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Tcp6RefreshNeighbor (
 | 
						|
  IN TCP_CB          *Tcb,
 | 
						|
  IN EFI_IP_ADDRESS  *Neighbor,
 | 
						|
  IN UINT32          Timeout
 | 
						|
  )
 | 
						|
{
 | 
						|
  IP_IO            *IpIo;
 | 
						|
  SOCKET           *Sock;
 | 
						|
  TCP_PROTO_DATA  *TcpProto;
 | 
						|
 | 
						|
  if (NULL == Tcb) {
 | 
						|
    IpIo = NULL;
 | 
						|
    IpIoFindSender (&IpIo, IP_VERSION_6, Neighbor);
 | 
						|
 | 
						|
    if (IpIo == NULL) {
 | 
						|
      DEBUG ((EFI_D_WARN, "Tcp6AddNeighbor: No appropriate IpIo.\n"));
 | 
						|
      return EFI_NOT_STARTED;
 | 
						|
    }
 | 
						|
 | 
						|
  } else {
 | 
						|
    Sock     = Tcb->Sk;
 | 
						|
    TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
 | 
						|
    IpIo     = TcpProto->TcpService->IpIo;
 | 
						|
  }
 | 
						|
 | 
						|
  return IpIoRefreshNeighbor (IpIo, Neighbor, Timeout);
 | 
						|
}
 | 
						|
 |