]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dispatcher.c
Update the copyright notice format
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Dispatcher.c
1 /** @file
2 Tcp request dispatcher implementation.
3
4 Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php<BR>
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Tcp4Main.h"
16
17 #define TCP_COMP_VAL(Min, Max, Default, Val) \
18 ((((Val) <= (Max)) && ((Val) >= (Min))) ? (Val) : (Default))
19
20 /**
21 Add or remove a route entry in the IP route table associated with this TCP instance.
22
23 @param Tcb Pointer to the TCP_CB of this TCP instance.
24 @param RouteInfo Pointer to the route info to be processed.
25
26 @retval EFI_SUCCESS The operation completed successfully.
27 @retval EFI_NOT_STARTED The driver instance has not been started.
28 @retval EFI_NO_MAPPING When using the default address, configuration(DHCP,
29 BOOTP, RARP, etc.) is not finished yet.
30 @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
31 @retval EFI_NOT_FOUND This route is not in the routing table
32 (when RouteInfo->DeleteRoute is TRUE).
33 @retval EFI_ACCESS_DENIED The route is already defined in the routing table
34 (when RouteInfo->DeleteRoute is FALSE).
35 **/
36 EFI_STATUS
37 Tcp4Route (
38 IN TCP_CB *Tcb,
39 IN TCP4_ROUTE_INFO *RouteInfo
40 )
41 {
42 EFI_IP4_PROTOCOL *Ip;
43
44 Ip = Tcb->IpInfo->Ip;
45
46 ASSERT (Ip != NULL);
47
48 return Ip->Routes (
49 Ip,
50 RouteInfo->DeleteRoute,
51 RouteInfo->SubnetAddress,
52 RouteInfo->SubnetMask,
53 RouteInfo->GatewayAddress
54 );
55
56 }
57
58
59 /**
60 Get the operational settings of this TCP instance.
61
62 @param Tcb Pointer to the TCP_CB of this TCP instance.
63 @param Mode Pointer to the buffer to store the operational
64 settings.
65
66 @retval EFI_SUCCESS The mode data is read.
67 @retval EFI_NOT_STARTED No configuration data is available because this
68 instance hasn't been started.
69
70 **/
71 EFI_STATUS
72 Tcp4GetMode (
73 IN TCP_CB *Tcb,
74 IN OUT TCP4_MODE_DATA *Mode
75 )
76 {
77 SOCKET *Sock;
78 EFI_TCP4_CONFIG_DATA *ConfigData;
79 EFI_TCP4_ACCESS_POINT *AccessPoint;
80 EFI_TCP4_OPTION *Option;
81 EFI_IP4_PROTOCOL *Ip;
82
83 Sock = Tcb->Sk;
84
85 if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp4ConfigData != NULL)) {
86 return EFI_NOT_STARTED;
87 }
88
89 if (Mode->Tcp4State != NULL) {
90 *(Mode->Tcp4State) = (EFI_TCP4_CONNECTION_STATE) Tcb->State;
91 }
92
93 if (Mode->Tcp4ConfigData != NULL) {
94
95 ConfigData = Mode->Tcp4ConfigData;
96 AccessPoint = &(ConfigData->AccessPoint);
97 Option = ConfigData->ControlOption;
98
99 ConfigData->TypeOfService = Tcb->Tos;
100 ConfigData->TimeToLive = Tcb->Ttl;
101
102 AccessPoint->UseDefaultAddress = Tcb->UseDefaultAddr;
103
104 CopyMem (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip, sizeof (EFI_IPv4_ADDRESS));
105 AccessPoint->SubnetMask = Tcb->SubnetMask;
106 AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);
107
108 CopyMem (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip, sizeof (EFI_IPv4_ADDRESS));
109 AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port);
110 AccessPoint->ActiveFlag = (BOOLEAN) (Tcb->State != TCP_LISTEN);
111
112 if (Option != NULL) {
113 Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk);
114 Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk);
115 Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk);
116
117 Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ;
118 Option->DataRetries = Tcb->MaxRexmit;
119 Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ;
120 Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ;
121 Option->KeepAliveProbes = Tcb->MaxKeepAlive;
122 Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ;
123 Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ;
124
125 Option->EnableNagle = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));
126 Option->EnableTimeStamp = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));
127 Option->EnableWindowScaling = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS));
128
129 Option->EnableSelectiveAck = FALSE;
130 Option->EnablePathMtuDiscovery = FALSE;
131 }
132 }
133
134 Ip = Tcb->IpInfo->Ip;
135 ASSERT (Ip != NULL);
136
137 return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData);
138 }
139
140
141 /**
142 If AP->StationPort isn't zero, check whether the access point
143 is registered, else generate a random station port for this
144 access point.
145
146 @param AP Pointer to the access point.
147
148 @retval EFI_SUCCESS The check is passed or the port is assigned.
149 @retval EFI_INVALID_PARAMETER The non-zero station port is already used.
150 @retval EFI_OUT_OF_RESOURCES No port can be allocated.
151
152 **/
153 EFI_STATUS
154 Tcp4Bind (
155 IN EFI_TCP4_ACCESS_POINT *AP
156 )
157 {
158 BOOLEAN Cycle;
159
160 if (0 != AP->StationPort) {
161 //
162 // check if a same endpoint is bound
163 //
164 if (TcpFindTcbByPeer (&AP->StationAddress, AP->StationPort)) {
165
166 return EFI_INVALID_PARAMETER;
167 }
168 } else {
169 //
170 // generate a random port
171 //
172 Cycle = FALSE;
173
174 if (TCP4_PORT_USER_RESERVED == mTcp4RandomPort) {
175 mTcp4RandomPort = TCP4_PORT_KNOWN;
176 }
177
178 mTcp4RandomPort++;
179
180 while (TcpFindTcbByPeer (&AP->StationAddress, mTcp4RandomPort)) {
181
182 mTcp4RandomPort++;
183
184 if (mTcp4RandomPort <= TCP4_PORT_KNOWN) {
185
186 if (Cycle) {
187 DEBUG ((EFI_D_ERROR, "Tcp4Bind: no port can be allocated "
188 "for this pcb\n"));
189
190 return EFI_OUT_OF_RESOURCES;
191 }
192
193 mTcp4RandomPort = TCP4_PORT_KNOWN + 1;
194
195 Cycle = TRUE;
196 }
197
198 }
199
200 AP->StationPort = mTcp4RandomPort;
201 }
202
203 return EFI_SUCCESS;
204 }
205
206
207 /**
208 Flush the Tcb add its associated protocols.
209
210 @param Tcb Pointer to the TCP_CB to be flushed.
211
212 **/
213 VOID
214 Tcp4FlushPcb (
215 IN TCP_CB *Tcb
216 )
217 {
218 SOCKET *Sock;
219 TCP4_PROTO_DATA *TcpProto;
220
221 IpIoConfigIp (Tcb->IpInfo, NULL);
222
223 Sock = Tcb->Sk;
224 TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
225
226 if (SOCK_IS_CONFIGURED (Sock)) {
227 RemoveEntryList (&Tcb->List);
228
229 //
230 // Uninstall the device path protocol.
231 //
232 if (Sock->DevicePath != NULL) {
233 gBS->UninstallProtocolInterface (
234 Sock->SockHandle,
235 &gEfiDevicePathProtocolGuid,
236 Sock->DevicePath
237 );
238 FreePool (Sock->DevicePath);
239 }
240
241 TcpSetVariableData (TcpProto->TcpService);
242 }
243
244 NetbufFreeList (&Tcb->SndQue);
245 NetbufFreeList (&Tcb->RcvQue);
246 }
247
248 /**
249 Attach a Pcb to the socket.
250
251 @param Sk Pointer to the socket of this TCP instance.
252
253 @retval EFI_SUCCESS The operation is completed successfully.
254 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
255
256 **/
257 EFI_STATUS
258 Tcp4AttachPcb (
259 IN SOCKET *Sk
260 )
261 {
262 TCP_CB *Tcb;
263 TCP4_PROTO_DATA *ProtoData;
264 IP_IO *IpIo;
265
266 Tcb = AllocateZeroPool (sizeof (TCP_CB));
267
268 if (Tcb == NULL) {
269
270 DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: failed to allocate a TCB\n"));
271
272 return EFI_OUT_OF_RESOURCES;
273 }
274
275 ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
276 IpIo = ProtoData->TcpService->IpIo;
277
278 //
279 // Create an IpInfo for this Tcb.
280 //
281 Tcb->IpInfo = IpIoAddIp (IpIo);
282 if (Tcb->IpInfo == NULL) {
283
284 FreePool (Tcb);
285 return EFI_OUT_OF_RESOURCES;
286 }
287
288 InitializeListHead (&Tcb->List);
289 InitializeListHead (&Tcb->SndQue);
290 InitializeListHead (&Tcb->RcvQue);
291
292 Tcb->State = TCP_CLOSED;
293 Tcb->Sk = Sk;
294 ProtoData->TcpPcb = Tcb;
295
296 return EFI_SUCCESS;
297 }
298
299 /**
300 Detach the Pcb of the socket.
301
302 @param Sk Pointer to the socket of this TCP instance.
303
304 **/
305 VOID
306 Tcp4DetachPcb (
307 IN SOCKET *Sk
308 )
309 {
310 TCP4_PROTO_DATA *ProtoData;
311 TCP_CB *Tcb;
312
313 ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
314 Tcb = ProtoData->TcpPcb;
315
316 ASSERT (Tcb != NULL);
317
318 Tcp4FlushPcb (Tcb);
319
320 IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);
321
322 FreePool (Tcb);
323
324 ProtoData->TcpPcb = NULL;
325 }
326
327
328 /**
329 Configure the Pcb using CfgData.
330
331 @param Sk Pointer to the socket of this TCP instance.
332 @param CfgData Pointer to the TCP configuration data.
333
334 @retval EFI_SUCCESS The operation is completed successfully.
335 @retval EFI_INVALID_PARAMETER A same access point has been configured in
336 another TCP instance.
337 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
338
339 **/
340 EFI_STATUS
341 Tcp4ConfigurePcb (
342 IN SOCKET *Sk,
343 IN EFI_TCP4_CONFIG_DATA *CfgData
344 )
345 {
346 EFI_IP4_CONFIG_DATA IpCfgData;
347 EFI_STATUS Status;
348 EFI_TCP4_OPTION *Option;
349 TCP4_PROTO_DATA *TcpProto;
350 TCP_CB *Tcb;
351
352 ASSERT ((CfgData != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL));
353
354 TcpProto = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
355 Tcb = TcpProto->TcpPcb;
356
357 ASSERT (Tcb != NULL);
358
359 //
360 // Add Ip for send pkt to the peer
361 //
362 CopyMem (&IpCfgData, &mIp4IoDefaultIpConfigData, sizeof (IpCfgData));
363 IpCfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
364 IpCfgData.UseDefaultAddress = CfgData->AccessPoint.UseDefaultAddress;
365 IpCfgData.StationAddress = CfgData->AccessPoint.StationAddress;
366 IpCfgData.SubnetMask = CfgData->AccessPoint.SubnetMask;
367 IpCfgData.ReceiveTimeout = (UINT32) (-1);
368
369 //
370 // Configure the IP instance this Tcb consumes.
371 //
372 Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);
373 if (EFI_ERROR (Status)) {
374 goto OnExit;
375 }
376
377 //
378 // Get the default address info if the instance is configured to use default address.
379 //
380 if (CfgData->AccessPoint.UseDefaultAddress) {
381 CfgData->AccessPoint.StationAddress = IpCfgData.StationAddress;
382 CfgData->AccessPoint.SubnetMask = IpCfgData.SubnetMask;
383 }
384
385 //
386 // check if we can bind this endpoint in CfgData
387 //
388 Status = Tcp4Bind (&(CfgData->AccessPoint));
389
390 if (EFI_ERROR (Status)) {
391 DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: Bind endpoint failed "
392 "with %r\n", Status));
393
394 goto OnExit;
395 }
396
397 //
398 // Initalize the operating information in this Tcb
399 //
400 ASSERT (Tcb->State == TCP_CLOSED &&
401 IsListEmpty (&Tcb->SndQue) &&
402 IsListEmpty (&Tcb->RcvQue));
403
404 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
405 Tcb->State = TCP_CLOSED;
406
407 Tcb->SndMss = 536;
408 Tcb->RcvMss = TcpGetRcvMss (Sk);
409
410 Tcb->SRtt = 0;
411 Tcb->Rto = 3 * TCP_TICK_HZ;
412
413 Tcb->CWnd = Tcb->SndMss;
414 Tcb->Ssthresh = 0xffffffff;
415
416 Tcb->CongestState = TCP_CONGEST_OPEN;
417
418 Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN;
419 Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD;
420 Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE;
421 Tcb->MaxRexmit = TCP_MAX_LOSS;
422 Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME;
423 Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME;
424 Tcb->ConnectTimeout = TCP_CONNECT_TIME;
425
426 //
427 // initialize Tcb in the light of CfgData
428 //
429 Tcb->Ttl = CfgData->TimeToLive;
430 Tcb->Tos = CfgData->TypeOfService;
431
432 Tcb->UseDefaultAddr = CfgData->AccessPoint.UseDefaultAddress;
433
434 CopyMem (&Tcb->LocalEnd.Ip, &CfgData->AccessPoint.StationAddress, sizeof (IP4_ADDR));
435 Tcb->LocalEnd.Port = HTONS (CfgData->AccessPoint.StationPort);
436 Tcb->SubnetMask = CfgData->AccessPoint.SubnetMask;
437
438 if (CfgData->AccessPoint.ActiveFlag) {
439 CopyMem (&Tcb->RemoteEnd.Ip, &CfgData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));
440 Tcb->RemoteEnd.Port = HTONS (CfgData->AccessPoint.RemotePort);
441 } else {
442 Tcb->RemoteEnd.Ip = 0;
443 Tcb->RemoteEnd.Port = 0;
444 }
445
446 Option = CfgData->ControlOption;
447
448 if (Option != NULL) {
449 SET_RCV_BUFFSIZE (
450 Sk,
451 (UINT32) (TCP_COMP_VAL (
452 TCP_RCV_BUF_SIZE_MIN,
453 TCP_RCV_BUF_SIZE,
454 TCP_RCV_BUF_SIZE,
455 Option->ReceiveBufferSize
456 )
457 )
458 );
459 SET_SND_BUFFSIZE (
460 Sk,
461 (UINT32) (TCP_COMP_VAL (
462 TCP_SND_BUF_SIZE_MIN,
463 TCP_SND_BUF_SIZE,
464 TCP_SND_BUF_SIZE,
465 Option->SendBufferSize
466 )
467 )
468 );
469
470 SET_BACKLOG (
471 Sk,
472 (UINT32) (TCP_COMP_VAL (
473 TCP_BACKLOG_MIN,
474 TCP_BACKLOG,
475 TCP_BACKLOG,
476 Option->MaxSynBackLog
477 )
478 )
479 );
480
481 Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL (
482 TCP_MAX_LOSS_MIN,
483 TCP_MAX_LOSS,
484 TCP_MAX_LOSS,
485 Option->DataRetries
486 );
487 Tcb->FinWait2Timeout = TCP_COMP_VAL (
488 TCP_FIN_WAIT2_TIME,
489 TCP_FIN_WAIT2_TIME_MAX,
490 TCP_FIN_WAIT2_TIME,
491 (UINT32) (Option->FinTimeout * TCP_TICK_HZ)
492 );
493
494 if (Option->TimeWaitTimeout != 0) {
495 Tcb->TimeWaitTimeout = TCP_COMP_VAL (
496 TCP_TIME_WAIT_TIME,
497 TCP_TIME_WAIT_TIME_MAX,
498 TCP_TIME_WAIT_TIME,
499 (UINT32) (Option->TimeWaitTimeout * TCP_TICK_HZ)
500 );
501 } else {
502 Tcb->TimeWaitTimeout = 0;
503 }
504
505 if (Option->KeepAliveProbes != 0) {
506 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
507
508 Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL (
509 TCP_MAX_KEEPALIVE_MIN,
510 TCP_MAX_KEEPALIVE,
511 TCP_MAX_KEEPALIVE,
512 Option->KeepAliveProbes
513 );
514 Tcb->KeepAliveIdle = TCP_COMP_VAL (
515 TCP_KEEPALIVE_IDLE_MIN,
516 TCP_KEEPALIVE_IDLE_MAX,
517 TCP_KEEPALIVE_IDLE_MIN,
518 (UINT32) (Option->KeepAliveTime * TCP_TICK_HZ)
519 );
520 Tcb->KeepAlivePeriod = TCP_COMP_VAL (
521 TCP_KEEPALIVE_PERIOD_MIN,
522 TCP_KEEPALIVE_PERIOD,
523 TCP_KEEPALIVE_PERIOD,
524 (UINT32) (Option->KeepAliveInterval * TCP_TICK_HZ)
525 );
526 }
527
528 Tcb->ConnectTimeout = TCP_COMP_VAL (
529 TCP_CONNECT_TIME_MIN,
530 TCP_CONNECT_TIME,
531 TCP_CONNECT_TIME,
532 (UINT32) (Option->ConnectionTimeout * TCP_TICK_HZ)
533 );
534
535 if (!Option->EnableNagle) {
536 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
537 }
538
539 if (!Option->EnableTimeStamp) {
540 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
541 }
542
543 if (!Option->EnableWindowScaling) {
544 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
545 }
546 }
547
548 //
549 // The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is
550 // determined, construct the IP device path and install it.
551 //
552 Status = TcpInstallDevicePath (Sk);
553 if (EFI_ERROR (Status)) {
554 goto OnExit;
555 }
556
557 //
558 // update state of Tcb and socket
559 //
560 if (!CfgData->AccessPoint.ActiveFlag) {
561
562 TcpSetState (Tcb, TCP_LISTEN);
563 SockSetState (Sk, SO_LISTENING);
564
565 Sk->ConfigureState = SO_CONFIGURED_PASSIVE;
566 } else {
567
568 Sk->ConfigureState = SO_CONFIGURED_ACTIVE;
569 }
570
571 TcpInsertTcb (Tcb);
572
573 OnExit:
574
575 return Status;
576 }
577
578
579 /**
580 The procotol handler provided to the socket layer, used to
581 dispatch the socket level requests by calling the corresponding
582 TCP layer functions.
583
584 @param Sock Pointer to the socket of this TCP instance.
585 @param Request The code of this operation request.
586 @param Data Pointer to the operation specific data passed in
587 together with the operation request.
588
589 @retval EFI_SUCCESS The socket request is completed successfully.
590 @retval other The error status returned by the corresponding TCP
591 layer function.
592
593 **/
594 EFI_STATUS
595 Tcp4Dispatcher (
596 IN SOCKET *Sock,
597 IN UINT8 Request,
598 IN VOID *Data OPTIONAL
599 )
600 {
601 TCP_CB *Tcb;
602 TCP4_PROTO_DATA *ProtoData;
603 EFI_IP4_PROTOCOL *Ip;
604
605 ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
606 Tcb = ProtoData->TcpPcb;
607
608 switch (Request) {
609 case SOCK_POLL:
610 Ip = (EFI_IP4_PROTOCOL *) (ProtoData->TcpService->IpIo->Ip);
611 Ip->Poll (Ip);
612 break;
613
614 case SOCK_CONSUMED:
615 //
616 // After user received data from socket buffer, socket will
617 // notify TCP using this message to give it a chance to send out
618 // window update information
619 //
620 ASSERT (Tcb != NULL);
621 TcpOnAppConsume (Tcb);
622 break;
623
624 case SOCK_SND:
625
626 ASSERT (Tcb != NULL);
627 TcpOnAppSend (Tcb);
628 break;
629
630 case SOCK_CLOSE:
631
632 TcpOnAppClose (Tcb);
633
634 break;
635
636 case SOCK_ABORT:
637
638 TcpOnAppAbort (Tcb);
639
640 break;
641
642 case SOCK_SNDPUSH:
643 Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);
644 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
645
646 break;
647
648 case SOCK_SNDURG:
649 Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;
650 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
651
652 break;
653
654 case SOCK_CONNECT:
655
656 TcpOnAppConnect (Tcb);
657
658 break;
659
660 case SOCK_ATTACH:
661
662 return Tcp4AttachPcb (Sock);
663
664 break;
665
666 case SOCK_FLUSH:
667
668 Tcp4FlushPcb (Tcb);
669
670 break;
671
672 case SOCK_DETACH:
673
674 Tcp4DetachPcb (Sock);
675
676 break;
677
678 case SOCK_CONFIGURE:
679
680 return Tcp4ConfigurePcb (
681 Sock,
682 (EFI_TCP4_CONFIG_DATA *) Data
683 );
684
685 break;
686
687 case SOCK_MODE:
688
689 ASSERT ((Data != NULL) && (Tcb != NULL));
690
691 return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);
692
693 break;
694
695 case SOCK_ROUTE:
696
697 ASSERT ((Data != NULL) && (Tcb != NULL));
698
699 return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);
700
701 default:
702 return EFI_UNSUPPORTED;
703 }
704
705 return EFI_SUCCESS;
706
707 }