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/12/17 17:25:12 UTC
[incubator-nuttx] branch master updated: net/udp: fix the invaild udp destination 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 b10dcf7 net/udp: fix the invaild udp destination address
b10dcf7 is described below
commit b10dcf7c0d3280dbb207b6cfc0564d99868568dd
Author: chao.an <an...@xiaomi.com>
AuthorDate: Fri Dec 17 14:35:51 2021 +0800
net/udp: fix the invaild udp destination address
If the udp socket not connected, it is possible to have
multi-different destination address in each iob entry,
update the remote address every time to avoid sent to the
incorrect destination.
Signed-off-by: chao.an <an...@xiaomi.com>
---
net/socket/net_fstat.c | 2 +-
net/udp/udp.h | 20 +++++-
net/udp/udp_conn.c | 140 ++++++++++++++++++++--------------------
net/udp/udp_finddev.c | 43 +++++++++---
net/udp/udp_sendto_buffered.c | 23 +++++--
net/udp/udp_sendto_unbuffered.c | 2 +-
6 files changed, 143 insertions(+), 87 deletions(-)
diff --git a/net/socket/net_fstat.c b/net/socket/net_fstat.c
index 24af5b3..7c75b85 100644
--- a/net/socket/net_fstat.c
+++ b/net/socket/net_fstat.c
@@ -133,7 +133,7 @@ int psock_fstat(FAR struct socket *psock, FAR struct stat *buf)
* order to get the MTU and LL_HDRLEN:
*/
- dev = udp_find_raddr_device(conn);
+ dev = udp_find_raddr_device(conn, NULL);
if (dev == NULL)
{
/* This should never happen except perhaps in some rare race
diff --git a/net/udp/udp.h b/net/udp/udp.h
index 868ea6d..2083260 100644
--- a/net/udp/udp.h
+++ b/net/udp/udp.h
@@ -247,6 +247,22 @@ FAR struct udp_conn_s *udp_active(FAR struct net_driver_s *dev,
FAR struct udp_conn_s *udp_nextconn(FAR struct udp_conn_s *conn);
/****************************************************************************
+ * Name: udp_select_port
+ *
+ * Description:
+ * Select an unused port number.
+ *
+ * NOTE that in principle this function could fail if there is no available
+ * port number. There is no check for that case and it would actually
+ * in an infinite loop if that were the case. In this simple, small UDP
+ * implementation, it is reasonable to assume that that error cannot happen
+ * and that a port number will always be available.
+ *
+ ****************************************************************************/
+
+uint16_t udp_select_port(uint8_t domain, FAR union ip_binding_u *u);
+
+/****************************************************************************
* Name: udp_bind
*
* Description:
@@ -610,7 +626,9 @@ FAR struct net_driver_s *udp_find_laddr_device(FAR struct udp_conn_s *conn);
*
****************************************************************************/
-FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn);
+FAR struct net_driver_s *
+udp_find_raddr_device(FAR struct udp_conn_s *conn,
+ FAR struct sockaddr_storage *remote);
/****************************************************************************
* Name: udp_callback
diff --git a/net/udp/udp_conn.c b/net/udp/udp_conn.c
index acb4377..57b46f1 100644
--- a/net/udp/udp_conn.c
+++ b/net/udp/udp_conn.c
@@ -173,76 +173,6 @@ static FAR struct udp_conn_s *udp_find_conn(uint8_t domain,
}
/****************************************************************************
- * Name: udp_select_port
- *
- * Description:
- * Select an unused port number.
- *
- * NOTE that in principle this function could fail if there is no available
- * port number. There is no check for that case and it would actually
- * in an infinite loop if that were the case. In this simple, small UDP
- * implementation, it is reasonable to assume that that error cannot happen
- * and that a port number will always be available.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * Next available port number
- *
- ****************************************************************************/
-
-static uint16_t udp_select_port(uint8_t domain, FAR union ip_binding_u *u)
-{
- static uint16_t g_last_udp_port;
- uint16_t portno;
-
- net_lock();
-
- /* Generate port base dynamically */
-
- if (g_last_udp_port == 0)
- {
- g_last_udp_port = clock_systime_ticks() % 32000;
-
- if (g_last_udp_port < 4096)
- {
- g_last_udp_port += 4096;
- }
- }
-
- /* Find an unused local port number. Loop until we find a valid
- * listen port number that is not being used by any other connection.
- */
-
- do
- {
- /* Guess that the next available port number will be the one after
- * the last port number assigned.
- */
-
- ++g_last_udp_port;
-
- /* Make sure that the port number is within range */
-
- if (g_last_udp_port >= 32000)
- {
- g_last_udp_port = 4096;
- }
- }
- while (udp_find_conn(domain, u, htons(g_last_udp_port)) != NULL);
-
- /* Initialize and return the connection structure, bind it to the
- * port number
- */
-
- portno = g_last_udp_port;
- net_unlock();
-
- return portno;
-}
-
-/****************************************************************************
* Name: udp_ipv4_active
*
* Description:
@@ -528,6 +458,76 @@ static inline FAR struct udp_conn_s *
****************************************************************************/
/****************************************************************************
+ * Name: udp_select_port
+ *
+ * Description:
+ * Select an unused port number.
+ *
+ * NOTE that in principle this function could fail if there is no available
+ * port number. There is no check for that case and it would actually
+ * in an infinite loop if that were the case. In this simple, small UDP
+ * implementation, it is reasonable to assume that that error cannot happen
+ * and that a port number will always be available.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Next available port number
+ *
+ ****************************************************************************/
+
+uint16_t udp_select_port(uint8_t domain, FAR union ip_binding_u *u)
+{
+ static uint16_t g_last_udp_port;
+ uint16_t portno;
+
+ net_lock();
+
+ /* Generate port base dynamically */
+
+ if (g_last_udp_port == 0)
+ {
+ g_last_udp_port = clock_systime_ticks() % 32000;
+
+ if (g_last_udp_port < 4096)
+ {
+ g_last_udp_port += 4096;
+ }
+ }
+
+ /* Find an unused local port number. Loop until we find a valid
+ * listen port number that is not being used by any other connection.
+ */
+
+ do
+ {
+ /* Guess that the next available port number will be the one after
+ * the last port number assigned.
+ */
+
+ ++g_last_udp_port;
+
+ /* Make sure that the port number is within range */
+
+ if (g_last_udp_port >= 32000)
+ {
+ g_last_udp_port = 4096;
+ }
+ }
+ while (udp_find_conn(domain, u, htons(g_last_udp_port)) != NULL);
+
+ /* Initialize and return the connection structure, bind it to the
+ * port number
+ */
+
+ portno = g_last_udp_port;
+ net_unlock();
+
+ return portno;
+}
+
+/****************************************************************************
* Name: udp_initialize
*
* Description:
diff --git a/net/udp/udp_finddev.c b/net/udp/udp_finddev.c
index e0efac1..3cacdb2 100644
--- a/net/udp/udp_finddev.c
+++ b/net/udp/udp_finddev.c
@@ -184,7 +184,9 @@ FAR struct net_driver_s *udp_find_laddr_device(FAR struct udp_conn_s *conn)
*
****************************************************************************/
-FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn)
+FAR struct net_driver_s *
+udp_find_raddr_device(FAR struct udp_conn_s *conn,
+ FAR struct sockaddr_storage *remote)
{
/* We need to select the device that is going to route the UDP packet
* based on the provided IP address.
@@ -195,13 +197,25 @@ FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn)
if (conn->domain == PF_INET)
#endif
{
+ in_addr_t raddr;
+
+ if (remote)
+ {
+ FAR const struct sockaddr_in *inaddr =
+ (FAR const struct sockaddr_in *)remote;
+ net_ipv4addr_copy(raddr, inaddr->sin_addr.s_addr);
+ }
+ else
+ {
+ net_ipv4addr_copy(raddr, conn->u.ipv4.raddr);
+ }
+
/* Check if the remote, destination address is the broadcast
* or multicast address. If this is the case, select the device
* using the locally bound address (assuming that there is one).
*/
- if (conn->u.ipv4.raddr == INADDR_BROADCAST ||
- IN_MULTICAST(NTOHL(conn->u.ipv4.raddr)))
+ if (raddr == INADDR_BROADCAST || IN_MULTICAST(NTOHL(raddr)))
{
/* Make sure that the socket is bound to some non-zero, local
* address. Zero is used as an indication that the laddr is
@@ -225,12 +239,12 @@ FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn)
* address.
*/
- else if (conn->u.ipv4.raddr != INADDR_ANY)
+ else if (raddr != INADDR_ANY)
{
/* Normal lookup using the verified remote address */
return netdev_findby_ripv4addr(conn->u.ipv4.laddr,
- conn->u.ipv4.raddr);
+ raddr);
}
else
{
@@ -248,12 +262,25 @@ FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn)
else
#endif
{
+ net_ipv6addr_t raddr;
+
+ if (remote)
+ {
+ FAR const struct sockaddr_in6 *inaddr =
+ (FAR const struct sockaddr_in6 *)remote;
+ net_ipv6addr_copy(raddr, inaddr->sin6_addr.s6_addr16);
+ }
+ else
+ {
+ net_ipv6addr_copy(raddr, conn->u.ipv6.raddr);
+ }
+
/* Check if the remote, destination address is a multicast
* address. If this is the case, select the device
* using the locally bound address (assuming that there is one).
*/
- if (net_is_addr_mcast(conn->u.ipv6.raddr))
+ if (net_is_addr_mcast(raddr))
{
/* Make sure that the socket is bound to some non-zero, local
* address. The IPv6 unspecified address is used as an
@@ -278,12 +305,12 @@ FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn)
* address.
*/
- else if (!net_ipv6addr_cmp(conn->u.ipv6.raddr, g_ipv6_unspecaddr))
+ else if (!net_ipv6addr_cmp(raddr, g_ipv6_unspecaddr))
{
/* Normal lookup using the verified remote address */
return netdev_findby_ripv6addr(conn->u.ipv6.laddr,
- conn->u.ipv6.raddr);
+ raddr);
}
else
{
diff --git a/net/udp/udp_sendto_buffered.c b/net/udp/udp_sendto_buffered.c
index 9f8840b..4ab651a 100644
--- a/net/udp/udp_sendto_buffered.c
+++ b/net/udp/udp_sendto_buffered.c
@@ -279,7 +279,6 @@ static int sendto_next_transfer(FAR struct socket *psock,
{
FAR struct udp_wrbuffer_s *wrb;
FAR struct net_driver_s *dev;
- int ret;
/* Set the UDP "connection" to the destination address of the write buffer
* at the head of the queue.
@@ -292,11 +291,15 @@ static int sendto_next_transfer(FAR struct socket *psock,
return -ENOENT;
}
- ret = udp_connect(conn, (FAR const struct sockaddr *)&wrb->wb_dest);
- if (ret < 0)
+ /* Has this address already been bound to a local port (lport)? */
+
+ if (!conn->lport)
{
- nerr("ERROR: udp_connect failed: %d\n", ret);
- return ret;
+ /* No.. Find an unused local port number and bind it to the
+ * connection structure.
+ */
+
+ conn->lport = htons(udp_select_port(conn->domain, &conn->u));
}
/* Get the device that will handle the remote packet transfers. This
@@ -308,7 +311,7 @@ static int sendto_next_transfer(FAR struct socket *psock,
* transmission could harm performance.
*/
- dev = udp_find_raddr_device(conn);
+ dev = udp_find_raddr_device(conn, &wrb->wb_dest);
if (dev == NULL)
{
nerr("ERROR: udp_find_raddr_device failed\n");
@@ -453,6 +456,14 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
wrb = (FAR struct udp_wrbuffer_s *)sq_peek(&conn->write_q);
DEBUGASSERT(wrb != NULL);
+ /* If the udp socket not connected, it is possible to have
+ * multi-different destination address in each iob entry,
+ * update the remote address every time to avoid sent to the
+ * incorrect destination.
+ */
+
+ udp_connect(conn, (FAR const struct sockaddr *)&wrb->wb_dest);
+
/* Get the amount of data that we can send in the next packet.
* We will send either the remaining data in the buffer I/O
* buffer chain, or as much as will fit given the MSS and current
diff --git a/net/udp/udp_sendto_unbuffered.c b/net/udp/udp_sendto_unbuffered.c
index f9d7385..12d5f81 100644
--- a/net/udp/udp_sendto_unbuffered.c
+++ b/net/udp/udp_sendto_unbuffered.c
@@ -431,7 +431,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
* should never be NULL.
*/
- state.st_dev = udp_find_raddr_device(conn);
+ state.st_dev = udp_find_raddr_device(conn, NULL);
if (state.st_dev == NULL)
{
nerr("ERROR: udp_find_raddr_device failed\n");