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 <anc...@xiaomi.com> AuthorDate: Thu Sep 23 14:55:19 2021 +0800 net/tcp: sanity check for the listen address Signed-off-by: chao.an <anc...@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) {