]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dispatcher.c
688f9a7e99c9a01e97acef292e4456a275c8dcbf
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Dispatcher.c
1 /** @file
2 Tcp request dispatcher implementation.
3
4 Copyright (c) 2005 - 2011, 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 *Ip4;
43
44 Ip4 = Tcb->IpInfo->Ip.Ip4;
45
46 ASSERT (Ip4 != NULL);
47
48 return Ip4->Routes (
49 Ip4,
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.Ip4;
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 Tcb->State = TCP_CLOSED;
247 }
248
249 /**
250 Attach a Pcb to the socket.
251
252 @param Sk Pointer to the socket of this TCP instance.
253
254 @retval EFI_SUCCESS The operation is completed successfully.
255 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
256
257 **/
258 EFI_STATUS
259 Tcp4AttachPcb (
260 IN SOCKET *Sk
261 )
262 {
263 TCP_CB *Tcb;
264 TCP4_PROTO_DATA *ProtoData;
265 IP_IO *IpIo;
266
267 Tcb = AllocateZeroPool (sizeof (TCP_CB));
268
269 if (Tcb == NULL) {
270
271 DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: failed to allocate a TCB\n"));
272
273 return EFI_OUT_OF_RESOURCES;
274 }
275
276 ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
277 IpIo = ProtoData->TcpService->IpIo;
278
279 //
280 // Create an IpInfo for this Tcb.
281 //
282 Tcb->IpInfo = IpIoAddIp (IpIo);
283 if (Tcb->IpInfo == NULL) {
284
285 FreePool (Tcb);
286 return EFI_OUT_OF_RESOURCES;
287 }
288
289 InitializeListHead (&Tcb->List);
290 InitializeListHead (&Tcb->SndQue);
291 InitializeListHead (&Tcb->RcvQue);
292
293 Tcb->State = TCP_CLOSED;
294 Tcb->Sk = Sk;
295 ProtoData->TcpPcb = Tcb;
296
297 return EFI_SUCCESS;
298 }
299
300 /**
301 Detach the Pcb of the socket.
302
303 @param Sk Pointer to the socket of this TCP instance.
304
305 **/
306 VOID
307 Tcp4DetachPcb (
308 IN SOCKET *Sk
309 )
310 {
311 TCP4_PROTO_DATA *ProtoData;
312 TCP_CB *Tcb;
313
314 ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
315 Tcb = ProtoData->TcpPcb;
316
317 ASSERT (Tcb != NULL);
318
319 Tcp4FlushPcb (Tcb);
320
321 IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);
322
323 FreePool (Tcb);
324
325 ProtoData->TcpPcb = NULL;
326 }
327
328
329 /**
330 Configure the Pcb using CfgData.
331
332 @param Sk Pointer to the socket 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 != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL));
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, &mIp4IoDefaultIpConfigData, 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) {
537 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
538 }
539
540 if (!Option->EnableTimeStamp) {
541 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
542 }
543
544 if (!Option->EnableWindowScaling) {
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) {
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 UINT8 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.Ip4;
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 != NULL);
622 TcpOnAppConsume (Tcb);
623 break;
624
625 case SOCK_SND:
626
627 ASSERT (Tcb != NULL);
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 case SOCK_FLUSH:
666
667 Tcp4FlushPcb (Tcb);
668
669 break;
670
671 case SOCK_DETACH:
672
673 Tcp4DetachPcb (Sock);
674
675 break;
676
677 case SOCK_CONFIGURE:
678
679 return Tcp4ConfigurePcb (
680 Sock,
681 (EFI_TCP4_CONFIG_DATA *) Data
682 );
683
684 case SOCK_MODE:
685
686 ASSERT ((Data != NULL) && (Tcb != NULL));
687
688 return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);
689
690 case SOCK_ROUTE:
691
692 ASSERT ((Data != NULL) && (Tcb != NULL));
693
694 return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);
695
696 default:
697 return EFI_UNSUPPORTED;
698 }
699
700 return EFI_SUCCESS;
701
702 }