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 2021/09/24 06:08:01 UTC

[incubator-nuttx] branch master updated: net/tcp: sanity check for the listen address

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/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new c132e5b  net/tcp: sanity check for the listen address
c132e5b is described below

commit c132e5bed4594a71980abe6ea8bad3e4880ab7e2
Author: chao.an <an...@xiaomi.com>
AuthorDate: Thu Sep 23 14:55:19 2021 +0800

    net/tcp: sanity check for the listen address
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 include/nuttx/net/ip.h |  1 +
 net/tcp/tcp.h          | 12 +++++++----
 net/tcp/tcp_input.c    | 50 ++++++++++++++++++++++++++++++++++++++++-----
 net/tcp/tcp_listen.c   | 55 +++++++++++++++++++++++++++++++++++++++-----------
 net/tcp/tcp_timer.c    |  5 +++--
 5 files changed, 100 insertions(+), 23 deletions(-)

diff --git a/include/nuttx/net/ip.h b/include/nuttx/net/ip.h
index 4e6b940..7e3ec70 100644
--- a/include/nuttx/net/ip.h
+++ b/include/nuttx/net/ip.h
@@ -52,6 +52,7 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 
 #include <arpa/inet.h>
 #include <netinet/in.h>
diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h
index 0be73a1..7e55d36 100644
--- a/net/tcp/tcp.h
+++ b/net/tcp/tcp.h
@@ -852,9 +852,12 @@ void tcp_listen_initialize(void);
  ****************************************************************************/
 
 #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
-FAR struct tcp_conn_s *tcp_findlistener(uint16_t portno, uint8_t domain);
+FAR struct tcp_conn_s *tcp_findlistener(FAR union ip_binding_u *uaddr,
+                                        uint16_t portno,
+                                        uint8_t domain);
 #else
-FAR struct tcp_conn_s *tcp_findlistener(uint16_t portno);
+FAR struct tcp_conn_s *tcp_findlistener(FAR union ip_binding_u *uaddr,
+                                        uint16_t portno);
 #endif
 
 /****************************************************************************
@@ -895,9 +898,10 @@ int tcp_listen(FAR struct tcp_conn_s *conn);
  ****************************************************************************/
 
 #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
-bool tcp_islistener(uint16_t portno, uint8_t domain);
+bool tcp_islistener(FAR union ip_binding_u *uaddr, uint16_t portno,
+                    uint8_t domain);
 #else
-bool tcp_islistener(uint16_t portno);
+bool tcp_islistener(FAR union ip_binding_u *uaddr, uint16_t portno);
 #endif
 
 /****************************************************************************
diff --git a/net/tcp/tcp_input.c b/net/tcp/tcp_input.c
index 01b9968..2975c0d 100644
--- a/net/tcp/tcp_input.c
+++ b/net/tcp/tcp_input.c
@@ -68,6 +68,7 @@
  ****************************************************************************/
 
 #define IPv4BUF ((FAR struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
+#define IPv6BUF ((FAR struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
 
 /****************************************************************************
  * Private Functions
@@ -283,8 +284,9 @@ static void tcp_snd_wnd_update(FAR struct tcp_conn_s *conn,
 static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
                       unsigned int iplen)
 {
-  FAR struct tcp_hdr_s *tcp;
   FAR struct tcp_conn_s *conn = NULL;
+  FAR struct tcp_hdr_s *tcp;
+  union ip_binding_u uaddr;
   unsigned int tcpiplen;
   unsigned int hdrlen;
   uint16_t tmp16;
@@ -370,10 +372,29 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
        */
 
       tmp16 = tcp->destport;
+#ifdef CONFIG_NET_IPv6
+#  ifdef CONFIG_NET_IPv4
+      if (domain == PF_INET6)
+#  endif
+        {
+          net_ipv6addr_copy(&uaddr.ipv6.laddr, IPv6BUF->destipaddr);
+        }
+#endif
+
+#ifdef CONFIG_NET_IPv4
+#  ifdef CONFIG_NET_IPv6
+      if (domain == PF_INET)
+#  endif
+        {
+          net_ipv4addr_copy(uaddr.ipv4.laddr,
+                            net_ip4addr_conv32(IPv4BUF->destipaddr));
+        }
+#endif
+
 #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
-      if (tcp_islistener(tmp16, domain))
+      if (tcp_islistener(&uaddr, tmp16, domain))
 #else
