]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/TcpDxe/TcpIo.c
Add NetworkPkg (P.UDK2010.UP3.Network.P1)
[mirror_edk2.git] / NetworkPkg / TcpDxe / TcpIo.c
1 /** @file
2 Implementation of I/O interfaces between TCP and IpIoLib.
3
4 Copyright (c) 2009 - 2010, 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 Dest = NULL;
116 }
117 }
118
119 ASSERT (Version == IpIo->IpVersion);
120
121 if (Version == IP_VERSION_4) {
122 Override.Ip4OverrideData.TypeOfService = 0;
123 Override.Ip4OverrideData.TimeToLive = 255;
124 Override.Ip4OverrideData.DoNotFragment = FALSE;
125 Override.Ip4OverrideData.Protocol = EFI_IP_PROTO_TCP;
126 ZeroMem (&Override.Ip4OverrideData.GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
127 CopyMem (&Override.Ip4OverrideData.SourceAddress, Src, sizeof (EFI_IPv4_ADDRESS));
128 } else {
129 Override.Ip6OverrideData.Protocol = EFI_IP_PROTO_TCP;
130 Override.Ip6OverrideData.HopLimit = 255;
131 Override.Ip6OverrideData.FlowLabel = 0;
132 }
133
134 Status = IpIoSend (IpIo, Nbuf, IpSender, NULL, NULL, Dest, &Override);
135
136 if (EFI_ERROR (Status)) {
137 DEBUG ((EFI_D_ERROR, "TcpSendIpPacket: return %r error\n", Status));
138 return -1;
139 }
140
141 return 0;
142 }
143
144 /**
145 Refresh the remote peer's Neighbor Cache State if already exists.
146
147 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
148 @param[in] Neighbor Source address of the TCP segment.
149 @param[in] Timeout Time in 100-ns units that this entry will remain
150 in the neighbor cache. A value of zero means that
151 the entry is permanent. A value of non-zero means
152 that the entry is dynamic and will be deleted
153 after Timeout.
154
155 @retval EFI_SUCCESS Successfully updated the neighbor relationship.
156 @retval EFI_NOT_STARTED The IpIo is not configured.
157 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
158 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
159 @retval EFI_NOT_FOUND This entry is not in the neighbor table.
160
161 **/
162 EFI_STATUS
163 Tcp6RefreshNeighbor (
164 IN TCP_CB *Tcb,
165 IN EFI_IP_ADDRESS *Neighbor,
166 IN UINT32 Timeout
167 )
168 {
169 IP_IO *IpIo;
170 SOCKET *Sock;
171 TCP_PROTO_DATA *TcpProto;
172
173 if (NULL == Tcb) {
174 IpIo = NULL;
175 IpIoFindSender (&IpIo, IP_VERSION_6, Neighbor);
176
177 if (IpIo == NULL) {
178 DEBUG ((EFI_D_WARN, "Tcp6AddNeighbor: No appropriate IpIo.\n"));
179 return EFI_NOT_STARTED;
180 }
181
182 } else {
183 Sock = Tcb->Sk;
184 TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
185 IpIo = TcpProto->TcpService->IpIo;
186 }
187
188 return IpIoRefreshNeighbor (IpIo, Neighbor, Timeout);
189 }
190