Home | History | Annotate | Download | only in TcpDxe
      1 /** @file
      2   Implementation of I/O interfaces between TCP and IpIoLib.
      3 
      4   Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "TcpMain.h"
     17 
     18 /**
     19   Packet receive callback function provided to IP_IO, used to call
     20   the proper function to handle the packet received by IP.
     21 
     22   @param[in] Status        Result of the receive request.
     23   @param[in] IcmpErr       Valid when Status is EFI_ICMP_ERROR.
     24   @param[in] NetSession    The IP session for the received packet.
     25   @param[in] Pkt           Packet received.
     26   @param[in] Context       The data provided by the user for the received packet when
     27                            the callback is registered in IP_IO_OPEN_DATA::RcvdContext.
     28                            This is an optional parameter that may be NULL.
     29 
     30 **/
     31 VOID
     32 EFIAPI
     33 TcpRxCallback (
     34   IN EFI_STATUS                       Status,
     35   IN UINT8                            IcmpErr,
     36   IN EFI_NET_SESSION_DATA             *NetSession,
     37   IN NET_BUF                          *Pkt,
     38   IN VOID                             *Context    OPTIONAL
     39   )
     40 {
     41   if (EFI_SUCCESS == Status) {
     42     TcpInput (Pkt, &NetSession->Source, &NetSession->Dest, NetSession->IpVersion);
     43   } else {
     44     TcpIcmpInput (
     45       Pkt,
     46       IcmpErr,
     47       &NetSession->Source,
     48       &NetSession->Dest,
     49       NetSession->IpVersion
     50       );
     51   }
     52 }
     53 
     54 /**
     55   Send the segment to IP via IpIo function.
     56 
     57   @param[in]  Tcb                Pointer to the TCP_CB of this TCP instance.
     58   @param[in]  Nbuf               Pointer to the TCP segment to be sent.
     59   @param[in]  Src                Source address of the TCP segment.
     60   @param[in]  Dest               Destination address of the TCP segment.
     61   @param[in]  Version            IP_VERSION_4 or IP_VERSION_6
     62 
     63   @retval 0                      The segment was sent out successfully.
     64   @retval -1                     The segment failed to send.
     65 
     66 **/
     67 INTN
     68 TcpSendIpPacket (
     69   IN TCP_CB          *Tcb,
     70   IN NET_BUF         *Nbuf,
     71   IN EFI_IP_ADDRESS  *Src,
     72   IN EFI_IP_ADDRESS  *Dest,
     73   IN UINT8           Version
     74   )
     75 {
     76   EFI_STATUS       Status;
     77   IP_IO            *IpIo;
     78   IP_IO_OVERRIDE   Override;
     79   SOCKET           *Sock;
     80   VOID             *IpSender;
     81   TCP_PROTO_DATA  *TcpProto;
     82 
     83   if (NULL == Tcb) {
     84 
     85     IpIo     = NULL;
     86     IpSender = IpIoFindSender (&IpIo, Version, Src);
     87 
     88     if (IpSender == NULL) {
     89       DEBUG ((EFI_D_WARN, "TcpSendIpPacket: No appropriate IpSender.\n"));
     90       return -1;
     91     }
     92 
     93     if (Version == IP_VERSION_6) {
     94       //
     95       // It's tricky here. EFI IPv6 Spec don't allow an instance overriding the
     96       // destination address if the dest is already specified through the
     97       // configuration data. Here we get the IpIo we need and use the default IP
     98       // instance in this IpIo to send the packet. The dest address is configured
     99       // to be the unspecified address for the default IP instance.
    100       //
    101       IpSender = NULL;
    102     }
    103   } else {
    104 
    105     Sock     = Tcb->Sk;
    106     TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
    107     IpIo     = TcpProto->TcpService->IpIo;
    108     IpSender = Tcb->IpInfo;
    109 
    110     if (Version == IP_VERSION_6) {
    111       //
    112       // It's IPv6 and this TCP segment belongs to a solid TCB, in such case
    113       // the destination address can't be overridden, so reset the Dest to NULL.
    114       //
    115       if (!Tcb->RemoteIpZero) {
    116         Dest = NULL;
    117       }
    118     }
    119   }
    120 
    121   ASSERT (Version == IpIo->IpVersion);
    122 
    123   if (Version == IP_VERSION_4) {
    124     Override.Ip4OverrideData.TypeOfService = 0;
    125     Override.Ip4OverrideData.TimeToLive    = 255;
    126     Override.Ip4OverrideData.DoNotFragment = FALSE;
    127     Override.Ip4OverrideData.Protocol      = EFI_IP_PROTO_TCP;
    128     ZeroMem (&Override.Ip4OverrideData.GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
    129     CopyMem (&Override.Ip4OverrideData.SourceAddress, Src, sizeof (EFI_IPv4_ADDRESS));
    130   } else {
    131     Override.Ip6OverrideData.Protocol  = EFI_IP_PROTO_TCP;
    132     Override.Ip6OverrideData.HopLimit  = 255;
    133     Override.Ip6OverrideData.FlowLabel = 0;
    134   }
    135 
    136   Status = IpIoSend (IpIo, Nbuf, IpSender, NULL, NULL, Dest, &Override);
    137 
    138   if (EFI_ERROR (Status)) {
    139     DEBUG ((EFI_D_ERROR, "TcpSendIpPacket: return %r error\n", Status));
    140     return -1;
    141   }
    142 
    143   return 0;
    144 }
    145 
    146 /**
    147   Refresh the remote peer's Neighbor Cache State if already exists.
    148 
    149   @param[in]  Tcb                Pointer to the TCP_CB of this TCP instance.
    150   @param[in]  Neighbor           Source address of the TCP segment.
    151   @param[in]  Timeout            Time in 100-ns units that this entry will remain
    152                                  in the neighbor cache. A value of zero means that
    153                                  the entry  is permanent. A value of non-zero means
    154                                  that the entry is dynamic and will be deleted
    155                                  after Timeout.
    156 
    157   @retval EFI_SUCCESS            Successfully updated the neighbor relationship.
    158   @retval EFI_NOT_STARTED        The IpIo is not configured.
    159   @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.
    160   @retval EFI_OUT_OF_RESOURCES   Failed to allocate some resources.
    161   @retval EFI_NOT_FOUND          This entry is not in the neighbor table.
    162 
    163 **/
    164 EFI_STATUS
    165 Tcp6RefreshNeighbor (
    166   IN TCP_CB          *Tcb,
    167   IN EFI_IP_ADDRESS  *Neighbor,
    168   IN UINT32          Timeout
    169   )
    170 {
    171   IP_IO            *IpIo;
    172   SOCKET           *Sock;
    173   TCP_PROTO_DATA  *TcpProto;
    174 
    175   if (NULL == Tcb) {
    176     IpIo = NULL;
    177     IpIoFindSender (&IpIo, IP_VERSION_6, Neighbor);
    178 
    179     if (IpIo == NULL) {
    180       DEBUG ((EFI_D_WARN, "Tcp6AddNeighbor: No appropriate IpIo.\n"));
    181       return EFI_NOT_STARTED;
    182     }
    183 
    184   } else {
    185     Sock     = Tcb->Sk;
    186     TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
    187     IpIo     = TcpProto->TcpService->IpIo;
    188   }
    189 
    190   return IpIoRefreshNeighbor (IpIo, Neighbor, Timeout);
    191 }
    192 
    193