]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/TcpDxe/TcpInput.c
NetworkPkg: Add wnd scale check before shrinking window.
[mirror_edk2.git] / NetworkPkg / TcpDxe / TcpInput.c
1 /** @file
2 TCP input process routines.
3
4 Copyright (c) 2009 - 2017, 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->RcvNxt, 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_NET,
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_NET,
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_NET,
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_NET,
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_NET,
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_NET,
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_NET,
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_NET,
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 INT32 Usable;
742
743 ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
744
745 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
746
747 Parent = NULL;
748 Tcb = NULL;
749
750 Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);
751 ASSERT (Head != NULL);
752
753 if (Nbuf->TotalSize < sizeof (TCP_HEAD)) {
754 DEBUG ((EFI_D_NET, "TcpInput: received a malformed packet\n"));
755 goto DISCARD;
756 }
757
758 Len = Nbuf->TotalSize - (Head->HeadLen << 2);
759
760 if ((Head->HeadLen < 5) || (Len < 0)) {
761
762 DEBUG ((EFI_D_NET, "TcpInput: received a malformed packet\n"));
763
764 goto DISCARD;
765 }
766
767 if (Version == IP_VERSION_4) {
768 Checksum = NetPseudoHeadChecksum (Src->Addr[0], Dst->Addr[0], 6, 0);
769 } else {
770 Checksum = NetIp6PseudoHeadChecksum (&Src->v6, &Dst->v6, 6, 0);
771 }
772
773 Checksum = TcpChecksum (Nbuf, Checksum);
774
775 if (Checksum != 0) {
776 DEBUG ((EFI_D_ERROR, "TcpInput: received a checksum error packet\n"));
777 goto DISCARD;
778 }
779
780 if (TCP_FLG_ON (Head->Flag, TCP_FLG_SYN)) {
781 Len++;
782 }
783
784 if (TCP_FLG_ON (Head->Flag, TCP_FLG_FIN)) {
785 Len++;
786 }
787
788 Tcb = TcpLocateTcb (
789 Head->DstPort,
790 Dst,
791 Head->SrcPort,
792 Src,
793 Version,
794 (BOOLEAN) TCP_FLG_ON (Head->Flag, TCP_FLG_SYN)
795 );
796
797 if ((Tcb == NULL) || (Tcb->State == TCP_CLOSED)) {
798 DEBUG ((EFI_D_NET, "TcpInput: send reset because no TCB found\n"));
799
800 Tcb = NULL;
801 goto SEND_RESET;
802 }
803
804 Seg = TcpFormatNetbuf (Tcb, Nbuf);
805
806 //
807 // RFC1122 recommended reaction to illegal option
808 // (in fact, an illegal option length) is reset.
809 //
810 if (TcpParseOption (Nbuf->Tcp, &Option) == -1) {
811 DEBUG (
812 (EFI_D_ERROR,
813 "TcpInput: reset the peer because of malformed option for TCB %p\n",
814 Tcb)
815 );
816
817 goto SEND_RESET;
818 }
819
820 //
821 // From now on, the segment is headless
822 //
823 NetbufTrim (Nbuf, (Head->HeadLen << 2), NET_BUF_HEAD);
824 Nbuf->Tcp = NULL;
825
826 //
827 // Process the segment in LISTEN state.
828 //
829 if (Tcb->State == TCP_LISTEN) {
830 //
831 // First step: Check RST
832 //
833 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
834 DEBUG (
835 (EFI_D_WARN,
836 "TcpInput: discard a reset segment for TCB %p in listening\n",
837 Tcb)
838 );
839
840 goto DISCARD;
841 }
842
843 //
844 // Second step: Check ACK.
845 // Any ACK sent to TCP in LISTEN is reseted.
846 //
847 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
848 DEBUG (
849 (EFI_D_WARN,
850 "TcpInput: send reset because of segment with ACK for TCB %p in listening\n",
851 Tcb)
852 );
853
854 goto SEND_RESET;
855 }
856
857 //
858 // Third step: Check SYN
859 //
860 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
861 //
862 // create a child TCB to handle the data
863 //
864 Parent = Tcb;
865
866 Tcb = TcpCloneTcb (Parent);
867 if (Tcb == NULL) {
868 DEBUG (
869 (EFI_D_ERROR,
870 "TcpInput: discard a segment because failed to clone a child for TCB %p\n",
871 Tcb)
872 );
873
874 goto DISCARD;
875 }
876
877 DEBUG (
878 (EFI_D_NET,
879 "TcpInput: create a child for TCB %p in listening\n",
880 Tcb)
881 );
882
883 //
884 // init the TCB structure
885 //
886 IP6_COPY_ADDRESS (&Tcb->LocalEnd.Ip, Dst);
887 IP6_COPY_ADDRESS (&Tcb->RemoteEnd.Ip, Src);
888 Tcb->LocalEnd.Port = Head->DstPort;
889 Tcb->RemoteEnd.Port = Head->SrcPort;
890
891 TcpInitTcbLocal (Tcb);
892 TcpInitTcbPeer (Tcb, Seg, &Option);
893
894 TcpSetState (Tcb, TCP_SYN_RCVD);
895 TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
896 TcpTrimInWnd (Tcb, Nbuf);
897
898 goto StepSix;
899 }
900
901 goto DISCARD;
902
903 } else if (Tcb->State == TCP_SYN_SENT) {
904 //
905 // First step: Check ACK bit
906 //
907 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK) && (Seg->Ack != Tcb->Iss + 1)) {
908
909 DEBUG (
910 (EFI_D_WARN,
911 "TcpInput: send reset because of wrong ACK received for TCB %p in SYN_SENT\n",
912 Tcb)
913 );
914
915 goto SEND_RESET;
916 }
917
918 //
919 // Second step: Check RST bit
920 //
921 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
922
923 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
924
925 DEBUG (
926 (EFI_D_WARN,
927 "TcpInput: connection reset by peer for TCB %p in SYN_SENT\n",
928 Tcb)
929 );
930
931 SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);
932 goto DROP_CONNECTION;
933 } else {
934
935 DEBUG (
936 (EFI_D_WARN,
937 "TcpInput: discard a reset segment because of no ACK for TCB %p in SYN_SENT\n",
938 Tcb)
939 );
940
941 goto DISCARD;
942 }
943 }
944
945 //
946 // Third step: Check security and precedence. Skipped
947 //
948
949 //
950 // Fourth step: Check SYN. Pay attention to simultaneous open
951 //
952 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
953
954 TcpInitTcbPeer (Tcb, Seg, &Option);
955
956 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
957
958 Tcb->SndUna = Seg->Ack;
959 }
960
961 TcpClearTimer (Tcb, TCP_TIMER_REXMIT);
962
963 if (TCP_SEQ_GT (Tcb->SndUna, Tcb->Iss)) {
964
965 TcpSetState (Tcb, TCP_ESTABLISHED);
966
967 TcpClearTimer (Tcb, TCP_TIMER_CONNECT);
968 TcpDeliverData (Tcb);
969
970 if ((Tcb->CongestState == TCP_CONGEST_OPEN) &&
971 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON))
972 {
973
974 TcpComputeRtt (Tcb, Tcb->RttMeasure);
975 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
976 }
977
978 TcpTrimInWnd (Tcb, Nbuf);
979
980 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
981
982 DEBUG (
983 (EFI_D_NET,
984 "TcpInput: connection established for TCB %p in SYN_SENT\n",
985 Tcb)
986 );
987
988 goto StepSix;
989 } else {
990 //
991 // Received a SYN segment without ACK, simultanous open.
992 //
993 TcpSetState (Tcb, TCP_SYN_RCVD);
994
995 ASSERT (Tcb->SndNxt == Tcb->Iss + 1);
996 TcpAdjustSndQue (Tcb, Tcb->SndNxt);
997
998 TcpTrimInWnd (Tcb, Nbuf);
999
1000 DEBUG (
1001 (EFI_D_WARN,
1002 "TcpInput: simultaneous open for TCB %p in SYN_SENT\n",
1003 Tcb)
1004 );
1005
1006 goto StepSix;
1007 }
1008 }
1009
1010 goto DISCARD;
1011 }
1012
1013 //
1014 // Process segment in SYN_RCVD or TCP_CONNECTED states
1015 //
1016
1017 //
1018 // Clear probe timer since the RecvWindow is opened.
1019 //
1020 if (Tcb->ProbeTimerOn && (Seg->Wnd != 0)) {
1021 TcpClearTimer (Tcb, TCP_TIMER_PROBE);
1022 Tcb->ProbeTimerOn = FALSE;
1023 }
1024
1025 //
1026 // First step: Check whether SEG.SEQ is acceptable
1027 //
1028 if (TcpSeqAcceptable (Tcb, Seg) == 0) {
1029 DEBUG (
1030 (EFI_D_WARN,
1031 "TcpInput: sequence acceptance test failed for segment of TCB %p\n",
1032 Tcb)
1033 );
1034
1035 if (!TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
1036 TcpSendAck (Tcb);
1037 }
1038
1039 goto DISCARD;
1040 }
1041
1042 if ((TCP_SEQ_LT (Seg->Seq, Tcb->RcvWl2)) &&
1043 (Tcb->RcvWl2 == Seg->End) &&
1044 !TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN | TCP_FLG_FIN))
1045 {
1046
1047 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
1048 }
1049
1050 //
1051 // Second step: Check the RST
1052 //
1053 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
1054
1055 DEBUG ((EFI_D_WARN, "TcpInput: connection reset for TCB %p\n", Tcb));
1056
1057 if (Tcb->State == TCP_SYN_RCVD) {
1058
1059 SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_REFUSED);
1060
1061 //
1062 // This TCB comes from either a LISTEN TCB,
1063 // or active open TCB with simultanous open.
1064 // Do NOT signal user CONNECTION refused
1065 // if it comes from a LISTEN TCB.
1066 //
1067 } else if ((Tcb->State == TCP_ESTABLISHED) ||
1068 (Tcb->State == TCP_FIN_WAIT_1) ||
1069 (Tcb->State == TCP_FIN_WAIT_2) ||
1070 (Tcb->State == TCP_CLOSE_WAIT))
1071 {
1072
1073 SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);
1074
1075 } else {
1076 }
1077
1078 goto DROP_CONNECTION;
1079 }
1080
1081 //
1082 // Trim the data and flags.
1083 //
1084 TcpTrimInWnd (Tcb, Nbuf);
1085
1086 //
1087 // Third step: Check security and precedence, Ignored
1088 //
1089
1090 //
1091 // Fourth step: Check the SYN bit.
1092 //
1093 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
1094
1095 DEBUG (
1096 (EFI_D_WARN,
1097 "TcpInput: connection reset because received extra SYN for TCB %p\n",
1098 Tcb)
1099 );
1100
1101 SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);
1102 goto RESET_THEN_DROP;
1103 }
1104 //
1105 // Fifth step: Check the ACK
1106 //
1107 if (!TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
1108 DEBUG (
1109 (EFI_D_WARN,
1110 "TcpInput: segment discard because of no ACK for connected TCB %p\n",
1111 Tcb)
1112 );
1113
1114 goto DISCARD;
1115 } else {
1116 if (Tcb->IpInfo->IpVersion == IP_VERSION_6 && Tcb->Tick == 0) {
1117 Tcp6RefreshNeighbor (Tcb, Src, TCP6_KEEP_NEIGHBOR_TIME * TICKS_PER_SECOND);
1118 Tcb->Tick = TCP6_REFRESH_NEIGHBOR_TICK;
1119 }
1120 }
1121
1122 if (Tcb->State == TCP_SYN_RCVD) {
1123
1124 if (TCP_SEQ_LT (Tcb->SndUna, Seg->Ack) &&
1125 TCP_SEQ_LEQ (Seg->Ack, Tcb->SndNxt))
1126 {
1127
1128 Tcb->SndWnd = Seg->Wnd;
1129 Tcb->SndWndMax = MAX (Tcb->SndWnd, Tcb->SndWndMax);
1130 Tcb->SndWl1 = Seg->Seq;
1131 Tcb->SndWl2 = Seg->Ack;
1132 TcpSetState (Tcb, TCP_ESTABLISHED);
1133
1134 TcpClearTimer (Tcb, TCP_TIMER_CONNECT);
1135 TcpDeliverData (Tcb);
1136
1137 DEBUG (
1138 (EFI_D_NET,
1139 "TcpInput: connection established for TCB %p in SYN_RCVD\n",
1140 Tcb)
1141 );
1142
1143 //
1144 // Continue the process as ESTABLISHED state
1145 //
1146 } else {
1147 DEBUG (
1148 (EFI_D_WARN,
1149 "TcpInput: send reset because of wrong ACK for TCB %p in SYN_RCVD\n",
1150 Tcb)
1151 );
1152
1153 goto SEND_RESET;
1154 }
1155 }
1156
1157 if (TCP_SEQ_LT (Seg->Ack, Tcb->SndUna)) {
1158
1159 DEBUG (
1160 (EFI_D_WARN,
1161 "TcpInput: ignore the out-of-data ACK for connected TCB %p\n",
1162 Tcb)
1163 );
1164
1165 goto StepSix;
1166
1167 } else if (TCP_SEQ_GT (Seg->Ack, Tcb->SndNxt)) {
1168
1169 DEBUG (
1170 (EFI_D_WARN,
1171 "TcpInput: discard segment for future ACK for connected TCB %p\n",
1172 Tcb)
1173 );
1174
1175 TcpSendAck (Tcb);
1176 goto DISCARD;
1177 }
1178
1179 //
1180 // From now on: SND.UNA <= SEG.ACK <= SND.NXT.
1181 //
1182 if (TCP_FLG_ON (Option.Flag, TCP_OPTION_RCVD_TS)) {
1183 //
1184 // update TsRecent as specified in page 16 RFC1323.
1185 // RcvWl2 equals to the variable "LastAckSent"
1186 // defined there.
1187 //
1188 if (TCP_SEQ_LEQ (Seg->Seq, Tcb->RcvWl2) &&
1189 TCP_SEQ_LT (Tcb->RcvWl2, Seg->End))
1190 {
1191
1192 Tcb->TsRecent = Option.TSVal;
1193 Tcb->TsRecentAge = mTcpTick;
1194 }
1195
1196 TcpComputeRtt (Tcb, TCP_SUB_TIME (mTcpTick, Option.TSEcr));
1197
1198 } else if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
1199
1200 ASSERT (Tcb->CongestState == TCP_CONGEST_OPEN);
1201
1202 TcpComputeRtt (Tcb, Tcb->RttMeasure);
1203 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
1204 }
1205
1206 if (Seg->Ack == Tcb->SndNxt) {
1207
1208 TcpClearTimer (Tcb, TCP_TIMER_REXMIT);
1209 } else {
1210
1211 TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
1212 }
1213
1214 //
1215 // Count duplicate acks.
1216 //
1217 if ((Seg->Ack == Tcb->SndUna) &&
1218 (Tcb->SndUna != Tcb->SndNxt) &&
1219 (Seg->Wnd == Tcb->SndWnd) &&
1220 (0 == Len))
1221 {
1222
1223 Tcb->DupAck++;
1224 } else {
1225
1226 Tcb->DupAck = 0;
1227 }
1228
1229 //
1230 // Congestion avoidance, fast recovery and fast retransmission.
1231 //
1232 if (((Tcb->CongestState == TCP_CONGEST_OPEN) && (Tcb->DupAck < 3)) ||
1233 (Tcb->CongestState == TCP_CONGEST_LOSS))
1234 {
1235
1236 if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {
1237
1238 if (Tcb->CWnd < Tcb->Ssthresh) {
1239
1240 Tcb->CWnd += Tcb->SndMss;
1241 } else {
1242
1243 Tcb->CWnd += MAX (Tcb->SndMss * Tcb->SndMss / Tcb->CWnd, 1);
1244 }
1245
1246 Tcb->CWnd = MIN (Tcb->CWnd, TCP_MAX_WIN << Tcb->SndWndScale);
1247 }
1248
1249 if (Tcb->CongestState == TCP_CONGEST_LOSS) {
1250 TcpFastLossRecover (Tcb, Seg);
1251 }
1252 } else {
1253
1254 TcpFastRecover (Tcb, Seg);
1255 }
1256
1257 if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {
1258
1259 TcpAdjustSndQue (Tcb, Seg->Ack);
1260 Tcb->SndUna = Seg->Ack;
1261
1262 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_URG) &&
1263 TCP_SEQ_LT (Tcb->SndUp, Seg->Ack))
1264 {
1265
1266 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
1267 }
1268 }
1269
1270 //
1271 // Update window info
1272 //
1273 if (TCP_SEQ_LT (Tcb->SndWl1, Seg->Seq) ||
1274 ((Tcb->SndWl1 == Seg->Seq) && TCP_SEQ_LEQ (Tcb->SndWl2, Seg->Ack)))
1275 {
1276
1277 Right = Seg->Ack + Seg->Wnd;
1278
1279 if (TCP_SEQ_LT (Right, Tcb->SndWl2 + Tcb->SndWnd)) {
1280
1281 if ((Tcb->SndWl1 == Seg->Seq) &&
1282 (Tcb->SndWl2 == Seg->Ack) &&
1283 (Len == 0))
1284 {
1285
1286 goto NO_UPDATE;
1287 }
1288
1289 DEBUG (
1290 (EFI_D_WARN,
1291 "TcpInput: peer shrinks the window for connected TCB %p\n",
1292 Tcb)
1293 );
1294
1295 if ((Tcb->CongestState == TCP_CONGEST_RECOVER) &&
1296 (TCP_SEQ_LT (Right, Tcb->Recover)))
1297 {
1298
1299 Tcb->Recover = Right;
1300 }
1301
1302 if ((Tcb->CongestState == TCP_CONGEST_LOSS) &&
1303 (TCP_SEQ_LT (Right, Tcb->LossRecover)))
1304 {
1305
1306 Tcb->LossRecover = Right;
1307 }
1308
1309 if (TCP_SEQ_LT (Right, Tcb->SndNxt)) {
1310 //
1311 // Check for Window Retraction in RFC7923 section 2.4.
1312 // The lower n bits of the peer's actual receive window is wiped out if TCP
1313 // window scale is enabled, it will look like the peer is shrinking the window.
1314 // Check whether the SndNxt is out of the advertised receive window by more than
1315 // 2^Rcv.Wind.Shift before moving the SndNxt to the left.
1316 //
1317 DEBUG (
1318 (EFI_D_WARN,
1319 "TcpInput: peer advise negative useable window for connected TCB %p\n",
1320 Tcb)
1321 );
1322 Usable = TCP_SUB_SEQ (Tcb->SndNxt, Right);
1323 if ((Usable >> Tcb->SndWndScale) > 0) {
1324 DEBUG (
1325 (EFI_D_WARN,
1326 "TcpInput: SndNxt is out of window by more than window scale for TCB %p\n",
1327 Tcb)
1328 );
1329 Tcb->SndNxt = Right;
1330 }
1331 if (Right == Tcb->SndUna) {
1332
1333 TcpClearTimer (Tcb, TCP_TIMER_REXMIT);
1334 TcpSetProbeTimer (Tcb);
1335 }
1336 }
1337 }
1338
1339 Tcb->SndWnd = Seg->Wnd;
1340 Tcb->SndWndMax = MAX (Tcb->SndWnd, Tcb->SndWndMax);
1341 Tcb->SndWl1 = Seg->Seq;
1342 Tcb->SndWl2 = Seg->Ack;
1343 }
1344
1345 NO_UPDATE:
1346
1347 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT) &&
1348 (Tcb->SndUna == Tcb->SndNxt))
1349 {
1350
1351 DEBUG (
1352 (EFI_D_NET,
1353 "TcpInput: local FIN is ACKed by peer for connected TCB %p\n",
1354 Tcb)
1355 );
1356
1357 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED);
1358 }
1359
1360 //
1361 // Transit the state if proper.
1362 //
1363 switch (Tcb->State) {
1364 case TCP_FIN_WAIT_1:
1365
1366 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
1367
1368 TcpSetState (Tcb, TCP_FIN_WAIT_2);
1369
1370 TcpClearAllTimer (Tcb);
1371 TcpSetTimer (Tcb, TCP_TIMER_FINWAIT2, Tcb->FinWait2Timeout);
1372 }
1373
1374 case TCP_FIN_WAIT_2:
1375
1376 break;
1377
1378 case TCP_CLOSE_WAIT:
1379 break;
1380
1381 case TCP_CLOSING:
1382
1383 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
1384
1385 TcpSetState (Tcb, TCP_TIME_WAIT);
1386
1387 TcpClearAllTimer (Tcb);
1388
1389 if (Tcb->TimeWaitTimeout != 0) {
1390
1391 TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);
1392 } else {
1393
1394 DEBUG (
1395 (EFI_D_WARN,
1396 "Connection closed immediately because app disables TIME_WAIT timer for %p\n",
1397 Tcb)
1398 );
1399
1400 TcpClose (Tcb);
1401 }
1402 }
1403 break;
1404
1405 case TCP_LAST_ACK:
1406
1407 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
1408
1409 TcpSetState (Tcb, TCP_CLOSED);
1410 }
1411
1412 break;
1413
1414 case TCP_TIME_WAIT:
1415
1416 TcpSendAck (Tcb);
1417
1418 if (Tcb->TimeWaitTimeout != 0) {
1419
1420 TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);
1421 } else {
1422
1423 DEBUG (
1424 (EFI_D_WARN,
1425 "Connection closed immediately because app disables TIME_WAIT timer for %p\n",
1426 Tcb)
1427 );
1428
1429 TcpClose (Tcb);
1430 }
1431 break;
1432
1433 default:
1434 break;
1435 }
1436 //
1437 // Sixth step: Check the URG bit.update the Urg point
1438 // if in TCP_CAN_RECV, otherwise, leave the RcvUp intact.
1439 //
1440 StepSix:
1441
1442 Tcb->Idle = 0;
1443 TcpSetKeepaliveTimer (Tcb);
1444
1445 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_URG) && !TCP_FIN_RCVD (Tcb->State)) {
1446
1447 DEBUG (
1448 (EFI_D_NET,
1449 "TcpInput: received urgent data from peer for connected TCB %p\n",
1450 Tcb)
1451 );
1452
1453 Urg = Seg->Seq + Seg->Urg;
1454
1455 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG) &&
1456 TCP_SEQ_GT (Urg, Tcb->RcvUp))
1457 {
1458
1459 Tcb->RcvUp = Urg;
1460 } else {
1461
1462 Tcb->RcvUp = Urg;
1463 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG);
1464 }
1465 }
1466 //
1467 // Seventh step: Process the segment data
1468 //
1469 if (Seg->End != Seg->Seq) {
1470
1471 if (TCP_FIN_RCVD (Tcb->State)) {
1472
1473 DEBUG (
1474 (EFI_D_WARN,
1475 "TcpInput: connection reset because data is lost for connected TCB %p\n",
1476 Tcb)
1477 );
1478
1479 goto RESET_THEN_DROP;
1480 }
1481
1482 if (TCP_LOCAL_CLOSED (Tcb->State) && (Nbuf->TotalSize != 0)) {
1483 DEBUG (
1484 (EFI_D_WARN,
1485 "TcpInput: connection reset because data is lost for connected TCB %p\n",
1486 Tcb)
1487 );
1488
1489 goto RESET_THEN_DROP;
1490 }
1491
1492 TcpQueueData (Tcb, Nbuf);
1493 if (TcpDeliverData (Tcb) == -1) {
1494 goto RESET_THEN_DROP;
1495 }
1496
1497 if (!IsListEmpty (&Tcb->RcvQue)) {
1498 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
1499 }
1500 }
1501
1502 //
1503 // Eighth step: check the FIN.
1504 // This step is moved to TcpDeliverData. FIN will be
1505 // processed in sequence there. Check the comments in
1506 // the beginning of the file header for information.
1507 //
1508
1509 //
1510 // Tcb is a new child of the listening Parent,
1511 // commit it.
1512 //
1513 if (Parent != NULL) {
1514 Tcb->Parent = Parent;
1515 TcpInsertTcb (Tcb);
1516 }
1517
1518 if ((Tcb->State != TCP_CLOSED) &&
1519 (TcpToSendData (Tcb, 0) == 0) &&
1520 (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW) || (Nbuf->TotalSize != 0)))
1521 {
1522
1523 TcpToSendAck (Tcb);
1524 }
1525
1526 NetbufFree (Nbuf);
1527 return 0;
1528
1529 RESET_THEN_DROP:
1530 TcpSendReset (Tcb, Head, Len, Dst, Src, Version);
1531
1532 DROP_CONNECTION:
1533 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
1534
1535 NetbufFree (Nbuf);
1536 TcpClose (Tcb);
1537
1538 return -1;
1539
1540 SEND_RESET:
1541
1542 TcpSendReset (Tcb, Head, Len, Dst, Src, Version);
1543
1544 DISCARD:
1545
1546 //
1547 // Tcb is a child of Parent, and it doesn't survive
1548 //
1549 DEBUG ((EFI_D_WARN, "TcpInput: Discard a packet\n"));
1550 NetbufFree (Nbuf);
1551
1552 if ((Parent != NULL) && (Tcb != NULL)) {
1553
1554 ASSERT (Tcb->Sk != NULL);
1555 TcpClose (Tcb);
1556 }
1557
1558 return 0;
1559 }
1560
1561 /**
1562 Process the received ICMP error messages for TCP.
1563
1564 @param[in] Nbuf The buffer that contains part of the TCP segment without an IP header
1565 truncated from the ICMP error packet.
1566 @param[in] IcmpErr The ICMP error code interpreted from an ICMP error packet.
1567 @param[in] Src Source address of the ICMP error message.
1568 @param[in] Dst Destination address of the ICMP error message.
1569 @param[in] Version IP_VERSION_4 indicates IP4 stack. IP_VERSION_6 indicates
1570 IP6 stack.
1571
1572 **/
1573 VOID
1574 TcpIcmpInput (
1575 IN NET_BUF *Nbuf,
1576 IN UINT8 IcmpErr,
1577 IN EFI_IP_ADDRESS *Src,
1578 IN EFI_IP_ADDRESS *Dst,
1579 IN UINT8 Version
1580 )
1581 {
1582 TCP_HEAD *Head;
1583 TCP_CB *Tcb;
1584 TCP_SEQNO Seq;
1585 EFI_STATUS IcmpErrStatus;
1586 BOOLEAN IcmpErrIsHard;
1587 BOOLEAN IcmpErrNotify;
1588
1589 if (Nbuf->TotalSize < sizeof (TCP_HEAD)) {
1590 goto CLEAN_EXIT;
1591 }
1592
1593 Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);
1594 ASSERT (Head != NULL);
1595
1596 Tcb = TcpLocateTcb (
1597 Head->DstPort,
1598 Dst,
1599 Head->SrcPort,
1600 Src,
1601 Version,
1602 FALSE
1603 );
1604 if (Tcb == NULL || Tcb->State == TCP_CLOSED) {
1605
1606 goto CLEAN_EXIT;
1607 }
1608
1609 //
1610 // Validate the sequence number.
1611 //
1612 Seq = NTOHL (Head->Seq);
1613 if (!(TCP_SEQ_LEQ (Tcb->SndUna, Seq) && TCP_SEQ_LT (Seq, Tcb->SndNxt))) {
1614
1615 goto CLEAN_EXIT;
1616 }
1617
1618 IcmpErrStatus = IpIoGetIcmpErrStatus (
1619 IcmpErr,
1620 Tcb->Sk->IpVersion,
1621 &IcmpErrIsHard,
1622 &IcmpErrNotify
1623 );
1624
1625 if (IcmpErrNotify) {
1626
1627 SOCK_ERROR (Tcb->Sk, IcmpErrStatus);
1628 }
1629
1630 if (IcmpErrIsHard) {
1631
1632 TcpClose (Tcb);
1633 }
1634
1635 CLEAN_EXIT:
1636
1637 NetbufFree (Nbuf);
1638 }