You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/01/18 08:24:18 UTC

[nuttx] 03/04: net/tcp: parse tcp options in common function

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit c581cc5f9b8c3bbd622895f3eff4e6a7f1342774
Author: chao an <an...@xiaomi.com>
AuthorDate: Mon Jan 9 19:44:23 2023 +0800

    net/tcp: parse tcp options in common function
    
    Signed-off-by: chao an <an...@xiaomi.com>
---
 net/tcp/tcp_input.c | 212 ++++++++++++++++++++++++----------------------------
 1 file changed, 96 insertions(+), 116 deletions(-)

diff --git a/net/tcp/tcp_input.c b/net/tcp/tcp_input.c
index 552f6b1d37..b4b7b05292 100644
--- a/net/tcp/tcp_input.c
+++ b/net/tcp/tcp_input.c
@@ -564,6 +564,100 @@ clear:
 }
 #endif /* CONFIG_NET_TCP_OUT_OF_ORDER */
 
+/****************************************************************************
+ * Name: tcp_parse_option
+ *
+ * Description:
+ *   Parse incoming TCP options
+ *
+ * Input Parameters:
+ *   dev    - The device driver structure containing the received TCP packet.
+ *   conn   - The TCP connection of interest
+ *   iplen  - Length of the IP header (IPv4_HDRLEN or IPv6_HDRLEN).
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static void tcp_parse_option(FAR struct net_driver_s *dev,
+                             FAR struct tcp_conn_s *conn,
+                             unsigned int iplen)
+{
+  FAR struct tcp_hdr_s *tcp;
+  unsigned int tcpiplen;
+  uint16_t tmp16;
+  uint8_t  opt;
+  int i;
+
+  tcp = IPBUF(iplen);
+
+  if ((tcp->tcpoffset & 0xf0) <= 0x50)
+    {
+      return;
+    }
+
+  tcpiplen = iplen + TCP_HDRLEN;
+
+  for (i = 0; i < ((tcp->tcpoffset >> 4) - 5) << 2 ; )
+    {
+      opt = IPDATA(tcpiplen + i);
+      if (opt == TCP_OPT_END)
+        {
+          /* End of options. */
+
+          break;
+        }
+      else if (opt == TCP_OPT_NOOP)
+        {
+          /* NOP option. */
+
+          ++i;
+          continue;
+        }
+      else if (opt == TCP_OPT_MSS &&
+               IPDATA(tcpiplen + 1 + i) == TCP_OPT_MSS_LEN)
+        {
+          uint16_t tcp_mss = TCP_MSS(dev, iplen);
+
+          /* An MSS option with the right option length. */
+
+          tmp16 = ((uint16_t)IPDATA(tcpiplen + 2 + i) << 8) |
+                   (uint16_t)IPDATA(tcpiplen + 3 + i);
+          conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16;
+        }
+#ifdef CONFIG_NET_TCP_WINDOW_SCALE
+      else if (opt == TCP_OPT_WS &&
+               IPDATA(tcpiplen + 1 + i) == TCP_OPT_WS_LEN)
+        {
+          conn->snd_scale = IPDATA(tcpiplen + 2 + i);
+          conn->rcv_scale = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR;
+          conn->flags    |= TCP_WSCALE;
+        }
+#endif
+      else
+        {
+          /* All other options have a length field, so that we
+           * easily can skip past them.
+           */
+
+          if (IPDATA(tcpiplen + 1 + i) == 0)
+            {
+              /* If the length field is zero, the options are
+               * malformed and we don't process them further.
+               */
+
+              break;
+            }
+        }
+
+      i += IPDATA(tcpiplen + 1 + i);
+    }
+}
+
 /****************************************************************************
  * Name: tcp_input
  *
@@ -593,9 +687,7 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
   uint16_t tmp16;
   uint16_t flags;
   uint16_t result;
-  uint8_t  opt;
   int      len;
-  int      i;
 
 #ifdef CONFIG_NET_STATISTICS
   /* Bump up the count of TCP packets received */
@@ -748,63 +840,7 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
 
           /* Parse the TCP MSS option, if present. */
 
