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