1 /** @file 2 TCP input process routines. 3 4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php. 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "TcpMain.h" 17 18 /** 19 Check whether the sequence number of the incoming segment is acceptable. 20 21 @param[in] Tcb Pointer to the TCP_CB of this TCP instance. 22 @param[in] Seg Pointer to the incoming segment. 23 24 @retval 1 The sequence number is acceptable. 25 @retval 0 The sequence number is not acceptable. 26 27 **/ 28 INTN 29 TcpSeqAcceptable ( 30 IN TCP_CB *Tcb, 31 IN TCP_SEG *Seg 32 ) 33 { 34 return (TCP_SEQ_LEQ (Tcb->RcvWl2, Seg->End) && 35 TCP_SEQ_LT (Seg->Seq, Tcb->RcvWl2 + Tcb->RcvWnd)); 36 } 37 38 /** 39 NewReno fast recovery defined in RFC3782. 40 41 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance. 42 @param[in] Seg Segment that triggers the fast recovery. 43 44 **/ 45 VOID 46 TcpFastRecover ( 47 IN OUT TCP_CB *Tcb, 48 IN TCP_SEG *Seg 49 ) 50 { 51 UINT32 FlightSize; 52 UINT32 Acked; 53 54 // 55 // Step 1: Three duplicate ACKs and not in fast recovery 56 // 57 if (Tcb->CongestState != TCP_CONGEST_RECOVER) { 58 59 // 60 // Step 1A: Invoking fast retransmission. 61 // 62 FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna); 63 64 Tcb->Ssthresh = MAX (FlightSize >> 1, (UINT32) (2 * Tcb->SndMss)); 65 Tcb->Recover = Tcb->SndNxt; 66 67 Tcb->CongestState = TCP_CONGEST_RECOVER; 68 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON); 69 70 // 71 // Step 2: Entering fast retransmission 72 // 73 TcpRetransmit (Tcb, Tcb->SndUna); 74 Tcb->CWnd = Tcb->Ssthresh + 3 * Tcb->SndMss; 75 76 DEBUG ( 77 (EFI_D_INFO, 78 "TcpFastRecover: enter fast retransmission for TCB %p, recover point is %d\n", 79 Tcb, 80 Tcb->Recover) 81 ); 82 return; 83 } 84 85 // 86 // During fast recovery, execute Step 3, 4, 5 of RFC3782 87 // 88 if (Seg->Ack == Tcb->SndUna) { 89 90 // 91 // Step 3: Fast Recovery, 92 // If this is a duplicated ACK, increse Cwnd by SMSS. 93 // 94 95 // Step 4 is skipped here only to be executed later 96 // by TcpToSendData 97 // 98 Tcb->CWnd += Tcb->SndMss; 99 DEBUG ( 100 (EFI_D_INFO, 101 "TcpFastRecover: received another duplicated ACK (%d) for TCB %p\n", 102 Seg->Ack, 103 Tcb) 104 ); 105 106 } else { 107 108 // 109 // New data is ACKed, check whether it is a 110 // full ACK or partial ACK 111 // 112 if (TCP_SEQ_GEQ (Seg->Ack, Tcb->Recover)) { 113 114 // 115 // Step 5 - Full ACK: 116 // deflate the congestion window, and exit fast recovery 117 // 118 FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna); 119 120 Tcb->CWnd = MIN (Tcb->Ssthresh, FlightSize + Tcb->SndMss); 121 122 Tcb->CongestState = TCP_CONGEST_OPEN; 123 DEBUG ( 124 (EFI_D_INFO, 125 "TcpFastRecover: received a full ACK(%d) for TCB %p, exit fast recovery\n", 126 Seg->Ack, 127 Tcb) 128 ); 129 130 } else { 131 132 // 133 // Step 5 - Partial ACK: 134 // fast retransmit the first unacknowledge field 135 // , then deflate the CWnd 136 // 137 TcpRetransmit (Tcb, Seg->Ack); 138 Acked = TCP_SUB_SEQ (Seg->Ack, Tcb->SndUna); 139 140 // 141 // Deflate the CWnd by the amount of new data 142 // ACKed by SEG.ACK. If more than one SMSS data 143 // is ACKed, add back SMSS byte to CWnd after 144 // 145 if (Acked >= Tcb->SndMss) { 146 Acked -= Tcb->SndMss; 147 148 } 149 150 Tcb->CWnd -= Acked; 151 152 DEBUG ( 153 (EFI_D_INFO, 154 "TcpFastRecover: received a partial ACK(%d) for TCB %p\n", 155 Seg->Ack, 156 Tcb) 157 ); 158 159 } 160 } 161 } 162 163 /** 164 NewReno fast loss recovery defined in RFC3792. 165 166 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance. 167 @param[in] Seg Segment that triggers the fast loss recovery. 168 169 **/ 170 VOID 171 TcpFastLossRecover ( 172 IN OUT TCP_CB *Tcb, 173 IN TCP_SEG *Seg 174 ) 175 { 176 if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) { 177 178 // 179 // New data is ACKed, check whether it is a 180 // full ACK or partial ACK 181 // 182 if (TCP_SEQ_GEQ (Seg->Ack, Tcb->LossRecover)) { 183 184 // 185 // Full ACK: exit the loss recovery. 186 // 187 Tcb->LossTimes = 0; 188 Tcb->CongestState = TCP_CONGEST_OPEN; 189 190 DEBUG ( 191 (EFI_D_INFO, 192 "TcpFastLossRecover: received a full ACK(%d) for TCB %p\n", 193 Seg->Ack, 194 Tcb) 195 ); 196 197 } else { 198 199 // 200 // Partial ACK: 201 // fast retransmit the first unacknowledge field. 202 // 203 TcpRetransmit (Tcb, Seg->Ack); 204 DEBUG ( 205 (EFI_D_INFO, 206 "TcpFastLossRecover: received a partial ACK(%d) for TCB %p\n", 207 Seg->Ack, 208 Tcb) 209 ); 210 } 211 } 212 } 213 214 /** 215 Compute the RTT as specified in RFC2988. 216 217 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance. 218 @param[in] Measure Currently measured RTT in heartbeats. 219 220 **/ 221 VOID 222 TcpComputeRtt ( 223 IN OUT TCP_CB *Tcb, 224 IN UINT32 Measure 225 ) 226 { 227 INT32 Var; 228 229 // 230 // Step 2.3: Compute the RTO for subsequent RTT measurement. 231 // 232 if (Tcb->SRtt != 0) { 233 234 Var = Tcb->SRtt - (Measure << TCP_RTT_SHIFT); 235 236 if (Var < 0) { 237 Var = -Var; 238 } 239 240 Tcb->RttVar = (3 * Tcb->RttVar + Var) >> 2; 241 Tcb->SRtt = 7 * (Tcb->SRtt >> 3) + Measure; 242 243 } else { 244 // 245 // Step 2.2: compute the first RTT measure 246 // 247 Tcb->SRtt = Measure << TCP_RTT_SHIFT; 248 Tcb->RttVar = Measure << (TCP_RTT_SHIFT - 1); 249 } 250 251 Tcb->Rto = (Tcb->SRtt + MAX (8, 4 * Tcb->RttVar)) >> TCP_RTT_SHIFT; 252 253 // 254 // Step 2.4: Limit the RTO to at least 1 second 255 // Step 2.5: Limit the RTO to a maxium value that 256 // is at least 60 second 257 // 258 if (Tcb->Rto < TCP_RTO_MIN) { 259 Tcb->Rto = TCP_RTO_MIN; 260 261 } else if (Tcb->Rto > TCP_RTO_MAX) { 262 Tcb->Rto = TCP_RTO_MAX; 263 264 } 265 266 DEBUG ( 267 (EFI_D_INFO, 268 "TcpComputeRtt: new RTT for TCB %p computed SRTT: %d RTTVAR: %d RTO: %d\n", 269 Tcb, 270 Tcb->SRtt, 271 Tcb->RttVar, 272 Tcb->Rto) 273 ); 274 275 } 276 277 /** 278 Trim the data; SYN and FIN to fit into the window defined by Left and Right. 279 280 @param[in] Nbuf The buffer that contains a received TCP segment without an IP header. 281 @param[in] Left The sequence number of the window's left edge. 282 @param[in] Right The sequence number of the window's right edge. 283 284 **/ 285 VOID 286 TcpTrimSegment ( 287 IN NET_BUF *Nbuf, 288 IN TCP_SEQNO Left, 289 IN TCP_SEQNO Right 290 ) 291 { 292 TCP_SEG *Seg; 293 TCP_SEQNO Urg; 294 UINT32 Drop; 295 296 Seg = TCPSEG_NETBUF (Nbuf); 297 298 // 299 // If the segment is completely out of window, 300 // truncate every thing, include SYN and FIN. 301 // 302 if (TCP_SEQ_LEQ (Seg->End, Left) || TCP_SEQ_LEQ (Right, Seg->Seq)) { 303 304 TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_SYN); 305 TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_FIN); 306 307 Seg->Seq = Seg->End; 308 NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_HEAD); 309 return; 310 } 311 312 // 313 // Adjust the buffer header 314 // 315 if (TCP_SEQ_LT (Seg->Seq, Left)) { 316 317 Drop = TCP_SUB_SEQ (Left, Seg->Seq); 318 Urg = Seg->Seq + Seg->Urg; 319 Seg->Seq = Left; 320 321 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) { 322 TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_SYN); 323 Drop--; 324 } 325 326 // 327 // Adjust the urgent point 328 // 329 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_URG)) { 330 331 if (TCP_SEQ_LT (Urg, Seg->Seq)) { 332 333 TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_URG); 334 } else { 335 Seg->Urg = (UINT16) TCP_SUB_SEQ (Urg, Seg->Seq); 336 } 337 } 338 339 if (Drop != 0) { 340 NetbufTrim (Nbuf, Drop, NET_BUF_HEAD); 341 } 342 } 343 344 // 345 // Adjust the buffer tail 346 // 347 if (TCP_SEQ_GT (Seg->End, Right)) { 348 349 Drop = TCP_SUB_SEQ (Seg->End, Right); 350 Seg->End = Right; 351 352 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) { 353 TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_FIN); 354 Drop--; 355 } 356 357 if (Drop != 0) { 358 NetbufTrim (Nbuf, Drop, NET_BUF_TAIL); 359 } 360 } 361 362 ASSERT (TcpVerifySegment (Nbuf) != 0); 363 } 364 365 /** 366 Trim off the data outside the tcb's receive window. 367 368 @param[in] Tcb Pointer to the TCP_CB of this TCP instance. 369 @param[in] Nbuf Pointer to the NET_BUF containing the received tcp segment. 370 371 **/ 372 VOID 373 TcpTrimInWnd ( 374 IN TCP_CB *Tcb, 375 IN NET_BUF *Nbuf 376 ) 377 { 378 TcpTrimSegment (Nbuf, Tcb->RcvNxt, Tcb->RcvWl2 + Tcb->RcvWnd); 379 } 380 381 /** 382 Process the data and FIN flag, and check whether to deliver 383 data to the socket layer. 384 385 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance. 386 387 @retval 0 No error occurred to deliver data. 388 @retval -1 An error condition occurred. The proper response is to reset the 389 connection. 390 391 **/ 392 INTN 393 TcpDeliverData ( 394 IN OUT TCP_CB *Tcb 395 ) 396 { 397 LIST_ENTRY *Entry; 398 NET_BUF *Nbuf; 399 TCP_SEQNO Seq; 400 TCP_SEG *Seg; 401 UINT32 Urgent; 402 403 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL)); 404 405 // 406 // make sure there is some data queued, 407 // and TCP is in a proper state 408 // 409 if (IsListEmpty (&Tcb->RcvQue) || !TCP_CONNECTED (Tcb->State)) { 410 411 return 0; 412 } 413 414 // 415 // Deliver data to the socket layer 416 // 417 Entry = Tcb->RcvQue.ForwardLink; 418 Seq = Tcb->RcvNxt; 419 420 while (Entry != &Tcb->RcvQue) { 421 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List); 422 Seg = TCPSEG_NETBUF (Nbuf); 423 424 ASSERT (TcpVerifySegment (Nbuf) != 0); 425 ASSERT (Nbuf->Tcp == NULL); 426 427 if (TCP_SEQ_GT (Seg->Seq, Seq)) { 428 break; 429 } 430 431 Entry = Entry->ForwardLink; 432 Seq = Seg->End; 433 Tcb->RcvNxt = Seq; 434 435 RemoveEntryList (&Nbuf->List); 436 437 // 438 // RFC793 Eighth step: process FIN in sequence 439 // 440 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) { 441 442 // 443 // The peer sends to us junky data after FIN, 444 // reset the connection. 445 // 446 if (!IsListEmpty (&Tcb->RcvQue)) { 447 DEBUG ( 448 (EFI_D_ERROR, 449 "TcpDeliverData: data received after FIN from peer of TCB %p, reset connection\n", 450 Tcb) 451 ); 452 453 NetbufFree (Nbuf); 454 return -1; 455 } 456 457 DEBUG ( 458 (EFI_D_INFO, 459 "TcpDeliverData: processing FIN from peer of TCB %p\n", 460 Tcb) 461 ); 462 463 switch (Tcb->State) { 464 case TCP_SYN_RCVD: 465 case TCP_ESTABLISHED: 466 467 TcpSetState (Tcb, TCP_CLOSE_WAIT); 468 break; 469 470 case TCP_FIN_WAIT_1: 471 472 if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) { 473 474 TcpSetState (Tcb, TCP_CLOSING); 475 break; 476 } 477 478 // 479 // fall through 480 // 481 case TCP_FIN_WAIT_2: 482 483 TcpSetState (Tcb, TCP_TIME_WAIT); 484 TcpClearAllTimer (Tcb); 485 486 if (Tcb->TimeWaitTimeout != 0) { 487 488 TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout); 489 } else { 490 491 DEBUG ( 492 (EFI_D_WARN, 493 "Connection closed immediately because app disables TIME_WAIT timer for %p\n", 494 Tcb) 495 ); 496 497 TcpSendAck (Tcb); 498 TcpClose (Tcb); 499 } 500 break; 501 502 case TCP_CLOSE_WAIT: 503 case TCP_CLOSING: 504 case TCP_LAST_ACK: 505 case TCP_TIME_WAIT: 506 // 507 // The peer sends to us junk FIN byte. Discard 508 // the buffer then reset the connection 509 // 510 NetbufFree (Nbuf); 511 return -1; 512 break; 513 default: 514 break; 515 } 516 517 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW); 518 519 Seg->End--; 520 } 521 522 // 523 // Don't delay the ack if PUSH flag is on. 524 // 525 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_PSH)) { 526 527 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW); 528 } 529 530 if (Nbuf->TotalSize != 0) { 531 Urgent = 0; 532 533 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG) && 534 TCP_SEQ_LEQ (Seg->Seq, Tcb->RcvUp)) 535 { 536 537 if (TCP_SEQ_LEQ (Seg->End, Tcb->RcvUp)) { 538 Urgent = Nbuf->TotalSize; 539 } else { 540 Urgent = TCP_SUB_SEQ (Tcb->RcvUp, Seg->Seq) + 1; 541 } 542 } 543 544 SockDataRcvd (Tcb->Sk, Nbuf, Urgent); 545 } 546 547 if (TCP_FIN_RCVD (Tcb->State)) { 548 549 SockNoMoreData (Tcb->Sk); 550 } 551 552 NetbufFree (Nbuf); 553 } 554 555 return 0; 556 } 557 558 /** 559 Store the data into the reassemble queue. 560 561 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance. 562 @param[in] Nbuf Pointer to the buffer containing the data to be queued. 563 564 **/ 565 VOID 566 TcpQueueData ( 567 IN OUT TCP_CB *Tcb, 568 IN NET_BUF *Nbuf 569 ) 570 { 571 TCP_SEG *Seg; 572 LIST_ENTRY *Head; 573 LIST_ENTRY *Prev; 574 LIST_ENTRY *Cur; 575 NET_BUF *Node; 576 577 ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL)); 578 579 NET_GET_REF (Nbuf); 580 581 Seg = TCPSEG_NETBUF (Nbuf); 582 Head = &Tcb->RcvQue; 583 584 // 585 // Fast path to process normal case. That is, 586 // no out-of-order segments are received. 587 // 588 if (IsListEmpty (Head)) { 589 590 InsertTailList (Head, &Nbuf->List); 591 return; 592 } 593 594 // 595 // Find the point to insert the buffer 596 // 597 for (Prev = Head, Cur = Head->ForwardLink; 598 Cur != Head; 599 Prev = Cur, Cur = Cur->ForwardLink) { 600 601 Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List); 602 603 if (TCP_SEQ_LT (Seg->Seq, TCPSEG_NETBUF (Node)->Seq)) { 604 break; 605 } 606 } 607 608 // 609 // Check whether the current segment overlaps with the 610 // previous segment. 611 // 612 if (Prev != Head) { 613 Node = NET_LIST_USER_STRUCT (Prev, NET_BUF, List); 614 615 if (TCP_SEQ_LT (Seg->Seq, TCPSEG_NETBUF (Node)->End)) { 616 617 if (TCP_SEQ_LEQ (Seg->End, TCPSEG_NETBUF (Node)->End)) { 618 619 NetbufFree (Nbuf); 620 return; 621 } 622 623 TcpTrimSegment (Nbuf, TCPSEG_NETBUF (Node)->End, Seg->End); 624 } 625 } 626 627 InsertHeadList (Prev, &Nbuf->List); 628 629 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW); 630 631 // 632 // Check the segments after the insert point. 633 // 634 while (Cur != Head) { 635 Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List); 636 637 if (TCP_SEQ_LEQ (TCPSEG_NETBUF (Node)->End, Seg->End)) { 638 639 Cur = Cur->ForwardLink; 640 641 RemoveEntryList (&Node->List); 642 NetbufFree (Node); 643 continue; 644 } 645 646 if (TCP_SEQ_LT (TCPSEG_NETBUF (Node)->Seq, Seg->End)) { 647 648 if (TCP_SEQ_LEQ (TCPSEG_NETBUF (Node)->Seq, Seg->Seq)) { 649 650 RemoveEntryList (&Nbuf->List); 651 NetbufFree (Nbuf); 652 return; 653 } 654 655 TcpTrimSegment (Nbuf, Seg->Seq, TCPSEG_NETBUF (Node)->Seq); 656 break; 657 } 658 659 Cur = Cur->ForwardLink; 660 } 661 } 662 663 664 /** 665 Adjust the send queue or the retransmit queue. 666 667 @param[in] Tcb Pointer to the TCP_CB of this TCP instance. 668 @param[in] Ack The acknowledge seuqence number of the received segment. 669 670 **/ 671 VOID 672 TcpAdjustSndQue ( 673 IN TCP_CB *Tcb, 674 IN TCP_SEQNO Ack 675 ) 676 { 677 LIST_ENTRY *Head; 678 LIST_ENTRY *Cur; 679 NET_BUF *Node; 680 TCP_SEG *Seg; 681 682 Head = &Tcb->SndQue; 683 Cur = Head->ForwardLink; 684 685 while (Cur != Head) { 686 Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List); 687 Seg = TCPSEG_NETBUF (Node); 688 689 if (TCP_SEQ_GEQ (Seg->Seq, Ack)) { 690 break; 691 } 692 693 // 694 // Remove completely ACKed segments 695 // 696 if (TCP_SEQ_LEQ (Seg->End, Ack)) { 697 Cur = Cur->ForwardLink; 698 699 RemoveEntryList (&Node->List); 700 NetbufFree (Node); 701 continue; 702 } 703 704 TcpTrimSegment (Node, Ack, Seg->End); 705 break; 706 } 707 } 708 709 /** 710 Process the received TCP segments. 711 712 @param[in] Nbuf Buffer that contains received a TCP segment without an IP header. 713 @param[in] Src Source address of the segment, or the peer's IP address. 714 @param[in] Dst Destination address of the segment, or the local end's IP 715 address. 716 @param[in] Version IP_VERSION_4 indicates IP4 stack. IP_VERSION_6 indicates 717 IP6 stack. 718 719 @retval 0 Segment processed successfully. It is either accepted or 720 discarded. However, no connection is reset by the segment. 721 @retval -1 A connection is reset by the segment. 722 723 **/ 724 INTN 725 TcpInput ( 726 IN NET_BUF *Nbuf, 727 IN EFI_IP_ADDRESS *Src, 728 IN EFI_IP_ADDRESS *Dst, 729 IN UINT8 Version 730 ) 731 { 732 TCP_CB *Tcb; 733 TCP_CB *Parent; 734 TCP_OPTION Option; 735 TCP_HEAD *Head; 736 INT32 Len; 737 TCP_SEG *Seg; 738 TCP_SEQNO Right; 739 TCP_SEQNO Urg; 740 UINT16 Checksum; 741 742 ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6)); 743 744 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE); 745 746 Parent = NULL; 747 Tcb = NULL; 748 749 Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL); 750 ASSERT (Head != NULL); 751 Len = Nbuf->TotalSize - (Head->HeadLen << 2); 752 753 if ((Head->HeadLen < 5) || (Len < 0)) { 754 755 DEBUG ((EFI_D_INFO, "TcpInput: received a malformed packet\n")); 756 goto DISCARD; 757 } 758 759 if (Version == IP_VERSION_4) { 760 Checksum = NetPseudoHeadChecksum (Src->Addr[0], Dst->Addr[0], 6, 0); 761 } else { 762 Checksum = NetIp6PseudoHeadChecksum (&Src->v6, &Dst->v6, 6, 0); 763 } 764 765 Checksum = TcpChecksum (Nbuf, Checksum); 766 767 if (Checksum != 0) { 768 DEBUG ((EFI_D_ERROR, "TcpInput: received a checksum error packet\n")); 769 goto DISCARD; 770 } 771 772 if (TCP_FLG_ON (Head->Flag, TCP_FLG_SYN)) { 773 Len++; 774 } 775 776 if (TCP_FLG_ON (Head->Flag, TCP_FLG_FIN)) { 777 Len++; 778 } 779 780 Tcb = TcpLocateTcb ( 781 Head->DstPort, 782 Dst, 783 Head->SrcPort, 784 Src, 785 Version, 786 (BOOLEAN) TCP_FLG_ON (Head->Flag, TCP_FLG_SYN) 787 ); 788 789 if ((Tcb == NULL) || (Tcb->State == TCP_CLOSED)) { 790 DEBUG ((EFI_D_INFO, "TcpInput: send reset because no TCB found\n")); 791 792 Tcb = NULL; 793 goto SEND_RESET; 794 } 795 796 Seg = TcpFormatNetbuf (Tcb, Nbuf); 797 798 // 799 // RFC1122 recommended reaction to illegal option 800 // (in fact, an illegal option length) is reset. 801 // 802 if (TcpParseOption (Nbuf->Tcp, &Option) == -1) { 803 DEBUG ( 804 (EFI_D_ERROR, 805 "TcpInput: reset the peer because of malformed option for TCB %p\n", 806 Tcb) 807 ); 808 809 goto SEND_RESET; 810 } 811 812 // 813 // From now on, the segment is headless 814 // 815 NetbufTrim (Nbuf, (Head->HeadLen << 2), NET_BUF_HEAD); 816 Nbuf->Tcp = NULL; 817 818 // 819 // Process the segment in LISTEN state. 820 // 821 if (Tcb->State == TCP_LISTEN) { 822 // 823 // First step: Check RST 824 // 825 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) { 826 DEBUG ( 827 (EFI_D_WARN, 828 "TcpInput: discard a reset segment for TCB %p in listening\n", 829 Tcb) 830 ); 831 832 goto DISCARD; 833 } 834 835 // 836 // Second step: Check ACK. 837 // Any ACK sent to TCP in LISTEN is reseted. 838 // 839 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) { 840 DEBUG ( 841 (EFI_D_WARN, 842 "TcpInput: send reset because of segment with ACK for TCB %p in listening\n", 843 Tcb) 844 ); 845 846 goto SEND_RESET; 847 } 848 849 // 850 // Third step: Check SYN 851 // 852 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) { 853 // 854 // create a child TCB to handle the data 855 // 856 Parent = Tcb; 857 858 Tcb = TcpCloneTcb (Parent); 859 if (Tcb == NULL) { 860 DEBUG ( 861 (EFI_D_ERROR, 862 "TcpInput: discard a segment because failed to clone a child for TCB %p\n", 863 Tcb) 864 ); 865 866 goto DISCARD; 867 } 868 869 DEBUG ( 870 (EFI_D_INFO, 871 "TcpInput: create a child for TCB %p in listening\n", 872 Tcb) 873 ); 874 875 // 876 // init the TCB structure 877 // 878 IP6_COPY_ADDRESS (&Tcb->LocalEnd.Ip, Dst); 879 IP6_COPY_ADDRESS (&Tcb->RemoteEnd.Ip, Src); 880 Tcb->LocalEnd.Port = Head->DstPort; 881 Tcb->RemoteEnd.Port = Head->SrcPort; 882 883 TcpInitTcbLocal (Tcb); 884 TcpInitTcbPeer (Tcb, Seg, &Option); 885 886 TcpSetState (Tcb, TCP_SYN_RCVD); 887 TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout); 888 TcpTrimInWnd (Tcb, Nbuf); 889 890 goto StepSix; 891 } 892 893 goto DISCARD; 894 895 } else if (Tcb->State == TCP_SYN_SENT) { 896 // 897 // First step: Check ACK bit 898 // 899 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK) && (Seg->Ack != Tcb->Iss + 1)) { 900 901 DEBUG ( 902 (EFI_D_WARN, 903 "TcpInput: send reset because of wrong ACK received for TCB %p in SYN_SENT\n", 904 Tcb) 905 ); 906 907 goto SEND_RESET; 908 } 909 910 // 911 // Second step: Check RST bit 912 // 913 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) { 914 915 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) { 916 917 DEBUG ( 918 (EFI_D_WARN, 919 "TcpInput: connection reset by peer for TCB %p in SYN_SENT\n", 920 Tcb) 921 ); 922 923 SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET); 924 goto DROP_CONNECTION; 925 } else { 926 927 DEBUG ( 928 (EFI_D_WARN, 929 "TcpInput: discard a reset segment because of no ACK for TCB %p in SYN_SENT\n", 930 Tcb) 931 ); 932 933 goto DISCARD; 934 } 935 } 936 937 // 938 // Third step: Check security and precedence. Skipped 939 // 940 941 // 942 // Fourth step: Check SYN. Pay attention to simultaneous open 943 // 944 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) { 945 946 TcpInitTcbPeer (Tcb, Seg, &Option); 947 948 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) { 949 950 Tcb->SndUna = Seg->Ack; 951 } 952 953 TcpClearTimer (Tcb, TCP_TIMER_REXMIT); 954 955 if (TCP_SEQ_GT (Tcb->SndUna, Tcb->Iss)) { 956 957 TcpSetState (Tcb, TCP_ESTABLISHED); 958 959 TcpClearTimer (Tcb, TCP_TIMER_CONNECT); 960 TcpDeliverData (Tcb); 961 962 if ((Tcb->CongestState == TCP_CONGEST_OPEN) && 963 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) 964 { 965 966 TcpComputeRtt (Tcb, Tcb->RttMeasure); 967 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON); 968 } 969 970 TcpTrimInWnd (Tcb, Nbuf); 971 972 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW); 973 974 DEBUG ( 975 (EFI_D_INFO, 976 "TcpInput: connection established for TCB %p in SYN_SENT\n", 977 Tcb) 978 ); 979 980 goto StepSix; 981 } else { 982 // 983 // Received a SYN segment without ACK, simultanous open. 984 // 985 TcpSetState (Tcb, TCP_SYN_RCVD); 986 987 ASSERT (Tcb->SndNxt == Tcb->Iss + 1); 988 TcpAdjustSndQue (Tcb, Tcb->SndNxt); 989 990 TcpTrimInWnd (Tcb, Nbuf); 991 992 DEBUG ( 993 (EFI_D_WARN, 994 "TcpInput: simultaneous open for TCB %p in SYN_SENT\n", 995 Tcb) 996 ); 997 998 goto StepSix; 999 } 1000 } 1001 1002 goto DISCARD; 1003 } 1004 1005 // 1006 // Process segment in SYN_RCVD or TCP_CONNECTED states 1007 // 1008 1009 // 1010 // Clear probe timer since the RecvWindow is opened. 1011 // 1012 if (Tcb->ProbeTimerOn && (Seg->Wnd != 0)) { 1013 TcpClearTimer (Tcb, TCP_TIMER_PROBE); 1014 Tcb->ProbeTimerOn = FALSE; 1015 } 1016 1017 // 1018 // First step: Check whether SEG.SEQ is acceptable 1019 // 1020 if (TcpSeqAcceptable (Tcb, Seg) == 0) { 1021 DEBUG ( 1022 (EFI_D_WARN, 1023 "TcpInput: sequence acceptance test failed for segment of TCB %p\n", 1024 Tcb) 1025 ); 1026 1027 if (!TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) { 1028 TcpSendAck (Tcb); 1029 } 1030 1031 goto DISCARD; 1032 } 1033 1034 if ((TCP_SEQ_LT (Seg->Seq, Tcb->RcvWl2)) && 1035 (Tcb->RcvWl2 == Seg->End) && 1036 !TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN | TCP_FLG_FIN)) 1037 { 1038 1039 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW); 1040 } 1041 1042 // 1043 // Second step: Check the RST 1044 // 1045 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) { 1046 1047 DEBUG ((EFI_D_WARN, "TcpInput: connection reset for TCB %p\n", Tcb)); 1048 1049 if (Tcb->State == TCP_SYN_RCVD) { 1050 1051 SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_REFUSED); 1052 1053 // 1054 // This TCB comes from either a LISTEN TCB, 1055 // or active open TCB with simultanous open. 1056 // Do NOT signal user CONNECTION refused 1057 // if it comes from a LISTEN TCB. 1058 // 1059 } else if ((Tcb->State == TCP_ESTABLISHED) || 1060 (Tcb->State == TCP_FIN_WAIT_1) || 1061 (Tcb->State == TCP_FIN_WAIT_2) || 1062 (Tcb->State == TCP_CLOSE_WAIT)) 1063 { 1064 1065 SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET); 1066 1067 } else { 1068 } 1069 1070 goto DROP_CONNECTION; 1071 } 1072 1073 // 1074 // Trim the data and flags. 1075 // 1076 TcpTrimInWnd (Tcb, Nbuf); 1077 1078 // 1079 // Third step: Check security and precedence, Ignored 1080 // 1081 1082 // 1083 // Fourth step: Check the SYN bit. 1084 // 1085 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) { 1086 1087 DEBUG ( 1088 (EFI_D_WARN, 1089 "TcpInput: connection reset because received extra SYN for TCB %p\n", 1090 Tcb) 1091 ); 1092 1093 SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET); 1094 goto RESET_THEN_DROP; 1095 } 1096 // 1097 // Fifth step: Check the ACK 1098 // 1099 if (!TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) { 1100 DEBUG ( 1101 (EFI_D_WARN, 1102 "TcpInput: segment discard because of no ACK for connected TCB %p\n", 1103 Tcb) 1104 ); 1105 1106 goto DISCARD; 1107 } else { 1108 if (Tcb->IpInfo->IpVersion == IP_VERSION_6 && Tcb->Tick == 0) { 1109 Tcp6RefreshNeighbor (Tcb, Src, TCP6_KEEP_NEIGHBOR_TIME * TICKS_PER_SECOND); 1110 Tcb->Tick = TCP6_REFRESH_NEIGHBOR_TICK; 1111 } 1112 } 1113 1114 if (Tcb->State == TCP_SYN_RCVD) { 1115 1116 if (TCP_SEQ_LT (Tcb->SndUna, Seg->Ack) && 1117 TCP_SEQ_LEQ (Seg->Ack, Tcb->SndNxt)) 1118 { 1119 1120 Tcb->SndWnd = Seg->Wnd; 1121 Tcb->SndWndMax = MAX (Tcb->SndWnd, Tcb->SndWndMax); 1122 Tcb->SndWl1 = Seg->Seq; 1123 Tcb->SndWl2 = Seg->Ack; 1124 TcpSetState (Tcb, TCP_ESTABLISHED); 1125 1126 TcpClearTimer (Tcb, TCP_TIMER_CONNECT); 1127 TcpDeliverData (Tcb); 1128 1129 DEBUG ( 1130 (EFI_D_INFO, 1131 "TcpInput: connection established for TCB %p in SYN_RCVD\n", 1132 Tcb) 1133 ); 1134 1135 // 1136 // Continue the process as ESTABLISHED state 1137 // 1138 } else { 1139 DEBUG ( 1140 (EFI_D_WARN, 1141 "TcpInput: send reset because of wrong ACK for TCB %p in SYN_RCVD\n", 1142 Tcb) 1143 ); 1144 1145 goto SEND_RESET; 1146 } 1147 } 1148 1149 if (TCP_SEQ_LT (Seg->Ack, Tcb->SndUna)) { 1150 1151 DEBUG ( 1152 (EFI_D_WARN, 1153 "TcpInput: ignore the out-of-data ACK for connected TCB %p\n", 1154 Tcb) 1155 ); 1156 1157 goto StepSix; 1158 1159 } else if (TCP_SEQ_GT (Seg->Ack, Tcb->SndNxt)) { 1160 1161 DEBUG ( 1162 (EFI_D_WARN, 1163 "TcpInput: discard segment for future ACK for connected TCB %p\n", 1164 Tcb) 1165 ); 1166 1167 TcpSendAck (Tcb); 1168 goto DISCARD; 1169 } 1170 1171 // 1172 // From now on: SND.UNA <= SEG.ACK <= SND.NXT. 1173 // 1174 if (TCP_FLG_ON (Option.Flag, TCP_OPTION_RCVD_TS)) { 1175 // 1176 // update TsRecent as specified in page 16 RFC1323. 1177 // RcvWl2 equals to the variable "LastAckSent" 1178 // defined there. 1179 // 1180 if (TCP_SEQ_LEQ (Seg->Seq, Tcb->RcvWl2) && 1181 TCP_SEQ_LT (Tcb->RcvWl2, Seg->End)) 1182 { 1183 1184 Tcb->TsRecent = Option.TSVal; 1185 Tcb->TsRecentAge = mTcpTick; 1186 } 1187 1188 TcpComputeRtt (Tcb, TCP_SUB_TIME (mTcpTick, Option.TSEcr)); 1189 1190 } else if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) { 1191 1192 ASSERT (Tcb->CongestState == TCP_CONGEST_OPEN); 1193 1194 TcpComputeRtt (Tcb, Tcb->RttMeasure); 1195 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON); 1196 } 1197 1198 if (Seg->Ack == Tcb->SndNxt) { 1199 1200 TcpClearTimer (Tcb, TCP_TIMER_REXMIT); 1201 } else { 1202 1203 TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto); 1204 } 1205 1206 // 1207 // Count duplicate acks. 1208 // 1209 if ((Seg->Ack == Tcb->SndUna) && 1210 (Tcb->SndUna != Tcb->SndNxt) && 1211 (Seg->Wnd == Tcb->SndWnd) && 1212 (0 == Len)) 1213 { 1214 1215 Tcb->DupAck++; 1216 } else { 1217 1218 Tcb->DupAck = 0; 1219 } 1220 1221 // 1222 // Congestion avoidance, fast recovery and fast retransmission. 1223 // 1224 if (((Tcb->CongestState == TCP_CONGEST_OPEN) && (Tcb->DupAck < 3)) || 1225 (Tcb->CongestState == TCP_CONGEST_LOSS)) 1226 { 1227 1228 if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) { 1229 1230 if (Tcb->CWnd < Tcb->Ssthresh) { 1231 1232 Tcb->CWnd += Tcb->SndMss; 1233 } else { 1234 1235 Tcb->CWnd += MAX (Tcb->SndMss * Tcb->SndMss / Tcb->CWnd, 1); 1236 } 1237 1238 Tcb->CWnd = MIN (Tcb->CWnd, TCP_MAX_WIN << Tcb->SndWndScale); 1239 } 1240 1241 if (Tcb->CongestState == TCP_CONGEST_LOSS) { 1242 TcpFastLossRecover (Tcb, Seg); 1243 } 1244 } else { 1245 1246 TcpFastRecover (Tcb, Seg); 1247 } 1248 1249 if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) { 1250 1251 TcpAdjustSndQue (Tcb, Seg->Ack); 1252 Tcb->SndUna = Seg->Ack; 1253 1254 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_URG) && 1255 TCP_SEQ_LT (Tcb->SndUp, Seg->Ack)) 1256 { 1257 1258 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG); 1259 } 1260 } 1261 1262 // 1263 // Update window info 1264 // 1265 if (TCP_SEQ_LT (Tcb->SndWl1, Seg->Seq) || 1266 ((Tcb->SndWl1 == Seg->Seq) && TCP_SEQ_LEQ (Tcb->SndWl2, Seg->Ack))) 1267 { 1268 1269 Right = Seg->Ack + Seg->Wnd; 1270 1271 if (TCP_SEQ_LT (Right, Tcb->SndWl2 + Tcb->SndWnd)) { 1272 1273 if ((Tcb->SndWl1 == Seg->Seq) && 1274 (Tcb->SndWl2 == Seg->Ack) && 1275 (Len == 0)) 1276 { 1277 1278 goto NO_UPDATE; 1279 } 1280 1281 DEBUG ( 1282 (EFI_D_WARN, 1283 "TcpInput: peer shrinks the window for connected TCB %p\n", 1284 Tcb) 1285 ); 1286 1287 if ((Tcb->CongestState == TCP_CONGEST_RECOVER) && 1288 (TCP_SEQ_LT (Right, Tcb->Recover))) 1289 { 1290 1291 Tcb->Recover = Right; 1292 } 1293 1294 if ((Tcb->CongestState == TCP_CONGEST_LOSS) && 1295 (TCP_SEQ_LT (Right, Tcb->LossRecover))) 1296 { 1297 1298 Tcb->LossRecover = Right; 1299 } 1300 1301 if (TCP_SEQ_LT (Right, Tcb->SndNxt)) { 1302 1303 Tcb->SndNxt = Right; 1304 1305 if (Right == Tcb->SndUna) { 1306 1307 TcpClearTimer (Tcb, TCP_TIMER_REXMIT); 1308 TcpSetProbeTimer (Tcb); 1309 } 1310 } 1311 } 1312 1313 Tcb->SndWnd = Seg->Wnd; 1314 Tcb->SndWndMax = MAX (Tcb->SndWnd, Tcb->SndWndMax); 1315 Tcb->SndWl1 = Seg->Seq; 1316 Tcb->SndWl2 = Seg->Ack; 1317 } 1318 1319 NO_UPDATE: 1320 1321 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT) && 1322 (Tcb->SndUna == Tcb->SndNxt)) 1323 { 1324 1325 DEBUG ( 1326 (EFI_D_INFO, 1327 "TcpInput: local FIN is ACKed by peer for connected TCB %p\n", 1328 Tcb) 1329 ); 1330 1331 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED); 1332 } 1333 1334 // 1335 // Transit the state if proper. 1336 // 1337 switch (Tcb->State) { 1338 case TCP_FIN_WAIT_1: 1339 1340 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) { 1341 1342 TcpSetState (Tcb, TCP_FIN_WAIT_2); 1343 1344 TcpClearAllTimer (Tcb); 1345 TcpSetTimer (Tcb, TCP_TIMER_FINWAIT2, Tcb->FinWait2Timeout); 1346 } 1347 1348 case TCP_FIN_WAIT_2: 1349 1350 break; 1351 1352 case TCP_CLOSE_WAIT: 1353 break; 1354 1355 case TCP_CLOSING: 1356 1357 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) { 1358 1359 TcpSetState (Tcb, TCP_TIME_WAIT); 1360 1361 TcpClearAllTimer (Tcb); 1362 1363 if (Tcb->TimeWaitTimeout != 0) { 1364 1365 TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout); 1366 } else { 1367 1368 DEBUG ( 1369 (EFI_D_WARN, 1370 "Connection closed immediately because app disables TIME_WAIT timer for %p\n", 1371 Tcb) 1372 ); 1373 1374 TcpClose (Tcb); 1375 } 1376 } 1377 break; 1378 1379 case TCP_LAST_ACK: 1380 1381 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) { 1382 1383 TcpSetState (Tcb, TCP_CLOSED); 1384 } 1385 1386 break; 1387 1388 case TCP_TIME_WAIT: 1389 1390 TcpSendAck (Tcb); 1391 1392 if (Tcb->TimeWaitTimeout != 0) { 1393 1394 TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout); 1395 } else { 1396 1397 DEBUG ( 1398 (EFI_D_WARN, 1399 "Connection closed immediately because app disables TIME_WAIT timer for %p\n", 1400 Tcb) 1401 ); 1402 1403 TcpClose (Tcb); 1404 } 1405 break; 1406 1407 default: 1408 break; 1409 } 1410 // 1411 // Sixth step: Check the URG bit.update the Urg point 1412 // if in TCP_CAN_RECV, otherwise, leave the RcvUp intact. 1413 // 1414 StepSix: 1415 1416 Tcb->Idle = 0; 1417 TcpSetKeepaliveTimer (Tcb); 1418 1419 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_URG) && !TCP_FIN_RCVD (Tcb->State)) { 1420 1421 DEBUG ( 1422 (EFI_D_INFO, 1423 "TcpInput: received urgent data from peer for connected TCB %p\n", 1424 Tcb) 1425 ); 1426 1427 Urg = Seg->Seq + Seg->Urg; 1428 1429 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG) && 1430 TCP_SEQ_GT (Urg, Tcb->RcvUp)) 1431 { 1432 1433 Tcb->RcvUp = Urg; 1434 } else { 1435 1436 Tcb->RcvUp = Urg; 1437 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG); 1438 } 1439 } 1440 // 1441 // Seventh step: Process the segment data 1442 // 1443 if (Seg->End != Seg->Seq) { 1444 1445 if (TCP_FIN_RCVD (Tcb->State)) { 1446 1447 DEBUG ( 1448 (EFI_D_WARN, 1449 "TcpInput: connection reset because data is lost for connected TCB %p\n", 1450 Tcb) 1451 ); 1452 1453 goto RESET_THEN_DROP; 1454 } 1455 1456 if (TCP_LOCAL_CLOSED (Tcb->State) && (Nbuf->TotalSize != 0)) { 1457 DEBUG ( 1458 (EFI_D_WARN, 1459 "TcpInput: connection reset because data is lost for connected TCB %p\n", 1460 Tcb) 1461 ); 1462 1463 goto RESET_THEN_DROP; 1464 } 1465 1466 TcpQueueData (Tcb, Nbuf); 1467 if (TcpDeliverData (Tcb) == -1) { 1468 goto RESET_THEN_DROP; 1469 } 1470 1471 if (!IsListEmpty (&Tcb->RcvQue)) { 1472 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW); 1473 } 1474 } 1475 1476 // 1477 // Eighth step: check the FIN. 1478 // This step is moved to TcpDeliverData. FIN will be 1479 // processed in sequence there. Check the comments in 1480 // the beginning of the file header for information. 1481 // 1482 1483 // 1484 // Tcb is a new child of the listening Parent, 1485 // commit it. 1486 // 1487 if (Parent != NULL) { 1488 Tcb->Parent = Parent; 1489 TcpInsertTcb (Tcb); 1490 } 1491 1492 if ((Tcb->State != TCP_CLOSED) && 1493 (TcpToSendData (Tcb, 0) == 0) && 1494 (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW) || (Nbuf->TotalSize != 0))) 1495 { 1496 1497 TcpToSendAck (Tcb); 1498 } 1499 1500 NetbufFree (Nbuf); 1501 return 0; 1502 1503 RESET_THEN_DROP: 1504 TcpSendReset (Tcb, Head, Len, Dst, Src, Version); 1505 1506 DROP_CONNECTION: 1507 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL)); 1508 1509 NetbufFree (Nbuf); 1510 TcpClose (Tcb); 1511 1512 return -1; 1513 1514 SEND_RESET: 1515 1516 TcpSendReset (Tcb, Head, Len, Dst, Src, Version); 1517 1518 DISCARD: 1519 1520 // 1521 // Tcb is a child of Parent, and it doesn't survive 1522 // 1523 DEBUG ((EFI_D_WARN, "TcpInput: Discard a packet\n")); 1524 NetbufFree (Nbuf); 1525 1526 if ((Parent != NULL) && (Tcb != NULL)) { 1527 1528 ASSERT (Tcb->Sk != NULL); 1529 TcpClose (Tcb); 1530 } 1531 1532 return 0; 1533 } 1534 1535 /** 1536 Process the received ICMP error messages for TCP. 1537 1538 @param[in] Nbuf The buffer that contains part of the TCP segment without an IP header 1539 truncated from the ICMP error packet. 1540 @param[in] IcmpErr The ICMP error code interpreted from an ICMP error packet. 1541 @param[in] Src Source address of the ICMP error message. 1542 @param[in] Dst Destination address of the ICMP error message. 1543 @param[in] Version IP_VERSION_4 indicates IP4 stack. IP_VERSION_6 indicates 1544 IP6 stack. 1545 1546 **/ 1547 VOID 1548 TcpIcmpInput ( 1549 IN NET_BUF *Nbuf, 1550 IN UINT8 IcmpErr, 1551 IN EFI_IP_ADDRESS *Src, 1552 IN EFI_IP_ADDRESS *Dst, 1553 IN UINT8 Version 1554 ) 1555 { 1556 TCP_HEAD *Head; 1557 TCP_CB *Tcb; 1558 TCP_SEQNO Seq; 1559 EFI_STATUS IcmpErrStatus; 1560 BOOLEAN IcmpErrIsHard; 1561 BOOLEAN IcmpErrNotify; 1562 1563 Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL); 1564 ASSERT (Head != NULL); 1565 1566 Tcb = TcpLocateTcb ( 1567 Head->DstPort, 1568 Dst, 1569 Head->SrcPort, 1570 Src, 1571 Version, 1572 FALSE 1573 ); 1574 if (Tcb == NULL || Tcb->State == TCP_CLOSED) { 1575 1576 goto CLEAN_EXIT; 1577 } 1578 1579 // 1580 // Validate the sequence number. 1581 // 1582 Seq = NTOHL (Head->Seq); 1583 if (!(TCP_SEQ_LEQ (Tcb->SndUna, Seq) && TCP_SEQ_LT (Seq, Tcb->SndNxt))) { 1584 1585 goto CLEAN_EXIT; 1586 } 1587 1588 IcmpErrStatus = IpIoGetIcmpErrStatus ( 1589 IcmpErr, 1590 Tcb->Sk->IpVersion, 1591 &IcmpErrIsHard, 1592 &IcmpErrNotify 1593 ); 1594 1595 if (IcmpErrNotify) { 1596 1597 SOCK_ERROR (Tcb->Sk, IcmpErrStatus); 1598 } 1599 1600 if (IcmpErrIsHard) { 1601 1602 TcpClose (Tcb); 1603 } 1604 1605 CLEAN_EXIT: 1606 1607 NetbufFree (Nbuf); 1608 } 1609