1 /** @file 2 Misc support routines for tcp. 3 4 Copyright (c) 2005 - 2015, 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 16 #include "Tcp4Main.h" 17 18 #include <Library/DevicePathLib.h> 19 20 LIST_ENTRY mTcpRunQue = { 21 &mTcpRunQue, 22 &mTcpRunQue 23 }; 24 25 LIST_ENTRY mTcpListenQue = { 26 &mTcpListenQue, 27 &mTcpListenQue 28 }; 29 30 TCP_SEQNO mTcpGlobalIss = 0x4d7e980b; 31 32 CHAR16 *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 **/ 53 VOID 54 TcpInitTcbLocal ( 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 **/ 95 VOID 96 TcpInitTcbPeer ( 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 **/ 182 TCP_CB * 183 TcpLocateListenTcb ( 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 **/ 246 BOOLEAN 247 TcpFindTcbByPeer ( 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 **/ 297 TCP_CB * 298 TcpLocateTcb ( 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 **/ 353 INTN 354 TcpInsertTcb ( 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 **/ 407 TCP_CB * 408 TcpCloneTcb ( 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 **/ 451 TCP_SEQNO 452 TcpGetIss ( 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 **/ 469 UINT16 470 TcpGetRcvMss ( 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 **/ 497 VOID 498 TcpSetState ( 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_INFO, 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 **/ 553 UINT16 554 TcpChecksum ( 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 **/ 582 TCP_SEG * 583 TcpFormatNetbuf ( 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 **/ 630 VOID 631 TcpResetConnection ( 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 **/ 679 VOID 680 TcpOnAppConnect ( 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 **/ 699 VOID 700 TcpOnAppClose ( 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 **/ 750 INTN 751 TcpOnAppSend ( 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 **/ 794 VOID 795 TcpOnAppConsume ( 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_INFO, "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_INFO, "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 **/ 856 VOID 857 TcpOnAppAbort ( 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 **/ 888 EFI_STATUS 889 TcpInstallDevicePath ( 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