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