]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dispatcher.c
a6acd267ef6f8fd9a0e377e451004a0092468cac
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Dispatcher.c
1 /** @file
2 Tcp request dispatcher implementation.
3
4 Copyright (c) 2005 - 2009, Intel Corporation<BR>
5 All rights reserved. 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 protocl.
231 //
232 gBS->UninstallProtocolInterface (
233 Sock->SockHandle,
234 &gEfiDevicePathProtocolGuid,
235 Sock->DevicePath
236 );
237 gBS->FreePool (Sock->DevicePath);
238
239 TcpSetVariableData (TcpProto->TcpService);
240 }
241
242 NetbufFreeList (&Tcb->SndQue);
243 NetbufFreeList (&Tcb->RcvQue);
244 }
245
246 /**
247 Attach a Pcb to the socket.
248
249 @param Sk Pointer to the socket of this TCP instance.
250
251 @retval EFI_SUCCESS The operation is completed successfully.
252 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
253
254 **/
255 EFI_STATUS
256 Tcp4AttachPcb (
257 IN SOCKET *Sk
258 )
259 {
260 TCP_CB *Tcb;
261 TCP4_PROTO_DATA *ProtoData;
262 IP_IO *IpIo;
263
264 Tcb = AllocateZeroPool (sizeof (TCP_CB));
265
266 if (Tcb == NULL) {
267
268 DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: failed to allocate a TCB\n"));
269
270 return EFI_OUT_OF_RESOURCES;
271 }
272
273 ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
274 IpIo = ProtoData->TcpService->IpIo;
275
276 //
277 // Create an IpInfo for this Tcb.
278 //
279 Tcb->IpInfo = IpIoAddIp (IpIo);
280 if (Tcb->IpInfo == NULL) {
281
282 gBS->FreePool (Tcb);
283 return EFI_OUT_OF_RESOURCES;
284 }
285
286 InitializeListHead (&Tcb->List);
287 InitializeListHead (&Tcb->SndQue);
288 InitializeListHead (&Tcb->RcvQue);
289
290 Tcb->State = TCP_CLOSED;
291 Tcb->Sk = Sk;
292 ProtoData->TcpPcb = Tcb;
293
294 return EFI_SUCCESS;
295 }
296
297 /**
298 Detach the Pcb of the socket.
299
300 @param Sk Pointer to the socket of this TCP instance.
301
302 **/
303 VOID
304 Tcp4DetachPcb (
305 IN SOCKET *Sk
306 )
307 {
308 TCP4_PROTO_DATA *ProtoData;
309 TCP_CB *Tcb;
310
311 ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
312 Tcb = ProtoData->TcpPcb;
313
314 ASSERT (Tcb != NULL);
315
316 Tcp4FlushPcb (Tcb);
317
318 IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);
319
320 gBS->FreePool (Tcb);
321
322 ProtoData->TcpPcb = NULL;
323 }
324
325
326 /**
327 Configure the Pcb using CfgData.
328
329 @param Sk Pointer to the socket of this TCP instance.
330 @param CfgData Pointer to the TCP configuration data.
331
332 @retval EFI_SUCCESS The operation is completed successfully.
333 @retval EFI_INVALID_PARAMETER A same access point has been configured in
334 another TCP instance.
335 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
336
337 **/
338 EFI_STATUS
339 Tcp4ConfigurePcb (
340 IN SOCKET *Sk,
341 IN EFI_TCP4_CONFIG_DATA *CfgData
342 )
343 {
344 EFI_IP4_CONFIG_DATA IpCfgData;
345 EFI_STATUS Status;
346 EFI_TCP4_OPTION *Option;
347 TCP4_PROTO_DATA *TcpProto;
348 TCP_CB *Tcb;
349
350 ASSERT ((CfgData != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL));
351
352 TcpProto = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
353 Tcb = TcpProto->TcpPcb;
354
355 ASSERT (Tcb != NULL);
356
357 //
358 // Add Ip for send pkt to the peer
359 //
360 CopyMem (&IpCfgData, &mIp4IoDefaultIpConfigData, sizeof (IpCfgData));
361 IpCfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
362 IpCfgData.UseDefaultAddress = CfgData->AccessPoint.UseDefaultAddress;
363 IpCfgData.StationAddress = CfgData->AccessPoint.StationAddress;
364 IpCfgData.SubnetMask = CfgData->AccessPoint.SubnetMask;
365 IpCfgData.ReceiveTimeout = (UINT32) (-1);
366
367 //
368 // Configure the IP instance this Tcb consumes.
369 //
370 Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);
371 if (EFI_ERROR (Status)) {
372 goto OnExit;
373 }
374
375 //
376 // Get the default address info if the instance is configured to use default address.
377 //
378 if (CfgData->AccessPoint.UseDefaultAddress) {
379 CfgData->AccessPoint.StationAddress = IpCfgData.StationAddress;
380 CfgData->AccessPoint.SubnetMask = IpCfgData.SubnetMask;
381 }
382
383 //
384 // check if we can bind this endpoint in CfgData
385 //
386 Status = Tcp4Bind (&(CfgData->AccessPoint));
387
388 if (EFI_ERROR (Status)) {
389 DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: Bind endpoint failed "
390 "with %r\n", Status));
391
392 goto OnExit;
393 }
394
395 //
396 // Initalize the operating information in this Tcb
397 //
398 ASSERT (Tcb->State == TCP_CLOSED &&
399 IsListEmpty (&Tcb->SndQue) &&
400 IsListEmpty (&Tcb->RcvQue));
401
402 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
403 Tcb->State = TCP_CLOSED;
404
405 Tcb->SndMss = 536;
406 Tcb->RcvMss = TcpGetRcvMss (Sk);
407
408 Tcb->SRtt = 0;
409 Tcb->Rto = 3 * TCP_TICK_HZ;
410
411 Tcb->CWnd = Tcb->SndMss;
412 Tcb->Ssthresh = 0xffffffff;
413
414 Tcb->CongestState = TCP_CONGEST_OPEN;
415
416 Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN;
417 Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD;
418 Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE;
419 Tcb->MaxRexmit = TCP_MAX_LOSS;
420 Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME;
421 Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME;
422 Tcb->ConnectTimeout = TCP_CONNECT_TIME;
423
424 //
425 // initialize Tcb in the light of CfgData
426 //
427 Tcb->Ttl = CfgData->TimeToLive;
428 Tcb->Tos = CfgData->TypeOfService;
429
430 Tcb->UseDefaultAddr = CfgData->AccessPoint.UseDefaultAddress;
431
432 CopyMem (&Tcb->LocalEnd.Ip, &CfgData->AccessPoint.StationAddress, sizeof (IP4_ADDR));
433 Tcb->LocalEnd.Port = HTONS (CfgData->AccessPoint.StationPort);
434 Tcb->SubnetMask = CfgData->AccessPoint.SubnetMask;
435
436 if (CfgData->AccessPoint.ActiveFlag) {
437 CopyMem (&Tcb->RemoteEnd.Ip, &CfgData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));
438 Tcb->RemoteEnd.Port = HTONS (CfgData->AccessPoint.RemotePort);
439 } else {
440 Tcb->RemoteEnd.Ip = 0;
441 Tcb->RemoteEnd.Port = 0;
442 }
443
444 Option = CfgData->ControlOption;
445
446 if (Option != NULL) {
447 SET_RCV_BUFFSIZE (
448 Sk,
449 (UINT32) (TCP_COMP_VAL (
450 TCP_RCV_BUF_SIZE_MIN,
451 TCP_RCV_BUF_SIZE,
452 TCP_RCV_BUF_SIZE,
453 Option->ReceiveBufferSize
454 )
455 )
456 );
457 SET_SND_BUFFSIZE (
458 Sk,
459 (UINT32) (TCP_COMP_VAL (
460 TCP_SND_BUF_SIZE_MIN,
461 TCP_SND_BUF_SIZE,
462 TCP_SND_BUF_SIZE,
463 Option->SendBufferSize
464 )
465 )
466 );
467
468 SET_BACKLOG (
469 Sk,
470 (UINT32) (TCP_COMP_VAL (
471 TCP_BACKLOG_MIN,
472 TCP_BACKLOG,
473 TCP_BACKLOG,
474 Option->MaxSynBackLog
475 )
476 )
477 );
478
479 Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL (
480 TCP_MAX_LOSS_MIN,
481 TCP_MAX_LOSS,
482 TCP_MAX_LOSS,
483 Option->DataRetries
484 );
485 Tcb->FinWait2Timeout = TCP_COMP_VAL (
486 TCP_FIN_WAIT2_TIME,
487 TCP_FIN_WAIT2_TIME_MAX,
488 TCP_FIN_WAIT2_TIME,
489 (UINT32) (Option->FinTimeout * TCP_TICK_HZ)
490 );
491
492 if (Option->TimeWaitTimeout != 0) {
493 Tcb->TimeWaitTimeout = TCP_COMP_VAL (
494 TCP_TIME_WAIT_TIME,
495 TCP_TIME_WAIT_TIME_MAX,
496 TCP_TIME_WAIT_TIME,
497 (UINT32) (Option->TimeWaitTimeout * TCP_TICK_HZ)
498 );
499 } else {
500 Tcb->TimeWaitTimeout = 0;
501 }
502
503 if (Option->KeepAliveProbes != 0) {
504 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
505
506 Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL (
507 TCP_MAX_KEEPALIVE_MIN,
508 TCP_MAX_KEEPALIVE,
509 TCP_MAX_KEEPALIVE,
510 Option->KeepAliveProbes
511 );
512 Tcb->KeepAliveIdle = TCP_COMP_VAL (
513 TCP_KEEPALIVE_IDLE_MIN,
514 TCP_KEEPALIVE_IDLE_MAX,
515 TCP_KEEPALIVE_IDLE_MIN,
516 (UINT32) (Option->KeepAliveTime * TCP_TICK_HZ)
517 );
518 Tcb->KeepAlivePeriod = TCP_COMP_VAL (
519 TCP_KEEPALIVE_PERIOD_MIN,
520 TCP_KEEPALIVE_PERIOD,
521 TCP_KEEPALIVE_PERIOD,
522 (UINT32) (Option->KeepAliveInterval * TCP_TICK_HZ)
523 );
524 }
525
526 Tcb->ConnectTimeout = TCP_COMP_VAL (
527 TCP_CONNECT_TIME_MIN,
528 TCP_CONNECT_TIME,
529 TCP_CONNECT_TIME,
530 (UINT32) (Option->ConnectionTimeout * TCP_TICK_HZ)
531 );
532
533 if (Option->EnableNagle == FALSE) {
534 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
535 }
536
537 if (Option->EnableTimeStamp == FALSE) {
538 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
539 }
540
541 if (Option->EnableWindowScaling == FALSE) {
542 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
543 }
544 }
545
546 //
547 // The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is
548 // determined, construct the IP device path and install it.
549 //
550 Status = TcpInstallDevicePath (Sk);
551 if (EFI_ERROR (Status)) {
552 goto OnExit;
553 }
554
555 //
556 // update state of Tcb and socket
557 //
558 if (CfgData->AccessPoint.ActiveFlag == FALSE) {
559
560 TcpSetState (Tcb, TCP_LISTEN);
561 SockSetState (Sk, SO_LISTENING);
562
563 Sk->ConfigureState = SO_CONFIGURED_PASSIVE;
564 } else {
565
566 Sk->ConfigureState = SO_CONFIGURED_ACTIVE;
567 }
568
569 TcpInsertTcb (Tcb);
570
571 OnExit:
572
573 return Status;
574 }
575
576
577 /**
578 The procotol handler provided to the socket layer, used to
579 dispatch the socket level requests by calling the corresponding
580 TCP layer functions.
581
582 @param Sock Pointer to the socket of this TCP instance.
583 @param Request The code of this operation request.
584 @param Data Pointer to the operation specific data passed in
585 together with the operation request.
586
587 @retval EFI_SUCCESS The socket request is completed successfully.
588 @retval other The error status returned by the corresponding TCP
589 layer function.
590
591 **/
592 EFI_STATUS
593 Tcp4Dispatcher (
594 IN SOCKET *Sock,
595 IN SOCK_REQUEST Request,
596 IN VOID *Data OPTIONAL
597 )
598 {
599 TCP_CB *Tcb;
600 TCP4_PROTO_DATA *ProtoData;
601 EFI_IP4_PROTOCOL *Ip;
602
603 ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
604 Tcb = ProtoData->TcpPcb;
605
606 switch (Request) {
607 case SOCK_POLL:
608 Ip = (EFI_IP4_PROTOCOL *) (ProtoData->TcpService->IpIo->Ip);
609 Ip->Poll (Ip);
610 break;
611
612 case SOCK_CONSUMED:
613 //
614 // After user received data from socket buffer, socket will
615 // notify TCP using this message to give it a chance to send out
616 // window update information
617 //
618 ASSERT (Tcb != NULL);
619 TcpOnAppConsume (Tcb);
620 break;
621
622 case SOCK_SND:
623
624 ASSERT (Tcb != NULL);
625 TcpOnAppSend (Tcb);
626 break;
627
628 case SOCK_CLOSE:
629
630 TcpOnAppClose (Tcb);
631
632 break;
633
634 case SOCK_ABORT:
635
636 TcpOnAppAbort (Tcb);
637
638 break;
639
640 case SOCK_SNDPUSH:
641 Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);
642 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
643
644 break;
645
646 case SOCK_SNDURG:
647 Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;
648 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
649
650 break;
651
652 case SOCK_CONNECT:
653
654 TcpOnAppConnect (Tcb);
655
656 break;
657
658 case SOCK_ATTACH:
659
660 return Tcp4AttachPcb (Sock);
661
662 break;
663
664 case SOCK_FLUSH:
665
666 Tcp4FlushPcb (Tcb);
667
668 break;
669
670 case SOCK_DETACH:
671
672 Tcp4DetachPcb (Sock);
673
674 break;
675
676 case SOCK_CONFIGURE:
677
678 return Tcp4ConfigurePcb (
679 Sock,
680 (EFI_TCP4_CONFIG_DATA *) Data
681 );
682
683 break;
684
685 case SOCK_MODE:
686
687 ASSERT ((Data != NULL) && (Tcb != NULL));
688
689 return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);
690
691 break;
692
693 case SOCK_ROUTE:
694
695 ASSERT ((Data != NULL) && (Tcb != NULL));
696
697 return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);
698
699 default:
700 return EFI_UNSUPPORTED;
701 }
702
703 return EFI_SUCCESS;
704
705 }