1/** @file 2 Misc support routines for tcp. 3 4Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR> 5This program and the accompanying materials 6are licensed and made available under the terms and conditions of the BSD License 7which accompanies this distribution. The full text of the license may be found at 8http://opensource.org/licenses/bsd-license.php<BR> 9 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13**/ 14 15 16#include "Tcp4Main.h" 17 18#include <Library/DevicePathLib.h> 19 20LIST_ENTRY mTcpRunQue = { 21 &mTcpRunQue, 22 &mTcpRunQue 23}; 24 25LIST_ENTRY mTcpListenQue = { 26 &mTcpListenQue, 27 &mTcpListenQue 28}; 29 30TCP_SEQNO mTcpGlobalIss = 0x4d7e980b; 31 32CHAR16 *mTcpStateName[] = { 33 L"TCP_CLOSED", 34 L"TCP_LISTEN", 35 L"TCP_SYN_SENT", 36 L"TCP_SYN_RCVD", 37 L"TCP_ESTABLISHED", 38 L"TCP_FIN_WAIT_1", 39 L"TCP_FIN_WAIT_2", 40 L"TCP_CLOSING", 41 L"TCP_TIME_WAIT", 42 L"TCP_CLOSE_WAIT", 43 L"TCP_LAST_ACK" 44}; 45 46 47/** 48 Initialize the Tcb local related members. 49 50 @param Tcb Pointer to the TCP_CB of this TCP instance. 51 52**/ 53VOID 54TcpInitTcbLocal ( 55 IN OUT TCP_CB *Tcb 56 ) 57{ 58 // 59 // Compute the checksum of the fixed parts of pseudo header 60 // 61 Tcb->HeadSum = NetPseudoHeadChecksum ( 62 Tcb->LocalEnd.Ip, 63 Tcb->RemoteEnd.Ip, 64 0x06, 65 0 66 ); 67 68 Tcb->Iss = TcpGetIss (); 69 Tcb->SndUna = Tcb->Iss; 70 Tcb->SndNxt = Tcb->Iss; 71 72 Tcb->SndWl2 = Tcb->Iss; 73 Tcb->SndWnd = 536; 74 75 Tcb->RcvWnd = GET_RCV_BUFFSIZE (Tcb->Sk); 76 77 // 78 // First window size is never scaled 79 // 80 Tcb->RcvWndScale = 0; 81 82 Tcb->ProbeTimerOn = FALSE; 83} 84 85 86/** 87 Initialize the peer related members. 88 89 @param Tcb Pointer to the TCP_CB of this TCP instance. 90 @param Seg Pointer to the segment that contains the peer's 91 intial info. 92 @param Opt Pointer to the options announced by the peer. 93 94**/ 95VOID 96TcpInitTcbPeer ( 97 IN OUT TCP_CB *Tcb, 98 IN TCP_SEG *Seg, 99 IN TCP_OPTION *Opt 100 ) 101{ 102 UINT16 RcvMss; 103 104 ASSERT ((Tcb != NULL) && (Seg != NULL) && (Opt != NULL)); 105 ASSERT (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)); 106 107 Tcb->SndWnd = Seg->Wnd; 108 Tcb->SndWndMax = Tcb->SndWnd; 109 Tcb->SndWl1 = Seg->Seq; 110 111 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) { 112 Tcb->SndWl2 = Seg->Ack; 113 } else { 114 Tcb->SndWl2 = Tcb->Iss + 1; 115 } 116 117 if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_MSS)) { 118 Tcb->SndMss = (UINT16) MAX (64, Opt->Mss); 119 120 RcvMss = TcpGetRcvMss (Tcb->Sk); 121 if (Tcb->SndMss > RcvMss) { 122 Tcb->SndMss = RcvMss; 123 } 124 125 } else { 126 // 127 // One end doesn't support MSS option, use default. 128 // 129 Tcb->RcvMss = 536; 130 } 131 132 Tcb->CWnd = Tcb->SndMss; 133 134 Tcb->Irs = Seg->Seq; 135 Tcb->RcvNxt = Tcb->Irs + 1; 136 137 Tcb->RcvWl2 = Tcb->RcvNxt; 138 139 if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_WS) && 140 !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS)) { 141 142 Tcb->SndWndScale = Opt->WndScale; 143 144 Tcb->RcvWndScale = TcpComputeScale (Tcb); 145 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS); 146 147 } else { 148 // 149 // One end doesn't support window scale option. use zero. 150 // 151 Tcb->RcvWndScale = 0; 152 } 153 154 if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_TS) && 155 !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS)) { 156 157 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_TS); 158 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS); 159 160 Tcb->TsRecent = Opt->TSVal; 161 162 // 163 // Compute the effective SndMss per RFC1122 164 // section 4.2.2.6. If timestamp option is 165 // enabled, it will always occupy 12 bytes. 166 // 167 Tcb->SndMss -= TCP_OPTION_TS_ALIGNED_LEN; 168 } 169} 170 171 172/** 173 Locate a listen TCB that matchs the Local and Remote. 174 175 @param Local Pointer to the local (IP, Port). 176 @param Remote Pointer to the remote (IP, Port). 177 178 @return Pointer to the TCP_CB with the least number of wildcard, 179 if NULL no match is found. 180 181**/ 182TCP_CB * 183TcpLocateListenTcb ( 184 IN TCP_PEER *Local, 185 IN TCP_PEER *Remote 186 ) 187{ 188 LIST_ENTRY *Entry; 189 TCP_CB *Node; 190 TCP_CB *Match; 191 INTN Last; 192 INTN Cur; 193 194 Last = 4; 195 Match = NULL; 196 197 NET_LIST_FOR_EACH (Entry, &mTcpListenQue) { 198 Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List); 199 200 if ((Local->Port != Node->LocalEnd.Port) || 201 !TCP_PEER_MATCH (Remote, &Node->RemoteEnd) || 202 !TCP_PEER_MATCH (Local, &Node->LocalEnd)) { 203 204 continue; 205 } 206 207 // 208 // Compute the number of wildcard 209 // 210 Cur = 0; 211 if (Node->RemoteEnd.Ip == 0) { 212 Cur++; 213 } 214 215 if (Node->RemoteEnd.Port == 0) { 216 Cur++; 217 } 218 219 if (Node->LocalEnd.Ip == 0) { 220 Cur++; 221 } 222 223 if (Cur < Last) { 224 if (Cur == 0) { 225 return Node; 226 } 227 228 Last = Cur; 229 Match = Node; 230 } 231 } 232 233 return Match; 234} 235 236 237/** 238 Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>. 239 240 @param Addr Pointer to the IP address needs to match. 241 @param Port The port number needs to match. 242 243 @return The Tcb which matches the <Addr Port> paire exists or not. 244 245**/ 246BOOLEAN 247TcpFindTcbByPeer ( 248 IN EFI_IPv4_ADDRESS *Addr, 249 IN TCP_PORTNO Port 250 ) 251{ 252 TCP_PORTNO LocalPort; 253 LIST_ENTRY *Entry; 254 TCP_CB *Tcb; 255 256 ASSERT ((Addr != NULL) && (Port != 0)); 257 258 LocalPort = HTONS (Port); 259 260 NET_LIST_FOR_EACH (Entry, &mTcpListenQue) { 261 Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List); 262 263 if (EFI_IP4_EQUAL (Addr, &Tcb->LocalEnd.Ip) && 264 (LocalPort == Tcb->LocalEnd.Port)) { 265 266 return TRUE; 267 } 268 } 269 270 NET_LIST_FOR_EACH (Entry, &mTcpRunQue) { 271 Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List); 272 273 if (EFI_IP4_EQUAL (Addr, &Tcb->LocalEnd.Ip) && 274 (LocalPort == Tcb->LocalEnd.Port)) { 275 276 return TRUE; 277 } 278 } 279 280 return FALSE; 281} 282 283 284/** 285 Locate the TCP_CB related to the socket pair. 286 287 @param LocalPort The local port number. 288 @param LocalIp The local IP address. 289 @param RemotePort The remote port number. 290 @param RemoteIp The remote IP address. 291 @param Syn Whether to search the listen sockets, if TRUE, the 292 listen sockets are searched. 293 294 @return Pointer to the related TCP_CB, if NULL no match is found. 295 296**/ 297TCP_CB * 298TcpLocateTcb ( 299 IN TCP_PORTNO LocalPort, 300 IN UINT32 LocalIp, 301 IN TCP_PORTNO RemotePort, 302 IN UINT32 RemoteIp, 303 IN BOOLEAN Syn 304 ) 305{ 306 TCP_PEER Local; 307 TCP_PEER Remote; 308 LIST_ENTRY *Entry; 309 TCP_CB *Tcb; 310 311 Local.Port = LocalPort; 312 Local.Ip = LocalIp; 313 314 Remote.Port = RemotePort; 315 Remote.Ip = RemoteIp; 316 317 // 318 // First check for exact match. 319 // 320 NET_LIST_FOR_EACH (Entry, &mTcpRunQue) { 321 Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List); 322 323 if (TCP_PEER_EQUAL (&Remote, &Tcb->RemoteEnd) && 324 TCP_PEER_EQUAL (&Local, &Tcb->LocalEnd)) { 325 326 RemoveEntryList (&Tcb->List); 327 InsertHeadList (&mTcpRunQue, &Tcb->List); 328 329 return Tcb; 330 } 331 } 332 333 // 334 // Only check listen queue when SYN flag is on 335 // 336 if (Syn) { 337 return TcpLocateListenTcb (&Local, &Remote); 338 } 339 340 return NULL; 341} 342 343 344/** 345 Insert a Tcb into the proper queue. 346 347 @param Tcb Pointer to the TCP_CB to be inserted. 348 349 @retval 0 The Tcb is inserted successfully. 350 @retval -1 Error condition occurred. 351 352**/ 353INTN 354TcpInsertTcb ( 355 IN TCP_CB *Tcb 356 ) 357{ 358 LIST_ENTRY *Entry; 359 LIST_ENTRY *Head; 360 TCP_CB *Node; 361 362 ASSERT ( 363 (Tcb != NULL) && 364 ((Tcb->State == TCP_LISTEN) || 365 (Tcb->State == TCP_SYN_SENT) || 366 (Tcb->State == TCP_SYN_RCVD) || 367 (Tcb->State == TCP_CLOSED)) 368 ); 369 370 if (Tcb->LocalEnd.Port == 0) { 371 return -1; 372 } 373 374 Head = &mTcpRunQue; 375 376 if (Tcb->State == TCP_LISTEN) { 377 Head = &mTcpListenQue; 378 } 379 380 // 381 // Check that Tcb isn't already on the list. 382 // 383 NET_LIST_FOR_EACH (Entry, Head) { 384 Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List); 385 386 if (TCP_PEER_EQUAL (&Tcb->LocalEnd, &Node->LocalEnd) && 387 TCP_PEER_EQUAL (&Tcb->RemoteEnd, &Node->RemoteEnd)) { 388 389 return -1; 390 } 391 } 392 393 InsertHeadList (Head, &Tcb->List); 394 395 return 0; 396} 397 398 399/** 400 Clone a TCB_CB from Tcb. 401 402 @param Tcb Pointer to the TCP_CB to be cloned. 403 404 @return Pointer to the new cloned TCP_CB, if NULL error condition occurred. 405 406**/ 407TCP_CB * 408TcpCloneTcb ( 409 IN TCP_CB *Tcb 410 ) 411{ 412 TCP_CB *Clone; 413 414 Clone = AllocatePool (sizeof (TCP_CB)); 415 416 if (Clone == NULL) { 417 return NULL; 418 419 } 420 421 CopyMem (Clone, Tcb, sizeof (TCP_CB)); 422 423 // 424 // Increate the reference count of the shared IpInfo. 425 // 426 NET_GET_REF (Tcb->IpInfo); 427 428 InitializeListHead (&Clone->List); 429 InitializeListHead (&Clone->SndQue); 430 InitializeListHead (&Clone->RcvQue); 431 432 Clone->Sk = SockClone (Tcb->Sk); 433 if (Clone->Sk == NULL) { 434 DEBUG ((EFI_D_ERROR, "TcpCloneTcb: failed to clone a sock\n")); 435 FreePool (Clone); 436 return NULL; 437 } 438 439 ((TCP4_PROTO_DATA *) (Clone->Sk->ProtoReserved))->TcpPcb = Clone; 440 441 return Clone; 442} 443 444 445/** 446 Compute an ISS to be used by a new connection. 447 448 @return The result ISS. 449 450**/ 451TCP_SEQNO 452TcpGetIss ( 453 VOID 454 ) 455{ 456 mTcpGlobalIss += 2048; 457 return mTcpGlobalIss; 458} 459 460 461/** 462 Get the local mss. 463 464 @param Sock Pointer to the socket to get mss 465 466 @return The mss size. 467 468**/ 469UINT16 470TcpGetRcvMss ( 471 IN SOCKET *Sock 472 ) 473{ 474 EFI_IP4_MODE_DATA Ip4Mode; 475 TCP4_PROTO_DATA *TcpProto; 476 EFI_IP4_PROTOCOL *Ip; 477 478 ASSERT (Sock != NULL); 479 480 TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved; 481 Ip = TcpProto->TcpService->IpIo->Ip.Ip4; 482 ASSERT (Ip != NULL); 483 484 Ip->GetModeData (Ip, &Ip4Mode, NULL, NULL); 485 486 return (UINT16) (Ip4Mode.MaxPacketSize - sizeof (TCP_HEAD)); 487} 488 489 490/** 491 Set the Tcb's state. 492 493 @param Tcb Pointer to the TCP_CB of this TCP instance. 494 @param State The state to be set. 495 496**/ 497VOID 498TcpSetState ( 499 IN OUT TCP_CB *Tcb, 500 IN UINT8 State 501 ) 502{ 503 ASSERT (Tcb->State < (sizeof (mTcpStateName) / sizeof (CHAR16 *))); 504 ASSERT (State < (sizeof (mTcpStateName) / sizeof (CHAR16 *))); 505 506 DEBUG ( 507 (EFI_D_NET, 508 "Tcb (%p) state %s --> %s\n", 509 Tcb, 510 mTcpStateName[Tcb->State], 511 mTcpStateName[State]) 512 ); 513 514 Tcb->State = State; 515 516 switch (State) { 517 case TCP_ESTABLISHED: 518 519 SockConnEstablished (Tcb->Sk); 520 521 if (Tcb->Parent != NULL) { 522 // 523 // A new connection is accepted by a listening socket, install 524 // the device path. 525 // 526 TcpInstallDevicePath (Tcb->Sk); 527 } 528 529 break; 530 531 case TCP_CLOSED: 532 533 SockConnClosed (Tcb->Sk); 534 535 break; 536 default: 537 break; 538 } 539} 540 541 542/** 543 Compute the TCP segment's checksum. 544 545 @param Nbuf Pointer to the buffer that contains the TCP 546 segment. 547 @param HeadSum The checksum value of the fixed part of pseudo 548 header. 549 550 @return The checksum value. 551 552**/ 553UINT16 554TcpChecksum ( 555 IN NET_BUF *Nbuf, 556 IN UINT16 HeadSum 557 ) 558{ 559 UINT16 Checksum; 560 561 Checksum = NetbufChecksum (Nbuf); 562 Checksum = NetAddChecksum (Checksum, HeadSum); 563 564 Checksum = NetAddChecksum ( 565 Checksum, 566 HTONS ((UINT16) Nbuf->TotalSize) 567 ); 568 569 return (UINT16) ~Checksum; 570} 571 572/** 573 Translate the information from the head of the received TCP 574 segment Nbuf contains and fill it into a TCP_SEG structure. 575 576 @param Tcb Pointer to the TCP_CB of this TCP instance. 577 @param Nbuf Pointer to the buffer contains the TCP segment. 578 579 @return Pointer to the TCP_SEG that contains the translated TCP head information. 580 581**/ 582TCP_SEG * 583TcpFormatNetbuf ( 584 IN TCP_CB *Tcb, 585 IN OUT NET_BUF *Nbuf 586 ) 587{ 588 TCP_SEG *Seg; 589 TCP_HEAD *Head; 590 591 Seg = TCPSEG_NETBUF (Nbuf); 592 Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL); 593 ASSERT (Head != NULL); 594 Nbuf->Tcp = Head; 595 596 Seg->Seq = NTOHL (Head->Seq); 597 Seg->Ack = NTOHL (Head->Ack); 598 Seg->End = Seg->Seq + (Nbuf->TotalSize - (Head->HeadLen << 2)); 599 600 Seg->Urg = NTOHS (Head->Urg); 601 Seg->Wnd = (NTOHS (Head->Wnd) << Tcb->SndWndScale); 602 Seg->Flag = Head->Flag; 603 604 // 605 // SYN and FIN flag occupy one sequence space each. 606 // 607 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) { 608 // 609 // RFC requires that initial window not be scaled 610 // 611 Seg->Wnd = NTOHS (Head->Wnd); 612 Seg->End++; 613 } 614 615 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) { 616 Seg->End++; 617 } 618 619 return Seg; 620} 621 622 623/** 624 Reset the connection related with Tcb. 625 626 @param Tcb Pointer to the TCP_CB of the connection to be 627 reset. 628 629**/ 630VOID 631TcpResetConnection ( 632 IN TCP_CB *Tcb 633 ) 634{ 635 NET_BUF *Nbuf; 636 TCP_HEAD *Nhead; 637 638 Nbuf = NetbufAlloc (TCP_MAX_HEAD); 639 640 if (Nbuf == NULL) { 641 return ; 642 } 643 644 Nhead = (TCP_HEAD *) NetbufAllocSpace ( 645 Nbuf, 646 sizeof (TCP_HEAD), 647 NET_BUF_TAIL 648 ); 649 650 ASSERT (Nhead != NULL); 651 652 Nbuf->Tcp = Nhead; 653 654 Nhead->Flag = TCP_FLG_RST; 655 Nhead->Seq = HTONL (Tcb->SndNxt); 656 Nhead->Ack = HTONL (Tcb->RcvNxt); 657 Nhead->SrcPort = Tcb->LocalEnd.Port; 658 Nhead->DstPort = Tcb->RemoteEnd.Port; 659 Nhead->HeadLen = (UINT8) (sizeof (TCP_HEAD) >> 2); 660 Nhead->Res = 0; 661 Nhead->Wnd = HTONS (0xFFFF); 662 Nhead->Checksum = 0; 663 Nhead->Urg = 0; 664 Nhead->Checksum = TcpChecksum (Nbuf, Tcb->HeadSum); 665 666 TcpSendIpPacket (Tcb, Nbuf, Tcb->LocalEnd.Ip, Tcb->RemoteEnd.Ip); 667 668 NetbufFree (Nbuf); 669} 670 671 672/** 673 Initialize an active connection. 674 675 @param Tcb Pointer to the TCP_CB that wants to initiate a 676 connection. 677 678**/ 679VOID 680TcpOnAppConnect ( 681 IN OUT TCP_CB *Tcb 682 ) 683{ 684 TcpInitTcbLocal (Tcb); 685 TcpSetState (Tcb, TCP_SYN_SENT); 686 687 TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout); 688 TcpToSendData (Tcb, 1); 689} 690 691 692/** 693 Initiate the connection close procedure, called when 694 applications want to close the connection. 695 696 @param Tcb Pointer to the TCP_CB of this TCP instance. 697 698**/ 699VOID 700TcpOnAppClose ( 701 IN OUT TCP_CB *Tcb 702 ) 703{ 704 ASSERT (Tcb != NULL); 705 706 if (!IsListEmpty (&Tcb->RcvQue) || GET_RCV_DATASIZE (Tcb->Sk) != 0) { 707 708 DEBUG ((EFI_D_WARN, "TcpOnAppClose: connection reset " 709 "because data is lost for TCB %p\n", Tcb)); 710 711 TcpResetConnection (Tcb); 712 TcpClose (Tcb); 713 return; 714 } 715 716 switch (Tcb->State) { 717 case TCP_CLOSED: 718 case TCP_LISTEN: 719 case TCP_SYN_SENT: 720 TcpSetState (Tcb, TCP_CLOSED); 721 break; 722 723 case TCP_SYN_RCVD: 724 case TCP_ESTABLISHED: 725 TcpSetState (Tcb, TCP_FIN_WAIT_1); 726 break; 727 728 case TCP_CLOSE_WAIT: 729 TcpSetState (Tcb, TCP_LAST_ACK); 730 break; 731 default: 732 break; 733 } 734 735 TcpToSendData (Tcb, 1); 736} 737 738 739/** 740 Check whether the application's newly delivered data can be sent out. 741 742 @param Tcb Pointer to the TCP_CB of this TCP instance. 743 744 @retval 0 Whether the data is sent out or is buffered for 745 further sending. 746 @retval -1 The Tcb is not in a state that data is permitted to 747 be sent out. 748 749**/ 750INTN 751TcpOnAppSend ( 752 IN OUT TCP_CB *Tcb 753 ) 754{ 755 756 switch (Tcb->State) { 757 case TCP_CLOSED: 758 return -1; 759 760 case TCP_LISTEN: 761 return -1; 762 763 case TCP_SYN_SENT: 764 case TCP_SYN_RCVD: 765 return 0; 766 767 case TCP_ESTABLISHED: 768 case TCP_CLOSE_WAIT: 769 TcpToSendData (Tcb, 0); 770 return 0; 771 772 case TCP_FIN_WAIT_1: 773 case TCP_FIN_WAIT_2: 774 case TCP_CLOSING: 775 case TCP_LAST_ACK: 776 case TCP_TIME_WAIT: 777 return -1; 778 779 default: 780 break; 781 } 782 783 return 0; 784} 785 786 787/** 788 Application has consumed some data, check whether 789 to send a window updata ack or a delayed ack. 790 791 @param Tcb Pointer to the TCP_CB of this TCP instance. 792 793**/ 794VOID 795TcpOnAppConsume ( 796 IN TCP_CB *Tcb 797 ) 798{ 799 UINT32 TcpOld; 800 801 switch (Tcb->State) { 802 case TCP_CLOSED: 803 return; 804 805 case TCP_LISTEN: 806 return; 807 808 case TCP_SYN_SENT: 809 case TCP_SYN_RCVD: 810 return; 811 812 case TCP_ESTABLISHED: 813 TcpOld = TcpRcvWinOld (Tcb); 814 if (TcpRcvWinNow (Tcb) > TcpOld) { 815 816 if (TcpOld < Tcb->RcvMss) { 817 818 DEBUG ((EFI_D_NET, "TcpOnAppConsume: send a window" 819 " update for a window closed Tcb %p\n", Tcb)); 820 821 TcpSendAck (Tcb); 822 } else if (Tcb->DelayedAck == 0) { 823 824 DEBUG ((EFI_D_NET, "TcpOnAppConsume: scheduled a delayed" 825 " ACK to update window for Tcb %p\n", Tcb)); 826 827 Tcb->DelayedAck = 1; 828 } 829 } 830 831 break; 832 833 case TCP_CLOSE_WAIT: 834 return; 835 836 case TCP_FIN_WAIT_1: 837 case TCP_FIN_WAIT_2: 838 case TCP_CLOSING: 839 case TCP_LAST_ACK: 840 case TCP_TIME_WAIT: 841 return; 842 843 default: 844 break; 845 } 846} 847 848 849/** 850 Abort the connection by sending a reset segment, called 851 when the application wants to abort the connection. 852 853 @param Tcb Pointer to the TCP_CB of the TCP instance. 854 855**/ 856VOID 857TcpOnAppAbort ( 858 IN TCP_CB *Tcb 859 ) 860{ 861 DEBUG ((EFI_D_WARN, "TcpOnAppAbort: connection reset " 862 "issued by application for TCB %p\n", Tcb)); 863 864 switch (Tcb->State) { 865 case TCP_SYN_RCVD: 866 case TCP_ESTABLISHED: 867 case TCP_FIN_WAIT_1: 868 case TCP_FIN_WAIT_2: 869 case TCP_CLOSE_WAIT: 870 TcpResetConnection (Tcb); 871 break; 872 default: 873 break; 874 } 875 876 TcpSetState (Tcb, TCP_CLOSED); 877} 878 879/** 880 Install the device path protocol on the TCP instance. 881 882 @param Sock Pointer to the socket representing the TCP instance. 883 884 @retval EFI_SUCCESS The device path protocol is installed. 885 @retval other Failed to install the device path protocol. 886 887**/ 888EFI_STATUS 889TcpInstallDevicePath ( 890 IN SOCKET *Sock 891 ) 892{ 893 TCP4_PROTO_DATA *TcpProto; 894 TCP4_SERVICE_DATA *TcpService; 895 TCP_CB *Tcb; 896 IPv4_DEVICE_PATH Ip4DPathNode; 897 EFI_STATUS Status; 898 TCP_PORTNO LocalPort; 899 TCP_PORTNO RemotePort; 900 901 TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved; 902 TcpService = TcpProto->TcpService; 903 Tcb = TcpProto->TcpPcb; 904 905 LocalPort = NTOHS (Tcb->LocalEnd.Port); 906 RemotePort = NTOHS (Tcb->RemoteEnd.Port); 907 NetLibCreateIPv4DPathNode ( 908 &Ip4DPathNode, 909 TcpService->ControllerHandle, 910 Tcb->LocalEnd.Ip, 911 LocalPort, 912 Tcb->RemoteEnd.Ip, 913 RemotePort, 914 EFI_IP_PROTO_TCP, 915 Tcb->UseDefaultAddr 916 ); 917 918 IP4_COPY_ADDRESS (&Ip4DPathNode.SubnetMask, &Tcb->SubnetMask); 919 920 Sock->DevicePath = AppendDevicePathNode ( 921 Sock->ParentDevicePath, 922 (EFI_DEVICE_PATH_PROTOCOL *) &Ip4DPathNode 923 ); 924 if (Sock->DevicePath == NULL) { 925 return EFI_OUT_OF_RESOURCES; 926 } 927 928 Status = gBS->InstallProtocolInterface ( 929 &Sock->SockHandle, 930 &gEfiDevicePathProtocolGuid, 931 EFI_NATIVE_INTERFACE, 932 Sock->DevicePath 933 ); 934 if (EFI_ERROR (Status)) { 935 FreePool (Sock->DevicePath); 936 } 937 938 return Status; 939} 940