1 | /** @file
|
---|
2 | The implementation of a dispatch routine for processing TCP requests.
|
---|
3 |
|
---|
4 | (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
|
---|
5 | Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
|
---|
6 |
|
---|
7 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
8 |
|
---|
9 | **/
|
---|
10 |
|
---|
11 | #include "TcpMain.h"
|
---|
12 |
|
---|
13 | /**
|
---|
14 | Add or remove a route entry in the IP route table associated with this TCP instance.
|
---|
15 |
|
---|
16 | @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
---|
17 | @param[in] RouteInfo Pointer to the route information to be processed.
|
---|
18 |
|
---|
19 | @retval EFI_SUCCESS The operation completed successfully.
|
---|
20 | @retval EFI_NOT_STARTED The driver instance has not been started.
|
---|
21 | @retval EFI_NO_MAPPING When using the default address, configuration(DHCP,
|
---|
22 | BOOTP, RARP, etc.) is not finished yet.
|
---|
23 | @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
|
---|
24 | @retval EFI_NOT_FOUND This route is not in the routing table
|
---|
25 | (when RouteInfo->DeleteRoute is TRUE).
|
---|
26 | @retval EFI_ACCESS_DENIED The route is already defined in the routing table
|
---|
27 | (when RouteInfo->DeleteRoute is FALSE).
|
---|
28 | **/
|
---|
29 | EFI_STATUS
|
---|
30 | Tcp4Route (
|
---|
31 | IN TCP_CB *Tcb,
|
---|
32 | IN TCP4_ROUTE_INFO *RouteInfo
|
---|
33 | )
|
---|
34 | {
|
---|
35 | IP_IO_IP_PROTOCOL Ip;
|
---|
36 |
|
---|
37 | Ip = Tcb->IpInfo->Ip;
|
---|
38 |
|
---|
39 | ASSERT (Ip.Ip4 != NULL);
|
---|
40 |
|
---|
41 | return Ip.Ip4->Routes (
|
---|
42 | Ip.Ip4,
|
---|
43 | RouteInfo->DeleteRoute,
|
---|
44 | RouteInfo->SubnetAddress,
|
---|
45 | RouteInfo->SubnetMask,
|
---|
46 | RouteInfo->GatewayAddress
|
---|
47 | );
|
---|
48 | }
|
---|
49 |
|
---|
50 | /**
|
---|
51 | Get the operational settings of this TCPv4 instance.
|
---|
52 |
|
---|
53 | @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
---|
54 | @param[in, out] Mode Pointer to the buffer to store the operational
|
---|
55 | settings.
|
---|
56 |
|
---|
57 | @retval EFI_SUCCESS The mode data was read.
|
---|
58 | @retval EFI_NOT_STARTED No configuration data is available because this
|
---|
59 | instance hasn't been started.
|
---|
60 |
|
---|
61 | **/
|
---|
62 | EFI_STATUS
|
---|
63 | Tcp4GetMode (
|
---|
64 | IN TCP_CB *Tcb,
|
---|
65 | IN OUT TCP4_MODE_DATA *Mode
|
---|
66 | )
|
---|
67 | {
|
---|
68 | SOCKET *Sock;
|
---|
69 | EFI_TCP4_CONFIG_DATA *ConfigData;
|
---|
70 | EFI_TCP4_ACCESS_POINT *AccessPoint;
|
---|
71 | EFI_TCP4_OPTION *Option;
|
---|
72 | EFI_IP4_PROTOCOL *Ip;
|
---|
73 |
|
---|
74 | Sock = Tcb->Sk;
|
---|
75 |
|
---|
76 | if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp4ConfigData != NULL)) {
|
---|
77 | return EFI_NOT_STARTED;
|
---|
78 | }
|
---|
79 |
|
---|
80 | if (Mode->Tcp4State != NULL) {
|
---|
81 | *(Mode->Tcp4State) = (EFI_TCP4_CONNECTION_STATE)Tcb->State;
|
---|
82 | }
|
---|
83 |
|
---|
84 | if (Mode->Tcp4ConfigData != NULL) {
|
---|
85 | ConfigData = Mode->Tcp4ConfigData;
|
---|
86 | AccessPoint = &(ConfigData->AccessPoint);
|
---|
87 | Option = ConfigData->ControlOption;
|
---|
88 |
|
---|
89 | ConfigData->TypeOfService = Tcb->Tos;
|
---|
90 | ConfigData->TimeToLive = Tcb->Ttl;
|
---|
91 |
|
---|
92 | AccessPoint->UseDefaultAddress = Tcb->UseDefaultAddr;
|
---|
93 |
|
---|
94 | IP4_COPY_ADDRESS (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip);
|
---|
95 |
|
---|
96 | IP4_COPY_ADDRESS (&AccessPoint->SubnetMask, &Tcb->SubnetMask);
|
---|
97 | AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);
|
---|
98 |
|
---|
99 | IP4_COPY_ADDRESS (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip);
|
---|
100 |
|
---|
101 | AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port);
|
---|
102 | AccessPoint->ActiveFlag = (BOOLEAN)(Tcb->State != TCP_LISTEN);
|
---|
103 |
|
---|
104 | if (Option != NULL) {
|
---|
105 | Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk);
|
---|
106 | Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk);
|
---|
107 | Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk);
|
---|
108 |
|
---|
109 | Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ;
|
---|
110 | Option->DataRetries = Tcb->MaxRexmit;
|
---|
111 | Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ;
|
---|
112 | Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ;
|
---|
113 | Option->KeepAliveProbes = Tcb->MaxKeepAlive;
|
---|
114 | Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ;
|
---|
115 | Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ;
|
---|
116 |
|
---|
117 | Option->EnableNagle = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));
|
---|
118 | Option->EnableTimeStamp = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));
|
---|
119 | Option->EnableWindowScaling = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS));
|
---|
120 |
|
---|
121 | Option->EnableSelectiveAck = FALSE;
|
---|
122 | Option->EnablePathMtuDiscovery = FALSE;
|
---|
123 | }
|
---|
124 | }
|
---|
125 |
|
---|
126 | Ip = Tcb->IpInfo->Ip.Ip4;
|
---|
127 | ASSERT (Ip != NULL);
|
---|
128 |
|
---|
129 | return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData);
|
---|
130 | }
|
---|
131 |
|
---|
132 | /**
|
---|
133 | Get the operational settings of this TCPv6 instance.
|
---|
134 |
|
---|
135 | @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
---|
136 | @param[in, out] Mode Pointer to the buffer to store the operational
|
---|
137 | settings.
|
---|
138 |
|
---|
139 | @retval EFI_SUCCESS The mode data was read.
|
---|
140 | @retval EFI_NOT_STARTED No configuration data is available because this
|
---|
141 | instance hasn't been started.
|
---|
142 |
|
---|
143 | **/
|
---|
144 | EFI_STATUS
|
---|
145 | Tcp6GetMode (
|
---|
146 | IN TCP_CB *Tcb,
|
---|
147 | IN OUT TCP6_MODE_DATA *Mode
|
---|
148 | )
|
---|
149 | {
|
---|
150 | SOCKET *Sock;
|
---|
151 | EFI_TCP6_CONFIG_DATA *ConfigData;
|
---|
152 | EFI_TCP6_ACCESS_POINT *AccessPoint;
|
---|
153 | EFI_TCP6_OPTION *Option;
|
---|
154 | EFI_IP6_PROTOCOL *Ip;
|
---|
155 |
|
---|
156 | Sock = Tcb->Sk;
|
---|
157 |
|
---|
158 | if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp6ConfigData != NULL)) {
|
---|
159 | return EFI_NOT_STARTED;
|
---|
160 | }
|
---|
161 |
|
---|
162 | if (Mode->Tcp6State != NULL) {
|
---|
163 | *(Mode->Tcp6State) = (EFI_TCP6_CONNECTION_STATE)(Tcb->State);
|
---|
164 | }
|
---|
165 |
|
---|
166 | if (Mode->Tcp6ConfigData != NULL) {
|
---|
167 | ConfigData = Mode->Tcp6ConfigData;
|
---|
168 | AccessPoint = &(ConfigData->AccessPoint);
|
---|
169 | Option = ConfigData->ControlOption;
|
---|
170 |
|
---|
171 | ConfigData->TrafficClass = Tcb->Tos;
|
---|
172 | ConfigData->HopLimit = Tcb->Ttl;
|
---|
173 |
|
---|
174 | AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);
|
---|
175 | AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port);
|
---|
176 | AccessPoint->ActiveFlag = (BOOLEAN)(Tcb->State != TCP_LISTEN);
|
---|
177 |
|
---|
178 | IP6_COPY_ADDRESS (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip);
|
---|
179 | IP6_COPY_ADDRESS (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip);
|
---|
180 |
|
---|
181 | if (Option != NULL) {
|
---|
182 | Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk);
|
---|
183 | Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk);
|
---|
184 | Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk);
|
---|
185 |
|
---|
186 | Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ;
|
---|
187 | Option->DataRetries = Tcb->MaxRexmit;
|
---|
188 | Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ;
|
---|
189 | Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ;
|
---|
190 | Option->KeepAliveProbes = Tcb->MaxKeepAlive;
|
---|
191 | Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ;
|
---|
192 | Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ;
|
---|
193 |
|
---|
194 | Option->EnableNagle = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));
|
---|
195 | Option->EnableTimeStamp = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));
|
---|
196 | Option->EnableWindowScaling = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS));
|
---|
197 |
|
---|
198 | Option->EnableSelectiveAck = FALSE;
|
---|
199 | Option->EnablePathMtuDiscovery = FALSE;
|
---|
200 | }
|
---|
201 | }
|
---|
202 |
|
---|
203 | Ip = Tcb->IpInfo->Ip.Ip6;
|
---|
204 | ASSERT (Ip != NULL);
|
---|
205 |
|
---|
206 | return Ip->GetModeData (Ip, Mode->Ip6ModeData, Mode->MnpConfigData, Mode->SnpModeData);
|
---|
207 | }
|
---|
208 |
|
---|
209 | /**
|
---|
210 | If TcpAp->StationPort isn't zero, check whether the access point
|
---|
211 | is registered, else generate a random station port for this
|
---|
212 | access point.
|
---|
213 |
|
---|
214 | @param[in] TcpAp Pointer to the access point.
|
---|
215 | @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6
|
---|
216 |
|
---|
217 | @retval EFI_SUCCESS The check passed or the port is assigned.
|
---|
218 | @retval EFI_INVALID_PARAMETER The non-zero station port is already used.
|
---|
219 | @retval EFI_OUT_OF_RESOURCES No port can be allocated.
|
---|
220 |
|
---|
221 | **/
|
---|
222 | EFI_STATUS
|
---|
223 | TcpBind (
|
---|
224 | IN TCP_ACCESS_POINT *TcpAp,
|
---|
225 | IN UINT8 IpVersion
|
---|
226 | )
|
---|
227 | {
|
---|
228 | BOOLEAN Cycle;
|
---|
229 | EFI_IP_ADDRESS Local;
|
---|
230 | UINT16 *Port;
|
---|
231 | UINT16 *RandomPort;
|
---|
232 |
|
---|
233 | if (IpVersion == IP_VERSION_4) {
|
---|
234 | IP4_COPY_ADDRESS (&Local, &TcpAp->Tcp4Ap.StationAddress);
|
---|
235 | Port = &TcpAp->Tcp4Ap.StationPort;
|
---|
236 | RandomPort = &mTcp4RandomPort;
|
---|
237 | } else {
|
---|
238 | IP6_COPY_ADDRESS (&Local, &TcpAp->Tcp6Ap.StationAddress);
|
---|
239 | Port = &TcpAp->Tcp6Ap.StationPort;
|
---|
240 | RandomPort = &mTcp6RandomPort;
|
---|
241 | }
|
---|
242 |
|
---|
243 | if (0 != *Port) {
|
---|
244 | //
|
---|
245 | // Check if a same endpoing is bound.
|
---|
246 | //
|
---|
247 | if (TcpFindTcbByPeer (&Local, *Port, IpVersion)) {
|
---|
248 | return EFI_INVALID_PARAMETER;
|
---|
249 | }
|
---|
250 | } else {
|
---|
251 | //
|
---|
252 | // generate a random port
|
---|
253 | //
|
---|
254 | Cycle = FALSE;
|
---|
255 |
|
---|
256 | if (TCP_PORT_USER_RESERVED == *RandomPort) {
|
---|
257 | *RandomPort = TCP_PORT_KNOWN;
|
---|
258 | }
|
---|
259 |
|
---|
260 | (*RandomPort)++;
|
---|
261 |
|
---|
262 | while (TcpFindTcbByPeer (&Local, *RandomPort, IpVersion)) {
|
---|
263 | (*RandomPort)++;
|
---|
264 |
|
---|
265 | if (*RandomPort <= TCP_PORT_KNOWN) {
|
---|
266 | if (Cycle) {
|
---|
267 | DEBUG (
|
---|
268 | (DEBUG_ERROR,
|
---|
269 | "TcpBind: no port can be allocated for this pcb\n")
|
---|
270 | );
|
---|
271 | return EFI_OUT_OF_RESOURCES;
|
---|
272 | }
|
---|
273 |
|
---|
274 | *RandomPort = TCP_PORT_KNOWN + 1;
|
---|
275 |
|
---|
276 | Cycle = TRUE;
|
---|
277 | }
|
---|
278 | }
|
---|
279 |
|
---|
280 | *Port = *RandomPort;
|
---|
281 | }
|
---|
282 |
|
---|
283 | return EFI_SUCCESS;
|
---|
284 | }
|
---|
285 |
|
---|
286 | /**
|
---|
287 | Flush the Tcb add its associated protocols.
|
---|
288 |
|
---|
289 | @param[in, out] Tcb Pointer to the TCP_CB to be flushed.
|
---|
290 |
|
---|
291 | **/
|
---|
292 | VOID
|
---|
293 | TcpFlushPcb (
|
---|
294 | IN OUT TCP_CB *Tcb
|
---|
295 | )
|
---|
296 | {
|
---|
297 | SOCKET *Sock;
|
---|
298 |
|
---|
299 | IpIoConfigIp (Tcb->IpInfo, NULL);
|
---|
300 |
|
---|
301 | Sock = Tcb->Sk;
|
---|
302 |
|
---|
303 | if (SOCK_IS_CONFIGURED (Sock)) {
|
---|
304 | RemoveEntryList (&Tcb->List);
|
---|
305 |
|
---|
306 | if (Sock->DevicePath != NULL) {
|
---|
307 | //
|
---|
308 | // Uninstall the device path protocol.
|
---|
309 | //
|
---|
310 | gBS->UninstallProtocolInterface (
|
---|
311 | Sock->SockHandle,
|
---|
312 | &gEfiDevicePathProtocolGuid,
|
---|
313 | Sock->DevicePath
|
---|
314 | );
|
---|
315 |
|
---|
316 | FreePool (Sock->DevicePath);
|
---|
317 | Sock->DevicePath = NULL;
|
---|
318 | }
|
---|
319 | }
|
---|
320 |
|
---|
321 | NetbufFreeList (&Tcb->SndQue);
|
---|
322 | NetbufFreeList (&Tcb->RcvQue);
|
---|
323 | Tcb->State = TCP_CLOSED;
|
---|
324 | Tcb->RemoteIpZero = FALSE;
|
---|
325 | }
|
---|
326 |
|
---|
327 | /**
|
---|
328 | Attach a Pcb to the socket.
|
---|
329 |
|
---|
330 | @param[in] Sk Pointer to the socket of this TCP instance.
|
---|
331 |
|
---|
332 | @retval EFI_SUCCESS The operation completed successfully.
|
---|
333 | @retval EFI_OUT_OF_RESOURCES Failed due to resource limits.
|
---|
334 |
|
---|
335 | **/
|
---|
336 | EFI_STATUS
|
---|
337 | TcpAttachPcb (
|
---|
338 | IN SOCKET *Sk
|
---|
339 | )
|
---|
340 | {
|
---|
341 | TCP_CB *Tcb;
|
---|
342 | TCP_PROTO_DATA *ProtoData;
|
---|
343 | IP_IO *IpIo;
|
---|
344 | EFI_STATUS Status;
|
---|
345 | VOID *Ip;
|
---|
346 | EFI_GUID *IpProtocolGuid;
|
---|
347 |
|
---|
348 | if (Sk->IpVersion == IP_VERSION_4) {
|
---|
349 | IpProtocolGuid = &gEfiIp4ProtocolGuid;
|
---|
350 | } else {
|
---|
351 | IpProtocolGuid = &gEfiIp6ProtocolGuid;
|
---|
352 | }
|
---|
353 |
|
---|
354 | Tcb = AllocateZeroPool (sizeof (TCP_CB));
|
---|
355 |
|
---|
356 | if (Tcb == NULL) {
|
---|
357 | DEBUG ((DEBUG_ERROR, "TcpConfigurePcb: failed to allocate a TCB\n"));
|
---|
358 |
|
---|
359 | return EFI_OUT_OF_RESOURCES;
|
---|
360 | }
|
---|
361 |
|
---|
362 | ProtoData = (TCP_PROTO_DATA *)Sk->ProtoReserved;
|
---|
363 | IpIo = ProtoData->TcpService->IpIo;
|
---|
364 |
|
---|
365 | //
|
---|
366 | // Create an IpInfo for this Tcb.
|
---|
367 | //
|
---|
368 | Tcb->IpInfo = IpIoAddIp (IpIo);
|
---|
369 | if (Tcb->IpInfo == NULL) {
|
---|
370 | FreePool (Tcb);
|
---|
371 | return EFI_OUT_OF_RESOURCES;
|
---|
372 | }
|
---|
373 |
|
---|
374 | //
|
---|
375 | // Open the new created IP instance BY_CHILD.
|
---|
376 | //
|
---|
377 | Status = gBS->OpenProtocol (
|
---|
378 | Tcb->IpInfo->ChildHandle,
|
---|
379 | IpProtocolGuid,
|
---|
380 | &Ip,
|
---|
381 | IpIo->Image,
|
---|
382 | Sk->SockHandle,
|
---|
383 | EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
---|
384 | );
|
---|
385 | if (EFI_ERROR (Status)) {
|
---|
386 | IpIoRemoveIp (IpIo, Tcb->IpInfo);
|
---|
387 | FreePool (Tcb);
|
---|
388 | return Status;
|
---|
389 | }
|
---|
390 |
|
---|
391 | InitializeListHead (&Tcb->List);
|
---|
392 | InitializeListHead (&Tcb->SndQue);
|
---|
393 | InitializeListHead (&Tcb->RcvQue);
|
---|
394 |
|
---|
395 | Tcb->State = TCP_CLOSED;
|
---|
396 | Tcb->Sk = Sk;
|
---|
397 | ProtoData->TcpPcb = Tcb;
|
---|
398 |
|
---|
399 | return EFI_SUCCESS;
|
---|
400 | }
|
---|
401 |
|
---|
402 | /**
|
---|
403 | Detach the Pcb of the socket.
|
---|
404 |
|
---|
405 | @param[in, out] Sk Pointer to the socket of this TCP instance.
|
---|
406 |
|
---|
407 | **/
|
---|
408 | VOID
|
---|
409 | TcpDetachPcb (
|
---|
410 | IN OUT SOCKET *Sk
|
---|
411 | )
|
---|
412 | {
|
---|
413 | TCP_PROTO_DATA *ProtoData;
|
---|
414 | TCP_CB *Tcb;
|
---|
415 |
|
---|
416 | ProtoData = (TCP_PROTO_DATA *)Sk->ProtoReserved;
|
---|
417 | Tcb = ProtoData->TcpPcb;
|
---|
418 |
|
---|
419 | ASSERT (Tcb != NULL);
|
---|
420 |
|
---|
421 | TcpFlushPcb (Tcb);
|
---|
422 |
|
---|
423 | IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);
|
---|
424 |
|
---|
425 | FreePool (Tcb);
|
---|
426 |
|
---|
427 | ProtoData->TcpPcb = NULL;
|
---|
428 | }
|
---|
429 |
|
---|
430 | /**
|
---|
431 | Configure the Pcb using CfgData.
|
---|
432 |
|
---|
433 | @param[in] Sk Pointer to the socket of this TCP instance.
|
---|
434 | @param[in] CfgData Pointer to the TCP configuration data.
|
---|
435 |
|
---|
436 | @retval EFI_SUCCESS The operation completed successfully.
|
---|
437 | @retval EFI_INVALID_PARAMETER A same access point has been configured in
|
---|
438 | another TCP instance.
|
---|
439 | @retval EFI_OUT_OF_RESOURCES Failed due to resource limits.
|
---|
440 |
|
---|
441 | **/
|
---|
442 | EFI_STATUS
|
---|
443 | TcpConfigurePcb (
|
---|
444 | IN SOCKET *Sk,
|
---|
445 | IN TCP_CONFIG_DATA *CfgData
|
---|
446 | )
|
---|
447 | {
|
---|
448 | IP_IO_IP_CONFIG_DATA IpCfgData;
|
---|
449 | EFI_STATUS Status;
|
---|
450 | EFI_TCP4_OPTION *Option;
|
---|
451 | TCP_PROTO_DATA *TcpProto;
|
---|
452 | TCP_CB *Tcb;
|
---|
453 | TCP_ACCESS_POINT *TcpAp;
|
---|
454 |
|
---|
455 | ASSERT ((CfgData != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL));
|
---|
456 |
|
---|
457 | TcpProto = (TCP_PROTO_DATA *)Sk->ProtoReserved;
|
---|
458 | Tcb = TcpProto->TcpPcb;
|
---|
459 |
|
---|
460 | ASSERT (Tcb != NULL);
|
---|
461 |
|
---|
462 | if (Sk->IpVersion == IP_VERSION_4) {
|
---|
463 | //
|
---|
464 | // Add Ip for send pkt to the peer
|
---|
465 | //
|
---|
466 | CopyMem (&IpCfgData.Ip4CfgData, &mIp4IoDefaultIpConfigData, sizeof (EFI_IP4_CONFIG_DATA));
|
---|
467 | IpCfgData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
|
---|
468 | IpCfgData.Ip4CfgData.TypeOfService = CfgData->Tcp4CfgData.TypeOfService;
|
---|
469 | IpCfgData.Ip4CfgData.TimeToLive = CfgData->Tcp4CfgData.TimeToLive;
|
---|
470 | IpCfgData.Ip4CfgData.UseDefaultAddress = CfgData->Tcp4CfgData.AccessPoint.UseDefaultAddress;
|
---|
471 | IP4_COPY_ADDRESS (
|
---|
472 | &IpCfgData.Ip4CfgData.SubnetMask,
|
---|
473 | &CfgData->Tcp4CfgData.AccessPoint.SubnetMask
|
---|
474 | );
|
---|
475 | IpCfgData.Ip4CfgData.ReceiveTimeout = (UINT32)(-1);
|
---|
476 | IP4_COPY_ADDRESS (
|
---|
477 | &IpCfgData.Ip4CfgData.StationAddress,
|
---|
478 | &CfgData->Tcp4CfgData.AccessPoint.StationAddress
|
---|
479 | );
|
---|
480 | } else {
|
---|
481 | ASSERT (Sk->IpVersion == IP_VERSION_6);
|
---|
482 |
|
---|
483 | CopyMem (&IpCfgData.Ip6CfgData, &mIp6IoDefaultIpConfigData, sizeof (EFI_IP6_CONFIG_DATA));
|
---|
484 | IpCfgData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
|
---|
485 | IpCfgData.Ip6CfgData.TrafficClass = CfgData->Tcp6CfgData.TrafficClass;
|
---|
486 | IpCfgData.Ip6CfgData.HopLimit = CfgData->Tcp6CfgData.HopLimit;
|
---|
487 | IpCfgData.Ip6CfgData.ReceiveTimeout = (UINT32)(-1);
|
---|
488 | IP6_COPY_ADDRESS (
|
---|
489 | &IpCfgData.Ip6CfgData.StationAddress,
|
---|
490 | &CfgData->Tcp6CfgData.AccessPoint.StationAddress
|
---|
491 | );
|
---|
492 | IP6_COPY_ADDRESS (
|
---|
493 | &IpCfgData.Ip6CfgData.DestinationAddress,
|
---|
494 | &CfgData->Tcp6CfgData.AccessPoint.RemoteAddress
|
---|
495 | );
|
---|
496 | }
|
---|
497 |
|
---|
498 | //
|
---|
499 | // Configure the IP instance this Tcb consumes.
|
---|
500 | //
|
---|
501 | Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);
|
---|
502 | if (EFI_ERROR (Status)) {
|
---|
503 | goto OnExit;
|
---|
504 | }
|
---|
505 |
|
---|
506 | if (Sk->IpVersion == IP_VERSION_4) {
|
---|
507 | //
|
---|
508 | // Get the default address information if the instance is configured to use default address.
|
---|
509 | //
|
---|
510 | IP4_COPY_ADDRESS (
|
---|
511 | &CfgData->Tcp4CfgData.AccessPoint.StationAddress,
|
---|
512 | &IpCfgData.Ip4CfgData.StationAddress
|
---|
513 | );
|
---|
514 | IP4_COPY_ADDRESS (
|
---|
515 | &CfgData->Tcp4CfgData.AccessPoint.SubnetMask,
|
---|
516 | &IpCfgData.Ip4CfgData.SubnetMask
|
---|
517 | );
|
---|
518 |
|
---|
519 | TcpAp = (TCP_ACCESS_POINT *)&CfgData->Tcp4CfgData.AccessPoint;
|
---|
520 | } else {
|
---|
521 | IP6_COPY_ADDRESS (
|
---|
522 | &CfgData->Tcp6CfgData.AccessPoint.StationAddress,
|
---|
523 | &IpCfgData.Ip6CfgData.StationAddress
|
---|
524 | );
|
---|
525 |
|
---|
526 | TcpAp = (TCP_ACCESS_POINT *)&CfgData->Tcp6CfgData.AccessPoint;
|
---|
527 | }
|
---|
528 |
|
---|
529 | //
|
---|
530 | // check if we can bind this endpoint in CfgData
|
---|
531 | //
|
---|
532 | Status = TcpBind (TcpAp, Sk->IpVersion);
|
---|
533 |
|
---|
534 | if (EFI_ERROR (Status)) {
|
---|
535 | DEBUG (
|
---|
536 | (DEBUG_ERROR,
|
---|
537 | "TcpConfigurePcb: Bind endpoint failed with %r\n",
|
---|
538 | Status)
|
---|
539 | );
|
---|
540 |
|
---|
541 | goto OnExit;
|
---|
542 | }
|
---|
543 |
|
---|
544 | //
|
---|
545 | // Initialize the operating information in this Tcb
|
---|
546 | //
|
---|
547 | ASSERT (
|
---|
548 | Tcb->State == TCP_CLOSED &&
|
---|
549 | IsListEmpty (&Tcb->SndQue) &&
|
---|
550 | IsListEmpty (&Tcb->RcvQue)
|
---|
551 | );
|
---|
552 |
|
---|
553 | TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
|
---|
554 | Tcb->State = TCP_CLOSED;
|
---|
555 |
|
---|
556 | Tcb->SndMss = 536;
|
---|
557 | Tcb->RcvMss = TcpGetRcvMss (Sk);
|
---|
558 |
|
---|
559 | Tcb->SRtt = 0;
|
---|
560 | Tcb->Rto = 3 * TCP_TICK_HZ;
|
---|
561 |
|
---|
562 | Tcb->CWnd = Tcb->SndMss;
|
---|
563 | Tcb->Ssthresh = 0xffffffff;
|
---|
564 |
|
---|
565 | Tcb->CongestState = TCP_CONGEST_OPEN;
|
---|
566 |
|
---|
567 | Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN;
|
---|
568 | Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD;
|
---|
569 | Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE;
|
---|
570 | Tcb->MaxRexmit = TCP_MAX_LOSS;
|
---|
571 | Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME;
|
---|
572 | Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME;
|
---|
573 | Tcb->ConnectTimeout = TCP_CONNECT_TIME;
|
---|
574 |
|
---|
575 | if (Sk->IpVersion == IP_VERSION_4) {
|
---|
576 | //
|
---|
577 | // initialize Tcb in the light of CfgData
|
---|
578 | //
|
---|
579 | Tcb->Ttl = CfgData->Tcp4CfgData.TimeToLive;
|
---|
580 | Tcb->Tos = CfgData->Tcp4CfgData.TypeOfService;
|
---|
581 |
|
---|
582 | Tcb->UseDefaultAddr = CfgData->Tcp4CfgData.AccessPoint.UseDefaultAddress;
|
---|
583 |
|
---|
584 | CopyMem (&Tcb->LocalEnd.Ip, &CfgData->Tcp4CfgData.AccessPoint.StationAddress, sizeof (IP4_ADDR));
|
---|
585 | Tcb->LocalEnd.Port = HTONS (CfgData->Tcp4CfgData.AccessPoint.StationPort);
|
---|
586 | IP4_COPY_ADDRESS (&Tcb->SubnetMask, &CfgData->Tcp4CfgData.AccessPoint.SubnetMask);
|
---|
587 |
|
---|
588 | CopyMem (&Tcb->RemoteEnd.Ip, &CfgData->Tcp4CfgData.AccessPoint.RemoteAddress, sizeof (IP4_ADDR));
|
---|
589 | Tcb->RemoteEnd.Port = HTONS (CfgData->Tcp4CfgData.AccessPoint.RemotePort);
|
---|
590 |
|
---|
591 | Option = CfgData->Tcp4CfgData.ControlOption;
|
---|
592 | } else {
|
---|
593 | Tcb->Ttl = CfgData->Tcp6CfgData.HopLimit;
|
---|
594 | Tcb->Tos = CfgData->Tcp6CfgData.TrafficClass;
|
---|
595 |
|
---|
596 | IP6_COPY_ADDRESS (&Tcb->LocalEnd.Ip, &CfgData->Tcp6CfgData.AccessPoint.StationAddress);
|
---|
597 | Tcb->LocalEnd.Port = HTONS (CfgData->Tcp6CfgData.AccessPoint.StationPort);
|
---|
598 |
|
---|
599 | IP6_COPY_ADDRESS (&Tcb->RemoteEnd.Ip, &CfgData->Tcp6CfgData.AccessPoint.RemoteAddress);
|
---|
600 | Tcb->RemoteEnd.Port = HTONS (CfgData->Tcp6CfgData.AccessPoint.RemotePort);
|
---|
601 |
|
---|
602 | //
|
---|
603 | // Type EFI_TCP4_OPTION and EFI_TCP6_OPTION are the same.
|
---|
604 | //
|
---|
605 | Option = (EFI_TCP4_OPTION *)CfgData->Tcp6CfgData.ControlOption;
|
---|
606 | }
|
---|
607 |
|
---|
608 | if (Option != NULL) {
|
---|
609 | SET_RCV_BUFFSIZE (
|
---|
610 | Sk,
|
---|
611 | (UINT32)(TCP_COMP_VAL (
|
---|
612 | TCP_RCV_BUF_SIZE_MIN,
|
---|
613 | TCP_RCV_BUF_SIZE,
|
---|
614 | TCP_RCV_BUF_SIZE,
|
---|
615 | Option->ReceiveBufferSize
|
---|
616 | )
|
---|
617 | )
|
---|
618 | );
|
---|
619 | SET_SND_BUFFSIZE (
|
---|
620 | Sk,
|
---|
621 | (UINT32)(TCP_COMP_VAL (
|
---|
622 | TCP_SND_BUF_SIZE_MIN,
|
---|
623 | TCP_SND_BUF_SIZE,
|
---|
624 | TCP_SND_BUF_SIZE,
|
---|
625 | Option->SendBufferSize
|
---|
626 | )
|
---|
627 | )
|
---|
628 | );
|
---|
629 |
|
---|
630 | SET_BACKLOG (
|
---|
631 | Sk,
|
---|
632 | (UINT32)(TCP_COMP_VAL (
|
---|
633 | TCP_BACKLOG_MIN,
|
---|
634 | TCP_BACKLOG,
|
---|
635 | TCP_BACKLOG,
|
---|
636 | Option->MaxSynBackLog
|
---|
637 | )
|
---|
638 | )
|
---|
639 | );
|
---|
640 |
|
---|
641 | Tcb->MaxRexmit = (UINT16)TCP_COMP_VAL (
|
---|
642 | TCP_MAX_LOSS_MIN,
|
---|
643 | TCP_MAX_LOSS,
|
---|
644 | TCP_MAX_LOSS,
|
---|
645 | Option->DataRetries
|
---|
646 | );
|
---|
647 | Tcb->FinWait2Timeout = TCP_COMP_VAL (
|
---|
648 | TCP_FIN_WAIT2_TIME,
|
---|
649 | TCP_FIN_WAIT2_TIME_MAX,
|
---|
650 | TCP_FIN_WAIT2_TIME,
|
---|
651 | (UINT32)(Option->FinTimeout * TCP_TICK_HZ)
|
---|
652 | );
|
---|
653 |
|
---|
654 | if (Option->TimeWaitTimeout != 0) {
|
---|
655 | Tcb->TimeWaitTimeout = TCP_COMP_VAL (
|
---|
656 | TCP_TIME_WAIT_TIME,
|
---|
657 | TCP_TIME_WAIT_TIME_MAX,
|
---|
658 | TCP_TIME_WAIT_TIME,
|
---|
659 | (UINT32)(Option->TimeWaitTimeout * TCP_TICK_HZ)
|
---|
660 | );
|
---|
661 | } else {
|
---|
662 | Tcb->TimeWaitTimeout = 0;
|
---|
663 | }
|
---|
664 |
|
---|
665 | if (Option->KeepAliveProbes != 0) {
|
---|
666 | TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
|
---|
667 |
|
---|
668 | Tcb->MaxKeepAlive = (UINT8)TCP_COMP_VAL (
|
---|
669 | TCP_MAX_KEEPALIVE_MIN,
|
---|
670 | TCP_MAX_KEEPALIVE,
|
---|
671 | TCP_MAX_KEEPALIVE,
|
---|
672 | Option->KeepAliveProbes
|
---|
673 | );
|
---|
674 | Tcb->KeepAliveIdle = TCP_COMP_VAL (
|
---|
675 | TCP_KEEPALIVE_IDLE_MIN,
|
---|
676 | TCP_KEEPALIVE_IDLE_MAX,
|
---|
677 | TCP_KEEPALIVE_IDLE_MIN,
|
---|
678 | (UINT32)(Option->KeepAliveTime * TCP_TICK_HZ)
|
---|
679 | );
|
---|
680 | Tcb->KeepAlivePeriod = TCP_COMP_VAL (
|
---|
681 | TCP_KEEPALIVE_PERIOD_MIN,
|
---|
682 | TCP_KEEPALIVE_PERIOD,
|
---|
683 | TCP_KEEPALIVE_PERIOD,
|
---|
684 | (UINT32)(Option->KeepAliveInterval * TCP_TICK_HZ)
|
---|
685 | );
|
---|
686 | }
|
---|
687 |
|
---|
688 | Tcb->ConnectTimeout = TCP_COMP_VAL (
|
---|
689 | TCP_CONNECT_TIME_MIN,
|
---|
690 | TCP_CONNECT_TIME,
|
---|
691 | TCP_CONNECT_TIME,
|
---|
692 | (UINT32)(Option->ConnectionTimeout * TCP_TICK_HZ)
|
---|
693 | );
|
---|
694 |
|
---|
695 | if (!Option->EnableNagle) {
|
---|
696 | TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
|
---|
697 | }
|
---|
698 |
|
---|
699 | if (!Option->EnableTimeStamp) {
|
---|
700 | TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
|
---|
701 | }
|
---|
702 |
|
---|
703 | if (!Option->EnableWindowScaling) {
|
---|
704 | TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
|
---|
705 | }
|
---|
706 | }
|
---|
707 |
|
---|
708 | //
|
---|
709 | // The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is
|
---|
710 | // determined, construct the IP device path and install it.
|
---|
711 | //
|
---|
712 | Status = TcpInstallDevicePath (Sk);
|
---|
713 | if (EFI_ERROR (Status)) {
|
---|
714 | goto OnExit;
|
---|
715 | }
|
---|
716 |
|
---|
717 | //
|
---|
718 | // update state of Tcb and socket
|
---|
719 | //
|
---|
720 | if (((Sk->IpVersion == IP_VERSION_4) && !CfgData->Tcp4CfgData.AccessPoint.ActiveFlag) ||
|
---|
721 | ((Sk->IpVersion == IP_VERSION_6) && !CfgData->Tcp6CfgData.AccessPoint.ActiveFlag)
|
---|
722 | )
|
---|
723 | {
|
---|
724 | TcpSetState (Tcb, TCP_LISTEN);
|
---|
725 | SockSetState (Sk, SO_LISTENING);
|
---|
726 |
|
---|
727 | Sk->ConfigureState = SO_CONFIGURED_PASSIVE;
|
---|
728 | } else {
|
---|
729 | Sk->ConfigureState = SO_CONFIGURED_ACTIVE;
|
---|
730 | }
|
---|
731 |
|
---|
732 | if (Sk->IpVersion == IP_VERSION_6) {
|
---|
733 | Tcb->Tick = TCP6_REFRESH_NEIGHBOR_TICK;
|
---|
734 |
|
---|
735 | if (NetIp6IsUnspecifiedAddr (&Tcb->RemoteEnd.Ip.v6)) {
|
---|
736 | Tcb->RemoteIpZero = TRUE;
|
---|
737 | }
|
---|
738 | }
|
---|
739 |
|
---|
740 | TcpInsertTcb (Tcb);
|
---|
741 |
|
---|
742 | OnExit:
|
---|
743 |
|
---|
744 | return Status;
|
---|
745 | }
|
---|
746 |
|
---|
747 | /**
|
---|
748 | The protocol handler provided to the socket layer, which is used to
|
---|
749 | dispatch the socket level requests by calling the corresponding
|
---|
750 | TCP layer functions.
|
---|
751 |
|
---|
752 | @param[in] Sock Pointer to the socket of this TCP instance.
|
---|
753 | @param[in] Request The code of this operation request.
|
---|
754 | @param[in] Data Pointer to the operation specific data passed in
|
---|
755 | together with the operation request. This is an
|
---|
756 | optional parameter that may be NULL.
|
---|
757 |
|
---|
758 | @retval EFI_SUCCESS The socket request completed successfully.
|
---|
759 | @retval other The error status returned by the corresponding TCP
|
---|
760 | layer function.
|
---|
761 |
|
---|
762 | **/
|
---|
763 | EFI_STATUS
|
---|
764 | TcpDispatcher (
|
---|
765 | IN SOCKET *Sock,
|
---|
766 | IN UINT8 Request,
|
---|
767 | IN VOID *Data OPTIONAL
|
---|
768 | )
|
---|
769 | {
|
---|
770 | TCP_CB *Tcb;
|
---|
771 | TCP_PROTO_DATA *ProtoData;
|
---|
772 |
|
---|
773 | ProtoData = (TCP_PROTO_DATA *)Sock->ProtoReserved;
|
---|
774 | Tcb = ProtoData->TcpPcb;
|
---|
775 |
|
---|
776 | switch (Request) {
|
---|
777 | case SOCK_POLL:
|
---|
778 | if (Tcb->Sk->IpVersion == IP_VERSION_4) {
|
---|
779 | ProtoData->TcpService->IpIo->Ip.Ip4->Poll (ProtoData->TcpService->IpIo->Ip.Ip4);
|
---|
780 | } else {
|
---|
781 | ProtoData->TcpService->IpIo->Ip.Ip6->Poll (ProtoData->TcpService->IpIo->Ip.Ip6);
|
---|
782 | }
|
---|
783 |
|
---|
784 | break;
|
---|
785 |
|
---|
786 | case SOCK_CONSUMED:
|
---|
787 | //
|
---|
788 | // After user received data from socket buffer, socket will
|
---|
789 | // notify TCP using this message to give it a chance to send out
|
---|
790 | // window update information
|
---|
791 | //
|
---|
792 | ASSERT (Tcb != NULL);
|
---|
793 | TcpOnAppConsume (Tcb);
|
---|
794 | break;
|
---|
795 |
|
---|
796 | case SOCK_SND:
|
---|
797 |
|
---|
798 | ASSERT (Tcb != NULL);
|
---|
799 | TcpOnAppSend (Tcb);
|
---|
800 | break;
|
---|
801 |
|
---|
802 | case SOCK_CLOSE:
|
---|
803 |
|
---|
804 | TcpOnAppClose (Tcb);
|
---|
805 |
|
---|
806 | break;
|
---|
807 |
|
---|
808 | case SOCK_ABORT:
|
---|
809 |
|
---|
810 | TcpOnAppAbort (Tcb);
|
---|
811 |
|
---|
812 | break;
|
---|
813 |
|
---|
814 | case SOCK_SNDPUSH:
|
---|
815 | Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);
|
---|
816 | TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
|
---|
817 |
|
---|
818 | break;
|
---|
819 |
|
---|
820 | case SOCK_SNDURG:
|
---|
821 | Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;
|
---|
822 | TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
|
---|
823 |
|
---|
824 | break;
|
---|
825 |
|
---|
826 | case SOCK_CONNECT:
|
---|
827 |
|
---|
828 | TcpOnAppConnect (Tcb);
|
---|
829 |
|
---|
830 | break;
|
---|
831 |
|
---|
832 | case SOCK_ATTACH:
|
---|
833 |
|
---|
834 | return TcpAttachPcb (Sock);
|
---|
835 |
|
---|
836 | break;
|
---|
837 |
|
---|
838 | case SOCK_FLUSH:
|
---|
839 |
|
---|
840 | TcpFlushPcb (Tcb);
|
---|
841 |
|
---|
842 | break;
|
---|
843 |
|
---|
844 | case SOCK_DETACH:
|
---|
845 |
|
---|
846 | TcpDetachPcb (Sock);
|
---|
847 |
|
---|
848 | break;
|
---|
849 |
|
---|
850 | case SOCK_CONFIGURE:
|
---|
851 |
|
---|
852 | return TcpConfigurePcb (
|
---|
853 | Sock,
|
---|
854 | (TCP_CONFIG_DATA *)Data
|
---|
855 | );
|
---|
856 |
|
---|
857 | break;
|
---|
858 |
|
---|
859 | case SOCK_MODE:
|
---|
860 |
|
---|
861 | ASSERT ((Data != NULL) && (Tcb != NULL));
|
---|
862 |
|
---|
863 | if (Tcb->Sk->IpVersion == IP_VERSION_4) {
|
---|
864 | return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *)Data);
|
---|
865 | } else {
|
---|
866 | return Tcp6GetMode (Tcb, (TCP6_MODE_DATA *)Data);
|
---|
867 | }
|
---|
868 |
|
---|
869 | break;
|
---|
870 |
|
---|
871 | case SOCK_ROUTE:
|
---|
872 |
|
---|
873 | ASSERT ((Data != NULL) && (Tcb != NULL) && (Tcb->Sk->IpVersion == IP_VERSION_4));
|
---|
874 |
|
---|
875 | return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *)Data);
|
---|
876 |
|
---|
877 | default:
|
---|
878 |
|
---|
879 | return EFI_UNSUPPORTED;
|
---|
880 | }
|
---|
881 |
|
---|
882 | return EFI_SUCCESS;
|
---|
883 | }
|
---|