]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/TcpDxe/TcpOutput.c
NetworkPkg/TcpDxe: Check TCP payload for release version.
[mirror_edk2.git] / NetworkPkg / TcpDxe / TcpOutput.c
index c038213484784abf8b4061536c3fe12c11a2bfa4..1697514a92bff1b1e4981e0ff1b71f4a5af430e0 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   TCP output process routines.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -292,7 +292,11 @@ TcpTransmitSegment (
   BOOLEAN   Syn;\r
   UINT32    DataLen;\r
 \r
-  ASSERT ((Nbuf != NULL) && (Nbuf->Tcp == NULL) && (TcpVerifySegment (Nbuf) != 0));\r
+  ASSERT ((Nbuf != NULL) && (Nbuf->Tcp == NULL));\r
+\r
+  if (TcpVerifySegment (Nbuf) == 0) {\r
+    return -1; \r
+  }\r
 \r
   DataLen = Nbuf->TotalSize;\r
 \r
@@ -634,7 +638,11 @@ TcpGetSegment (
     Nbuf = TcpGetSegmentSock (Tcb, Seq, Len);\r
   }\r
 \r
-  ASSERT (TcpVerifySegment (Nbuf) != 0);\r
+  if (TcpVerifySegment (Nbuf) == 0) {\r
+    NetbufFree (Nbuf);\r
+    return NULL;\r
+  }\r
+  \r
   return Nbuf;\r
 }\r
 \r
@@ -664,7 +672,27 @@ TcpRetransmit (
   // 2. Must in the current send window\r
   // 3. Will not change the boundaries of queued segments.\r
   //\r
-  if (TCP_SEQ_LT (Tcb->SndWl2 + Tcb->SndWnd, Seq)) {\r
+\r
+  //\r
+  // Handle the Window Retraction if TCP window scale is enabled according to RFC7323:\r
+  //   On first retransmission, or if the sequence number is out of\r
+  //   window by less than 2^Rcv.Wind.Shift, then do normal\r
+  //   retransmission(s) without regard to the receiver window as long\r
+  //   as the original segment was in window when it was sent.\r
+  //\r
+  if ((Tcb->SndWndScale != 0) &&\r
+      (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax) || TCP_SEQ_BETWEEN (Tcb->SndWl2 + Tcb->SndWnd, Seq, Tcb->SndWl2 + Tcb->SndWnd + (1 << Tcb->SndWndScale)))) {\r
+    Len = TCP_SUB_SEQ (Tcb->SndNxt, Seq);\r
+    DEBUG (\r
+      (EFI_D_WARN,\r
+      "TcpRetransmit: retransmission without regard to the receiver window for TCB %p\n",\r
+      Tcb)\r
+      );\r
+    \r
+  } else if (TCP_SEQ_GEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq)) {\r
+    Len = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq);\r
+    \r
+  } else {\r
     DEBUG (\r
       (EFI_D_WARN,\r
       "TcpRetransmit: retransmission cancelled because send window too small for TCB %p\n",\r
@@ -674,20 +702,25 @@ TcpRetransmit (
     return 0;\r
   }\r
 \r
-  Len   = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq);\r
-  Len   = MIN (Len, Tcb->SndMss);\r
+  Len = MIN (Len, Tcb->SndMss);\r
 \r
-  Nbuf  = TcpGetSegmentSndQue (Tcb, Seq, Len);\r
+  Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len);\r
   if (Nbuf == NULL) {\r
     return -1;\r
   }\r
 \r
-  ASSERT (TcpVerifySegment (Nbuf) != 0);\r
+  if (TcpVerifySegment (Nbuf) == 0) {\r
+    goto OnError;\r
+  }\r
 \r
   if (TcpTransmitSegment (Tcb, Nbuf) != 0) {\r
     goto OnError;\r
   }\r
 \r
+  if (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax)) {\r
+    Tcb->RetxmitSeqMax = Seq;\r
+  }\r
+\r
   //\r
   // The retransmitted buffer may be on the SndQue,\r
   // trim TCP head because all the buffers on SndQue\r
@@ -797,7 +830,7 @@ TcpToSendData (
     Len   = TcpDataToSend (Tcb, Force);\r
     Seq   = Tcb->SndNxt;\r
 \r
-    ASSERT ((Tcb->State) < (sizeof (mTcpOutFlag) / sizeof (mTcpOutFlag[0])));\r
+    ASSERT ((Tcb->State) < (ARRAY_SIZE (mTcpOutFlag)));\r
     Flag  = mTcpOutFlag[Tcb->State];\r
 \r
     if ((Flag & TCP_FLG_SYN) != 0) {\r
@@ -847,7 +880,7 @@ TcpToSendData (
           TCP_SEQ_LT (End + 1, Tcb->SndWnd + Tcb->SndWl2)\r
             ) {\r
         DEBUG (\r
-          (EFI_D_INFO,\r
+          (EFI_D_NET,\r
           "TcpToSendData: send FIN to peer for TCB %p in state %s\n",\r
           Tcb,\r
           mTcpStateName[Tcb->State])\r
@@ -863,8 +896,14 @@ TcpToSendData (
     Seg->End  = End;\r
     Seg->Flag = Flag;\r
 \r
-    ASSERT (TcpVerifySegment (Nbuf) != 0);\r
-    ASSERT (TcpCheckSndQue (&Tcb->SndQue) != 0);\r
+    if (TcpVerifySegment (Nbuf) == 0 || TcpCheckSndQue (&Tcb->SndQue) == 0) {\r
+      DEBUG (\r
+        (EFI_D_ERROR,\r
+        "TcpToSendData: discard a broken segment for TCB %p\n",\r
+        Tcb)\r
+        );\r
+      goto OnError;\r
+    }\r
 \r
     //\r
     // Don't send an empty segment here.\r
@@ -876,8 +915,7 @@ TcpToSendData (
         Tcb)\r
         );\r
 \r
-      NetbufFree (Nbuf);\r
-      return Sent;\r
+      goto OnError;\r
     }\r
 \r
     if (TcpTransmitSegment (Tcb, Nbuf) != 0) {\r
@@ -927,7 +965,7 @@ TcpToSendData (
     if ((Tcb->CongestState == TCP_CONGEST_OPEN) && !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {\r
 \r
       DEBUG (\r
-        (EFI_D_INFO,\r
+        (EFI_D_NET,\r
         "TcpToSendData: set RTT measure sequence %d for TCB %p\n",\r
         Seq,\r
         Tcb)\r
@@ -1058,7 +1096,7 @@ TcpToSendAck (
   }\r
 \r
   DEBUG (\r
-    (EFI_D_INFO,\r
+    (EFI_D_NET,\r
     "TcpToSendAck: scheduled a delayed ACK for TCB %p\n",\r
     Tcb)\r
     );\r