1 /** @file 2 The implementation of a dispatch routine for processing TCP requests. 3 4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR> 5 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> 6 7 SPDX-License-Identifier: BSD-2-Clause-Patent 8 9 **/ 10 11 #include "TcpMain.h" 12 13 /** 14 Add or remove a route entry in the IP route table associated with this TCP instance. 15 16 @param[in] Tcb Pointer to the TCP_CB of this TCP instance. 17 @param[in] RouteInfo Pointer to the route information to be processed. 18 19 @retval EFI_SUCCESS The operation completed successfully. 20 @retval EFI_NOT_STARTED The driver instance has not been started. 21 @retval EFI_NO_MAPPING When using the default address, configuration(DHCP, 22 BOOTP, RARP, etc.) is not finished yet. 23 @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table. 24 @retval EFI_NOT_FOUND This route is not in the routing table 25 (when RouteInfo->DeleteRoute is TRUE). 26 @retval EFI_ACCESS_DENIED The route is already defined in the routing table 27 (when RouteInfo->DeleteRoute is FALSE). 28 **/ 29 EFI_STATUS 30 Tcp4Route ( 31 IN TCP_CB *Tcb, 32 IN TCP4_ROUTE_INFO *RouteInfo 33 ) 34 { 35 IP_IO_IP_PROTOCOL Ip; 36 37 Ip = Tcb->IpInfo->Ip; 38 39 ASSERT (Ip.Ip4!= NULL); 40 41 return Ip.Ip4->Routes ( 42 Ip.Ip4, 43 RouteInfo->DeleteRoute, 44 RouteInfo->SubnetAddress, 45 RouteInfo->SubnetMask, 46 RouteInfo->GatewayAddress 47 ); 48 49 } 50 51 /** 52 Get the operational settings of this TCPv4 instance. 53 54 @param[in] Tcb Pointer to the TCP_CB of this TCP instance. 55 @param[in, out] Mode Pointer to the buffer to store the operational 56 settings. 57 58 @retval EFI_SUCCESS The mode data was read. 59 @retval EFI_NOT_STARTED No configuration data is available because this 60 instance hasn't been started. 61 62 **/ 63 EFI_STATUS 64 Tcp4GetMode ( 65 IN TCP_CB *Tcb, 66 IN OUT TCP4_MODE_DATA *Mode 67 ) 68 { 69 SOCKET *Sock; 70 EFI_TCP4_CONFIG_DATA *ConfigData; 71 EFI_TCP4_ACCESS_POINT *AccessPoint; 72 EFI_TCP4_OPTION *Option; 73 EFI_IP4_PROTOCOL *Ip; 74 75 Sock = Tcb->Sk; 76 77 if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp4ConfigData != NULL)) { 78 return EFI_NOT_STARTED; 79 } 80 81 if (Mode->Tcp4State != NULL) { 82 *(Mode->Tcp4State) = (EFI_TCP4_CONNECTION_STATE) Tcb->State; 83 } 84 85 if (Mode->Tcp4ConfigData != NULL) { 86 87 ConfigData = Mode->Tcp4ConfigData; 88 AccessPoint = &(ConfigData->AccessPoint); 89 Option = ConfigData->ControlOption; 90 91 ConfigData->TypeOfService = Tcb->Tos; 92 ConfigData->TimeToLive = Tcb->Ttl; 93 94 AccessPoint->UseDefaultAddress = Tcb->UseDefaultAddr; 95 96 IP4_COPY_ADDRESS (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip); 97 98 IP4_COPY_ADDRESS (&AccessPoint->SubnetMask, &Tcb->SubnetMask); 99 AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port); 100 101 IP4_COPY_ADDRESS (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip); 102 103 AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port); 104 AccessPoint->ActiveFlag = (BOOLEAN) (Tcb->State != TCP_LISTEN); 105 106 if (Option != NULL) { 107 Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk); 108 Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk); 109 Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk); 110 111 Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ; 112 Option->DataRetries = Tcb->MaxRexmit; 113 Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ; 114 Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ; 115 Option->KeepAliveProbes = Tcb->MaxKeepAlive; 116 Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ; 117 Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ; 118 119 Option->EnableNagle = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE)); 120 Option->EnableTimeStamp = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS)); 121 Option->EnableWindowScaling = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS)); 122 123 Option->EnableSelectiveAck = FALSE; 124 Option->EnablePathMtuDiscovery = FALSE; 125 } 126 } 127 128 Ip = Tcb->IpInfo->Ip.Ip4; 129 ASSERT (Ip != NULL); 130 131 return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData); 132 } 133 134 /** 135 Get the operational settings of this TCPv6 instance. 136 137 @param[in] Tcb Pointer to the TCP_CB of this TCP instance. 138 @param[in, out] Mode Pointer to the buffer to store the operational 139 settings. 140 141 @retval EFI_SUCCESS The mode data was read. 142 @retval EFI_NOT_STARTED No configuration data is available because this 143 instance hasn't been started. 144 145 **/ 146 EFI_STATUS 147 Tcp6GetMode ( 148 IN TCP_CB *Tcb, 149 IN OUT TCP6_MODE_DATA *Mode 150 ) 151 { 152 SOCKET *Sock; 153 EFI_TCP6_CONFIG_DATA *ConfigData; 154 EFI_TCP6_ACCESS_POINT *AccessPoint; 155 EFI_TCP6_OPTION *Option; 156 EFI_IP6_PROTOCOL *Ip; 157 158 Sock = Tcb->Sk; 159 160 if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp6ConfigData != NULL)) { 161 return EFI_NOT_STARTED; 162 } 163 164 if (Mode->Tcp6State != NULL) { 165 *(Mode->Tcp6State) = (EFI_TCP6_CONNECTION_STATE) (Tcb->State); 166 } 167 168 if (Mode->Tcp6ConfigData != NULL) { 169 170 ConfigData = Mode->Tcp6ConfigData; 171 AccessPoint = &(ConfigData->AccessPoint); 172 Option = ConfigData->ControlOption; 173 174 ConfigData->TrafficClass = Tcb->Tos; 175 ConfigData->HopLimit = Tcb->Ttl; 176 177 AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port); 178 AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port); 179 AccessPoint->ActiveFlag = (BOOLEAN) (Tcb->State != TCP_LISTEN); 180 181 IP6_COPY_ADDRESS (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip); 182 IP6_COPY_ADDRESS (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip); 183 184 if (Option != NULL) { 185 Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk); 186 Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk); 187 Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk); 188 189 Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ; 190 Option->DataRetries = Tcb->MaxRexmit; 191 Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ; 192 Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ; 193 Option->KeepAliveProbes = Tcb->MaxKeepAlive; 194 Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ; 195 Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ; 196 197 Option->EnableNagle = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE)); 198 Option->EnableTimeStamp = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS)); 199 Option->EnableWindowScaling = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS)); 200 201 Option->EnableSelectiveAck = FALSE; 202 Option->EnablePathMtuDiscovery = FALSE; 203 } 204 } 205 206 Ip = Tcb->IpInfo->Ip.Ip6; 207 ASSERT (Ip != NULL); 208 209 return Ip->GetModeData (Ip, Mode->Ip6ModeData, Mode->MnpConfigData, Mode->SnpModeData); 210 } 211 212 /** 213 If TcpAp->StationPort isn't zero, check whether the access point 214 is registered, else generate a random station port for this 215 access point. 216 217 @param[in] TcpAp Pointer to the access point. 218 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6 219 220 @retval EFI_SUCCESS The check passed or the port is assigned. 221 @retval EFI_INVALID_PARAMETER The non-zero station port is already used. 222 @retval EFI_OUT_OF_RESOURCES No port can be allocated. 223 224 **/ 225 EFI_STATUS 226 TcpBind ( 227 IN TCP_ACCESS_POINT *TcpAp, 228 IN UINT8 IpVersion 229 ) 230 { 231 BOOLEAN Cycle; 232 EFI_IP_ADDRESS Local; 233 UINT16 *Port; 234 UINT16 *RandomPort; 235 236 if (IpVersion == IP_VERSION_4) { 237 IP4_COPY_ADDRESS (&Local, &TcpAp->Tcp4Ap.StationAddress); 238 Port = &TcpAp->Tcp4Ap.StationPort; 239 RandomPort = &mTcp4RandomPort; 240 } else { 241 IP6_COPY_ADDRESS (&Local, &TcpAp->Tcp6Ap.StationAddress); 242 Port = &TcpAp->Tcp6Ap.StationPort; 243 RandomPort = &mTcp6RandomPort; 244 } 245 246 if (0 != *Port) { 247 // 248 // Check if a same endpoing is bound. 249 // 250 if (TcpFindTcbByPeer (&Local, *Port, IpVersion)) { 251 252 return EFI_INVALID_PARAMETER; 253 } 254 } else { 255 // 256 // generate a random port 257 // 258 Cycle = FALSE; 259 260 if (TCP_PORT_USER_RESERVED == *RandomPort) { 261 *RandomPort = TCP_PORT_KNOWN; 262 } 263 264 (*RandomPort)++; 265 266 while (TcpFindTcbByPeer (&Local, *RandomPort, IpVersion)) { 267 (*RandomPort)++; 268 269 if (*RandomPort <= TCP_PORT_KNOWN) { 270 if (Cycle) { 271 DEBUG ( 272 (EFI_D_ERROR, 273 "TcpBind: no port can be allocated for this pcb\n") 274 ); 275 return EFI_OUT_OF_RESOURCES; 276 } 277 278 *RandomPort = TCP_PORT_KNOWN + 1; 279 280 Cycle = TRUE; 281 } 282 } 283 284 *Port = *RandomPort; 285 } 286 287 return EFI_SUCCESS; 288 } 289 290 /** 291 Flush the Tcb add its associated protocols. 292 293 @param[in, out] Tcb Pointer to the TCP_CB to be flushed. 294 295 **/ 296 VOID 297 TcpFlushPcb ( 298 IN OUT TCP_CB *Tcb 299 ) 300 { 301 SOCKET *Sock; 302 303 IpIoConfigIp (Tcb->IpInfo, NULL); 304 305 Sock = Tcb->Sk; 306 307 if (SOCK_IS_CONFIGURED (Sock)) { 308 RemoveEntryList (&Tcb->List); 309 310 if (Sock->DevicePath != NULL) { 311 // 312 // Uninstall the device path protocol. 313 // 314 gBS->UninstallProtocolInterface ( 315 Sock->SockHandle, 316 &gEfiDevicePathProtocolGuid, 317 Sock->DevicePath 318 ); 319 320 FreePool (Sock->DevicePath); 321 Sock->DevicePath = NULL; 322 } 323 } 324 325 NetbufFreeList (&Tcb->SndQue); 326 NetbufFreeList (&Tcb->RcvQue); 327 Tcb->State = TCP_CLOSED; 328 Tcb->RemoteIpZero = FALSE; 329 } 330 331 /** 332 Attach a Pcb to the socket. 333 334 @param[in] Sk Pointer to the socket of this TCP instance. 335 336 @retval EFI_SUCCESS The operation completed successfully. 337 @retval EFI_OUT_OF_RESOURCES Failed due to resource limits. 338 339 **/ 340 EFI_STATUS 341 TcpAttachPcb ( 342 IN SOCKET *Sk 343 ) 344 { 345 TCP_CB *Tcb; 346 TCP_PROTO_DATA *ProtoData; 347 IP_IO *IpIo; 348 EFI_STATUS Status; 349 VOID *Ip; 350 EFI_GUID *IpProtocolGuid; 351 352 if (Sk->IpVersion == IP_VERSION_4) { 353 IpProtocolGuid = &gEfiIp4ProtocolGuid; 354 } else { 355 IpProtocolGuid = &gEfiIp6ProtocolGuid; 356 } 357 358 Tcb = AllocateZeroPool (sizeof (TCP_CB)); 359 360 if (Tcb == NULL) { 361 362 DEBUG ((EFI_D_ERROR, "TcpConfigurePcb: failed to allocate a TCB\n")); 363 364 return EFI_OUT_OF_RESOURCES; 365 } 366 367 ProtoData = (TCP_PROTO_DATA *) Sk->ProtoReserved; 368 IpIo = ProtoData->TcpService->IpIo; 369 370 // 371 // Create an IpInfo for this Tcb. 372 // 373 Tcb->IpInfo = IpIoAddIp (IpIo); 374 if (Tcb->IpInfo == NULL) { 375 376 FreePool (Tcb); 377 return EFI_OUT_OF_RESOURCES; 378 } 379 380 // 381 // Open the new created IP instance BY_CHILD. 382 // 383 Status = gBS->OpenProtocol ( 384 Tcb->IpInfo->ChildHandle, 385 IpProtocolGuid, 386 &Ip, 387 IpIo->Image, 388 Sk->SockHandle, 389 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 390 ); 391 if (EFI_ERROR (Status)) { 392 IpIoRemoveIp (IpIo, Tcb->IpInfo); 393 FreePool (Tcb); 394 return Status; 395 } 396 397 InitializeListHead (&Tcb->List); 398 InitializeListHead (&Tcb->SndQue); 399 InitializeListHead (&Tcb->RcvQue); 400 401 Tcb->State = TCP_CLOSED; 402 Tcb->Sk = Sk; 403 ProtoData->TcpPcb = Tcb; 404 405 return EFI_SUCCESS; 406 } 407 408 /** 409 Detach the Pcb of the socket. 410 411 @param[in, out] Sk Pointer to the socket of this TCP instance. 412 413 **/ 414 VOID 415 TcpDetachPcb ( 416 IN OUT SOCKET *Sk 417 ) 418 { 419 TCP_PROTO_DATA *ProtoData; 420 TCP_CB *Tcb; 421 422 ProtoData = (TCP_PROTO_DATA *) Sk->ProtoReserved; 423 Tcb = ProtoData->TcpPcb; 424 425 ASSERT (Tcb != NULL); 426 427 TcpFlushPcb (Tcb); 428 429 IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo); 430 431 FreePool (Tcb); 432 433 ProtoData->TcpPcb = NULL; 434 } 435 436 /** 437 Configure the Pcb using CfgData. 438 439 @param[in] Sk Pointer to the socket of this TCP instance. 440 @param[in] CfgData Pointer to the TCP configuration data. 441 442 @retval EFI_SUCCESS The operation completed successfully. 443 @retval EFI_INVALID_PARAMETER A same access point has been configured in 444 another TCP instance. 445 @retval EFI_OUT_OF_RESOURCES Failed due to resource limits. 446 447 **/ 448 EFI_STATUS 449 TcpConfigurePcb ( 450 IN SOCKET *Sk, 451 IN TCP_CONFIG_DATA *CfgData 452 ) 453 { 454 IP_IO_IP_CONFIG_DATA IpCfgData; 455 EFI_STATUS Status; 456 EFI_TCP4_OPTION *Option; 457 TCP_PROTO_DATA *TcpProto; 458 TCP_CB *Tcb; 459 TCP_ACCESS_POINT *TcpAp; 460 461 ASSERT ((CfgData != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL)); 462 463 TcpProto = (TCP_PROTO_DATA *) Sk->ProtoReserved; 464 Tcb = TcpProto->TcpPcb; 465 466 ASSERT (Tcb != NULL); 467 468 if (Sk->IpVersion == IP_VERSION_4) { 469 // 470 // Add Ip for send pkt to the peer 471 // 472 CopyMem (&IpCfgData.Ip4CfgData, &mIp4IoDefaultIpConfigData, sizeof (EFI_IP4_CONFIG_DATA)); 473 IpCfgData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP; 474 IpCfgData.Ip4CfgData.TypeOfService = CfgData->Tcp4CfgData.TypeOfService; 475 IpCfgData.Ip4CfgData.TimeToLive = CfgData->Tcp4CfgData.TimeToLive; 476 IpCfgData.Ip4CfgData.UseDefaultAddress = CfgData->Tcp4CfgData.AccessPoint.UseDefaultAddress; 477 IP4_COPY_ADDRESS ( 478 &IpCfgData.Ip4CfgData.SubnetMask, 479 &CfgData->Tcp4CfgData.AccessPoint.SubnetMask 480 ); 481 IpCfgData.Ip4CfgData.ReceiveTimeout = (UINT32) (-1); 482 IP4_COPY_ADDRESS ( 483 &IpCfgData.Ip4CfgData.StationAddress, 484 &CfgData->Tcp4CfgData.AccessPoint.StationAddress 485 ); 486 487 } else { 488 ASSERT (Sk->IpVersion == IP_VERSION_6); 489 490 CopyMem (&IpCfgData.Ip6CfgData, &mIp6IoDefaultIpConfigData, sizeof (EFI_IP6_CONFIG_DATA)); 491 IpCfgData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP; 492 IpCfgData.Ip6CfgData.TrafficClass = CfgData->Tcp6CfgData.TrafficClass; 493 IpCfgData.Ip6CfgData.HopLimit = CfgData->Tcp6CfgData.HopLimit; 494 IpCfgData.Ip6CfgData.ReceiveTimeout = (UINT32) (-1); 495 IP6_COPY_ADDRESS ( 496 &IpCfgData.Ip6CfgData.StationAddress, 497 &CfgData->Tcp6CfgData.AccessPoint.StationAddress 498 ); 499 IP6_COPY_ADDRESS ( 500 &IpCfgData.Ip6CfgData.DestinationAddress, 501 &CfgData->Tcp6CfgData.AccessPoint.RemoteAddress 502 ); 503 } 504 505 // 506 // Configure the IP instance this Tcb consumes. 507 // 508 Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData); 509 if (EFI_ERROR (Status)) { 510 goto OnExit; 511 } 512 513 if (Sk->IpVersion == IP_VERSION_4) { 514 // 515 // Get the default address information if the instance is configured to use default address. 516 // 517 IP4_COPY_ADDRESS ( 518 &CfgData->Tcp4CfgData.AccessPoint.StationAddress, 519 &IpCfgData.Ip4CfgData.StationAddress 520 ); 521 IP4_COPY_ADDRESS ( 522 &CfgData->Tcp4CfgData.AccessPoint.SubnetMask, 523 &IpCfgData.Ip4CfgData.SubnetMask 524 ); 525 526 TcpAp = (TCP_ACCESS_POINT *) &CfgData->Tcp4CfgData.AccessPoint; 527 } else { 528 IP6_COPY_ADDRESS ( 529 &CfgData->Tcp6CfgData.AccessPoint.StationAddress, 530 &IpCfgData.Ip6CfgData.StationAddress 531 ); 532 533 TcpAp = (TCP_ACCESS_POINT *) &CfgData->Tcp6CfgData.AccessPoint; 534 } 535 536 // 537 // check if we can bind this endpoint in CfgData 538 // 539 Status = TcpBind (TcpAp, Sk->IpVersion); 540 541 if (EFI_ERROR (Status)) { 542 DEBUG ( 543 (EFI_D_ERROR, 544 "TcpConfigurePcb: Bind endpoint failed with %r\n", 545 Status) 546 ); 547 548 goto OnExit; 549 } 550 551 // 552 // Initialize the operating information in this Tcb 553 // 554 ASSERT (Tcb->State == TCP_CLOSED && 555 IsListEmpty (&Tcb->SndQue) && 556 IsListEmpty (&Tcb->RcvQue)); 557 558 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE); 559 Tcb->State = TCP_CLOSED; 560 561 Tcb->SndMss = 536; 562 Tcb->RcvMss = TcpGetRcvMss (Sk); 563 564 Tcb->SRtt = 0; 565 Tcb->Rto = 3 * TCP_TICK_HZ; 566 567 Tcb->CWnd = Tcb->SndMss; 568 Tcb->Ssthresh = 0xffffffff; 569 570 Tcb->CongestState = TCP_CONGEST_OPEN; 571 572 Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN; 573 Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD; 574 Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE; 575 Tcb->MaxRexmit = TCP_MAX_LOSS; 576 Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME; 577 Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME; 578 Tcb->ConnectTimeout = TCP_CONNECT_TIME; 579 580 if (Sk->IpVersion == IP_VERSION_4) { 581 // 582 // initialize Tcb in the light of CfgData 583 // 584 Tcb->Ttl = CfgData->Tcp4CfgData.TimeToLive; 585 Tcb->Tos = CfgData->Tcp4CfgData.TypeOfService; 586 587 Tcb->UseDefaultAddr = CfgData->Tcp4CfgData.AccessPoint.UseDefaultAddress; 588 589 CopyMem (&Tcb->LocalEnd.Ip, &CfgData->Tcp4CfgData.AccessPoint.StationAddress, sizeof (IP4_ADDR)); 590 Tcb->LocalEnd.Port = HTONS (CfgData->Tcp4CfgData.AccessPoint.StationPort); 591 IP4_COPY_ADDRESS (&Tcb->SubnetMask, &CfgData->Tcp4CfgData.AccessPoint.SubnetMask); 592 593 CopyMem (&Tcb->RemoteEnd.Ip, &CfgData->Tcp4CfgData.AccessPoint.RemoteAddress, sizeof (IP4_ADDR)); 594 Tcb->RemoteEnd.Port = HTONS (CfgData->Tcp4CfgData.AccessPoint.RemotePort); 595 596 Option = CfgData->Tcp4CfgData.ControlOption; 597 } else { 598 Tcb->Ttl = CfgData->Tcp6CfgData.HopLimit; 599 Tcb->Tos = CfgData->Tcp6CfgData.TrafficClass; 600 601 IP6_COPY_ADDRESS (&Tcb->LocalEnd.Ip, &CfgData->Tcp6CfgData.AccessPoint.StationAddress); 602 Tcb->LocalEnd.Port = HTONS (CfgData->Tcp6CfgData.AccessPoint.StationPort); 603 604 IP6_COPY_ADDRESS (&Tcb->RemoteEnd.Ip, &CfgData->Tcp6CfgData.AccessPoint.RemoteAddress); 605 Tcb->RemoteEnd.Port = HTONS (CfgData->Tcp6CfgData.AccessPoint.RemotePort); 606 607 // 608 // Type EFI_TCP4_OPTION and EFI_TCP6_OPTION are the same. 609 // 610 Option = (EFI_TCP4_OPTION *) CfgData->Tcp6CfgData.ControlOption; 611 } 612 613 if (Option != NULL) { 614 SET_RCV_BUFFSIZE ( 615 Sk, 616 (UINT32) (TCP_COMP_VAL ( 617 TCP_RCV_BUF_SIZE_MIN, 618 TCP_RCV_BUF_SIZE, 619 TCP_RCV_BUF_SIZE, 620 Option->ReceiveBufferSize 621 ) 622 ) 623 ); 624 SET_SND_BUFFSIZE ( 625 Sk, 626 (UINT32) (TCP_COMP_VAL ( 627 TCP_SND_BUF_SIZE_MIN, 628 TCP_SND_BUF_SIZE, 629 TCP_SND_BUF_SIZE, 630 Option->SendBufferSize 631 ) 632 ) 633 ); 634 635 SET_BACKLOG ( 636 Sk, 637 (UINT32) (TCP_COMP_VAL ( 638 TCP_BACKLOG_MIN, 639 TCP_BACKLOG, 640 TCP_BACKLOG, 641 Option->MaxSynBackLog 642 ) 643 ) 644 ); 645 646 Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL ( 647 TCP_MAX_LOSS_MIN, 648 TCP_MAX_LOSS, 649 TCP_MAX_LOSS, 650 Option->DataRetries 651 ); 652 Tcb->FinWait2Timeout = TCP_COMP_VAL ( 653 TCP_FIN_WAIT2_TIME, 654 TCP_FIN_WAIT2_TIME_MAX, 655 TCP_FIN_WAIT2_TIME, 656 (UINT32) (Option->FinTimeout * TCP_TICK_HZ) 657 ); 658 659 if (Option->TimeWaitTimeout != 0) { 660 Tcb->TimeWaitTimeout = TCP_COMP_VAL ( 661 TCP_TIME_WAIT_TIME, 662 TCP_TIME_WAIT_TIME_MAX, 663 TCP_TIME_WAIT_TIME, 664 (UINT32) (Option->TimeWaitTimeout * TCP_TICK_HZ) 665 ); 666 } else { 667 Tcb->TimeWaitTimeout = 0; 668 } 669 670 if (Option->KeepAliveProbes != 0) { 671 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE); 672 673 Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL ( 674 TCP_MAX_KEEPALIVE_MIN, 675 TCP_MAX_KEEPALIVE, 676 TCP_MAX_KEEPALIVE, 677 Option->KeepAliveProbes 678 ); 679 Tcb->KeepAliveIdle = TCP_COMP_VAL ( 680 TCP_KEEPALIVE_IDLE_MIN, 681 TCP_KEEPALIVE_IDLE_MAX, 682 TCP_KEEPALIVE_IDLE_MIN, 683 (UINT32) (Option->KeepAliveTime * TCP_TICK_HZ) 684 ); 685 Tcb->KeepAlivePeriod = TCP_COMP_VAL ( 686 TCP_KEEPALIVE_PERIOD_MIN, 687 TCP_KEEPALIVE_PERIOD, 688 TCP_KEEPALIVE_PERIOD, 689 (UINT32) (Option->KeepAliveInterval * TCP_TICK_HZ) 690 ); 691 } 692 693 Tcb->ConnectTimeout = TCP_COMP_VAL ( 694 TCP_CONNECT_TIME_MIN, 695 TCP_CONNECT_TIME, 696 TCP_CONNECT_TIME, 697 (UINT32) (Option->ConnectionTimeout * TCP_TICK_HZ) 698 ); 699 700 if (!Option->EnableNagle) { 701 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE); 702 } 703 704 if (!Option->EnableTimeStamp) { 705 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS); 706 } 707 708 if (!Option->EnableWindowScaling) { 709 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS); 710 } 711 } 712 713 // 714 // The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is 715 // determined, construct the IP device path and install it. 716 // 717 Status = TcpInstallDevicePath (Sk); 718 if (EFI_ERROR (Status)) { 719 goto OnExit; 720 } 721 722 // 723 // update state of Tcb and socket 724 // 725 if (((Sk->IpVersion == IP_VERSION_4) && !CfgData->Tcp4CfgData.AccessPoint.ActiveFlag) || 726 ((Sk->IpVersion == IP_VERSION_6) && !CfgData->Tcp6CfgData.AccessPoint.ActiveFlag) 727 ) { 728 729 TcpSetState (Tcb, TCP_LISTEN); 730 SockSetState (Sk, SO_LISTENING); 731 732 Sk->ConfigureState = SO_CONFIGURED_PASSIVE; 733 } else { 734 735 Sk->ConfigureState = SO_CONFIGURED_ACTIVE; 736 } 737 738 if (Sk->IpVersion == IP_VERSION_6) { 739 Tcb->Tick = TCP6_REFRESH_NEIGHBOR_TICK; 740 741 if (NetIp6IsUnspecifiedAddr (&Tcb->RemoteEnd.Ip.v6)) { 742 Tcb->RemoteIpZero = TRUE; 743 } 744 } 745 746 TcpInsertTcb (Tcb); 747 748 OnExit: 749 750 return Status; 751 } 752 753 /** 754 The protocol handler provided to the socket layer, which is used to 755 dispatch the socket level requests by calling the corresponding 756 TCP layer functions. 757 758 @param[in] Sock Pointer to the socket of this TCP instance. 759 @param[in] Request The code of this operation request. 760 @param[in] Data Pointer to the operation specific data passed in 761 together with the operation request. This is an 762 optional parameter that may be NULL. 763 764 @retval EFI_SUCCESS The socket request completed successfully. 765 @retval other The error status returned by the corresponding TCP 766 layer function. 767 768 **/ 769 EFI_STATUS 770 TcpDispatcher ( 771 IN SOCKET *Sock, 772 IN UINT8 Request, 773 IN VOID *Data OPTIONAL 774 ) 775 { 776 TCP_CB *Tcb; 777 TCP_PROTO_DATA *ProtoData; 778 779 ProtoData = (TCP_PROTO_DATA *) Sock->ProtoReserved; 780 Tcb = ProtoData->TcpPcb; 781 782 switch (Request) { 783 case SOCK_POLL: 784 if (Tcb->Sk->IpVersion == IP_VERSION_4) { 785 ProtoData->TcpService->IpIo->Ip.Ip4->Poll (ProtoData->TcpService->IpIo->Ip.Ip4); 786 } else { 787 ProtoData->TcpService->IpIo->Ip.Ip6->Poll (ProtoData->TcpService->IpIo->Ip.Ip6); 788 } 789 790 break; 791 792 case SOCK_CONSUMED: 793 // 794 // After user received data from socket buffer, socket will 795 // notify TCP using this message to give it a chance to send out 796 // window update information 797 // 798 ASSERT (Tcb != NULL); 799 TcpOnAppConsume (Tcb); 800 break; 801 802 case SOCK_SND: 803 804 ASSERT (Tcb != NULL); 805 TcpOnAppSend (Tcb); 806 break; 807 808 case SOCK_CLOSE: 809 810 TcpOnAppClose (Tcb); 811 812 break; 813 814 case SOCK_ABORT: 815 816 TcpOnAppAbort (Tcb); 817 818 break; 819 820 case SOCK_SNDPUSH: 821 Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk); 822 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH); 823 824 break; 825 826 case SOCK_SNDURG: 827 Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1; 828 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG); 829 830 break; 831 832 case SOCK_CONNECT: 833 834 TcpOnAppConnect (Tcb); 835 836 break; 837 838 case SOCK_ATTACH: 839 840 return TcpAttachPcb (Sock); 841 842 break; 843 844 case SOCK_FLUSH: 845 846 TcpFlushPcb (Tcb); 847 848 break; 849 850 case SOCK_DETACH: 851 852 TcpDetachPcb (Sock); 853 854 break; 855 856 case SOCK_CONFIGURE: 857 858 return TcpConfigurePcb ( 859 Sock, 860 (TCP_CONFIG_DATA *) Data 861 ); 862 863 break; 864 865 case SOCK_MODE: 866 867 ASSERT ((Data != NULL) && (Tcb != NULL)); 868 869 if (Tcb->Sk->IpVersion == IP_VERSION_4) { 870 871 return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data); 872 } else { 873 874 return Tcp6GetMode (Tcb, (TCP6_MODE_DATA *) Data); 875 } 876 877 break; 878 879 case SOCK_ROUTE: 880 881 ASSERT ((Data != NULL) && (Tcb != NULL) && (Tcb->Sk->IpVersion == IP_VERSION_4)); 882 883 return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data); 884 885 default: 886 887 return EFI_UNSUPPORTED; 888 } 889 890 return EFI_SUCCESS; 891 } 892