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