-      if (tcp_islistener(tmp16))
+      if (tcp_islistener(&uaddr, tmp16))
 #endif
         {
           /* We matched the incoming packet with a connection in LISTEN.
@@ -541,10 +562,29 @@ found:
 
           /* Notify the listener for the connection of the reset event */
 
+#ifdef CONFIG_NET_IPv6
+#  ifdef CONFIG_NET_IPv4
+          if (domain == PF_INET6)
+#  endif
+            {
+              net_ipv6addr_copy(&uaddr.ipv6.laddr, IPv6BUF->destipaddr);
+            }
+#endif
+
+#ifdef CONFIG_NET_IPv4
+#  ifdef CONFIG_NET_IPv6
+          if (domain == PF_INET)
+#  endif
+            {
+              net_ipv4addr_copy(uaddr.ipv4.laddr,
+                                net_ip4addr_conv32(IPv4BUF->destipaddr));
+            }
+#endif
+
 #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
-          listener = tcp_findlistener(conn->lport, domain);
+          listener = tcp_findlistener(&uaddr, conn->lport, domain);
 #else
-          listener = tcp_findlistener(conn->lport);
+          listener = tcp_findlistener(&uaddr, conn->lport);
 #endif
 
           /* We must free this TCP connection structure; this connection
diff --git a/net/tcp/tcp_listen.c b/net/tcp/tcp_listen.c
index c320174..4eb4c9c 100644
--- a/net/tcp/tcp_listen.c
+++ b/net/tcp/tcp_listen.c
@@ -52,6 +52,7 @@
 #include <nuttx/net/net.h>
 
 #include "devif/devif.h"
+#include "inet/inet.h"
 #include "tcp/tcp.h"
 
 /****************************************************************************
@@ -78,9 +79,12 @@ static FAR struct tcp_conn_s *tcp_listenports[CONFIG_NET_MAX_LISTENPORTS];
  ****************************************************************************/
 
 #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
-FAR struct tcp_conn_s *tcp_findlistener(uint16_t portno, uint8_t domain)
+FAR struct tcp_conn_s *tcp_findlistener(FAR union ip_binding_u *uaddr,
+                                        uint16_t portno,
+                                        uint8_t domain)
 #else
-FAR struct tcp_conn_s *tcp_findlistener(uint16_t portno)
+FAR struct tcp_conn_s *tcp_findlistener(FAR union ip_binding_u *uaddr,
+                                        uint16_t portno)
 #endif
 {
   int ndx;
@@ -100,9 +104,35 @@ FAR struct tcp_conn_s *tcp_findlistener(uint16_t portno)
       if (conn && conn->lport == portno)
 #endif
         {
-          /* Yes.. we found a listener on this port */
+#ifdef CONFIG_NET_IPv6
+#  ifdef CONFIG_NET_IPv4
+          if (domain == PF_INET6)
+#  endif
+            {
+              if (net_ipv6addr_cmp(conn->u.ipv6.laddr, uaddr->ipv6.laddr) ||
+                  net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_unspecaddr))
+                {
+                  /* Yes.. we found a listener on this port */
+
+                  return conn;
+                }
+            }
+#endif
 
-          return conn;
+#ifdef CONFIG_NET_IPv4
+#  ifdef CONFIG_NET_IPv6
+          if (domain == PF_INET)
+#  endif
+            {
+              if (net_ipv4addr_cmp(conn->u.ipv4.laddr, uaddr->ipv4.laddr) ||
+                  net_ipv4addr_cmp(conn->u.ipv4.laddr, INADDR_ANY))
+                {
+                  /* Yes.. we found a listener on this port */
+
+                  return conn;
+                }
+            }
+#endif
         }
     }
 
@@ -192,9 +222,9 @@ int tcp_listen(FAR struct tcp_conn_s *conn)
   /* First, check if there is already a socket listening on this port */
 
 #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
-  if (tcp_islistener(conn->lport, conn->domain))
+  if (tcp_islistener(&conn->u, conn->lport, conn->domain))
 #else
-  if (tcp_islistener(conn->lport))
+  if (tcp_islistener(&conn->u, conn->lport))
 #endif
     {
       /* Yes, then we must refuse this request */
@@ -242,14 +272,15 @@ int tcp_listen(FAR struct tcp_conn_s *conn)
  ****************************************************************************/
 
 #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
-bool tcp_islistener(uint16_t portno, uint8_t domain)
+bool tcp_islistener(FAR union ip_binding_u *uaddr, uint16_t portno,
+                    uint8_t domain)
 {
-  return tcp_findlistener(portno, domain) != NULL;
+  return tcp_findlistener(uaddr, portno, domain) != NULL;
 }
 #else
-bool tcp_islistener(uint16_t portno)
+bool tcp_islistener(FAR union ip_binding_u *uaddr, uint16_t portno)
 {
-  return tcp_findlistener(portno) != NULL;
+  return tcp_findlistener(uaddr, portno) != NULL;
 }
 #endif
 
@@ -276,9 +307,9 @@ int tcp_accept_connection(FAR struct net_driver_s *dev,
    */
 
 #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
-  listener = tcp_findlistener(portno, conn->domain);
+  listener = tcp_findlistener(&conn->u, portno, conn->domain);
 #else
-  listener = tcp_findlistener(portno);
+  listener = tcp_findlistener(&conn->u, portno);
 #endif
   if (listener != NULL)
     {
diff --git a/net/tcp/tcp_timer.c b/net/tcp/tcp_timer.c
index 9c063b0..4e8fc13 100644
--- a/net/tcp/tcp_timer.c
+++ b/net/tcp/tcp_timer.c
@@ -250,9 +250,10 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
                   /* Find the listener for this connection. */
 
 #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
-                  listener = tcp_findlistener(conn->lport, conn->domain);
+                  listener = tcp_findlistener(&conn->u, conn->lport,
+                                              conn->domain);
 #else
-                  listener = tcp_findlistener(conn->lport);
+                  listener = tcp_findlistener(&conn->u, conn->lport);
 #endif
                   if (listener != NULL)
                     {