-          if ((tcp->tcpoffset & 0xf0) > 0x50)
-            {
-              for (i = 0; i < ((tcp->tcpoffset >> 4) - 5) << 2 ; )
-                {
-                  opt = IPDATA(tcpiplen + i);
-                  if (opt == TCP_OPT_END)
-                    {
-                      /* End of options. */
-
-                      break;
-                    }
-                  else if (opt == TCP_OPT_NOOP)
-                    {
-                      /* NOP option. */
-
-                      ++i;
-                      continue;
-                    }
-                  else if (opt == TCP_OPT_MSS &&
-                           IPDATA(tcpiplen + 1 + i) == TCP_OPT_MSS_LEN)
-                    {
-                      uint16_t tcp_mss = TCP_MSS(dev, iplen);
-
-                      /* An MSS option with the right option length. */
-
-                      tmp16 = ((uint16_t)IPDATA(tcpiplen + 2 + i) << 8) |
-                               (uint16_t)IPDATA(tcpiplen + 3 + i);
-                      conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16;
-                    }
-#ifdef CONFIG_NET_TCP_WINDOW_SCALE
-                  else if (opt == TCP_OPT_WS &&
-                           IPDATA(tcpiplen + 1 + i) == TCP_OPT_WS_LEN)
-                    {
-                      conn->snd_scale = IPDATA(tcpiplen + 2 + i);
-                      conn->rcv_scale = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR;
-                      conn->flags    |= TCP_WSCALE;
-                    }
-#endif
-                  else
-                    {
-                      /* All other options have a length field, so that we
-                       * easily can skip past them.
-                       */
-
-                      if (IPDATA(tcpiplen + 1 + i) == 0)
-                        {
-                          /* If the length field is zero, the options are
-                           * malformed and we don't process them further.
-                           */
-
-                          break;
-                        }
-                    }
-
-                  i += IPDATA(tcpiplen + 1 + i);
-                }
-            }
+          tcp_parse_option(dev, conn, iplen);
 
           /* Our response will be a SYNACK. */
 
@@ -1245,63 +1281,7 @@ found:
           {
             /* Parse the TCP MSS option, if present. */
 
-            if ((tcp->tcpoffset & 0xf0) > 0x50)
-              {
-                for (i = 0; i < ((tcp->tcpoffset >> 4) - 5) << 2 ; )
-                  {
-                    opt = IPDATA(tcpiplen + i);
-                    if (opt == TCP_OPT_END)
-                      {
-                        /* End of options. */
-
-                        break;
-                      }
-                    else if (opt == TCP_OPT_NOOP)
-                      {
-                        /* NOP option. */
-
-                        ++i;
-                        continue;
-                      }
-                    else if (opt == TCP_OPT_MSS &&
-                             IPDATA(tcpiplen + 1 + i) == TCP_OPT_MSS_LEN)
-                      {
-                        uint16_t tcp_mss = TCP_MSS(dev, iplen);
-
-                        /* An MSS option with the right option length. */
-
-                        tmp16 = (IPDATA(tcpiplen + 2 + i) << 8) |
-                                 IPDATA(tcpiplen + 3 + i);
-                        conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16;
-                      }
-#ifdef CONFIG_NET_TCP_WINDOW_SCALE
-                    else if (opt == TCP_OPT_WS &&
-                             IPDATA(tcpiplen + 1 + i) == TCP_OPT_WS_LEN)
-                      {
-                        conn->snd_scale = IPDATA(tcpiplen + 2 + i);
-                        conn->rcv_scale = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR;
-                        conn->flags    |= TCP_WSCALE;
-                      }
-#endif
-                    else
-                      {
-                        /* All other options have a length field, so that we
-                         * easily can skip past them.
-                         */
-
-                        if (IPDATA(tcpiplen + 1 + i) == 0)
-                          {
-                            /* If the length field is zero, the options are
-                             * malformed and we don't process them further.
-                             */
-
-                            break;
-                          }
-                      }
-
-                    i += IPDATA(tcpiplen + 1 + i);
-                  }
-              }
+            tcp_parse_option(dev, conn, iplen);
 
             conn->tcpstateflags = TCP_ESTABLISHED;
             memcpy(conn->rcvseq, tcp->seqno, 4);