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