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