net/icmpv6: replace net_lock with conn_lock and conn_lock_dev

Protect icmpv6 resources through netdev_lock, conn_lock, and icmpv6_list_lock

Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
This commit is contained in:
zhanghongyu
2025-07-25 11:00:30 +08:00
committed by Xiang Xiao
parent 5032377c34
commit 8ef876562e
10 changed files with 39 additions and 47 deletions
+1
View File
@@ -177,3 +177,4 @@ libs/libc/tre-mem.c
fs_ep, &fs_ep->sems, &fs_ep->reqq); fs_ep, &fs_ep->sems, &fs_ep->reqq);
#define RTPROT_RA 9 /* RDISC/ND router advertisements */ #define RTPROT_RA 9 /* RDISC/ND router advertisements */
/* Followed by one or more ND options */ /* Followed by one or more ND options */
* message using the Neighbor Discovery (ND) protocol. It then listens
+5 -19
View File
@@ -230,11 +230,13 @@ static int icmpv6_send_message(FAR struct net_driver_s *dev, bool advertise)
* net_sem_wait will also terminate if a signal is received. * net_sem_wait will also terminate if a signal is received.
*/ */
netdev_unlock(dev);
do do
{ {
net_sem_wait(&state.snd_sem); net_sem_wait(&state.snd_sem);
} }
while (!state.snd_sent); while (!state.snd_sent);
netdev_lock(dev);
ret = state.snd_result; ret = state.snd_result;
devif_dev_callback_free(dev, state.snd_cb); devif_dev_callback_free(dev, state.snd_cb);
@@ -271,6 +273,9 @@ errout_with_semaphore:
* Zero (OK) is returned on success; A negated errno value is returned on * Zero (OK) is returned on success; A negated errno value is returned on
* any failure. * any failure.
* *
* Assumptions:
* This function must be called with the network locked.
*
****************************************************************************/ ****************************************************************************/
int icmpv6_autoconfig(FAR struct net_driver_s *dev) int icmpv6_autoconfig(FAR struct net_driver_s *dev)
@@ -285,22 +290,6 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
DEBUGASSERT(dev); DEBUGASSERT(dev);
ninfo("Auto-configuring %s\n", dev->d_ifname); ninfo("Auto-configuring %s\n", dev->d_ifname);
/* Lock the network.
*
* NOTE: Normally it is required that the network be in the "down" state
* when re-configuring the network interface. This is thought not to be
* a problem here because.
*
* 1. The ICMPv6 logic here runs with the network locked so there can be
* no outgoing packets with bad source IP addresses from any
* asynchronous network activity using the device being reconfigured.
* 2. Incoming packets depend only upon the MAC filtering. Network
* drivers do not use the IP address; they filter incoming packets
* using only the MAC address which is not being changed here.
*/
net_lock();
/* IPv6 Stateless Autoconfiguration /* IPv6 Stateless Autoconfiguration
* Reference: * Reference:
* http://www.tcpipguide.com/free/t_IPv6AutoconfigurationandRenumbering.htm * http://www.tcpipguide.com/free/t_IPv6AutoconfigurationandRenumbering.htm
@@ -354,7 +343,6 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
nerr("ERROR: IP conflict\n"); nerr("ERROR: IP conflict\n");
net_unlock();
return -EEXIST; return -EEXIST;
} }
} }
@@ -369,7 +357,6 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
ret = netdev_ipv6_add(dev, lladdr, net_ipv6_mask2pref(g_ipv6_llnetmask)); ret = netdev_ipv6_add(dev, lladdr, net_ipv6_mask2pref(g_ipv6_llnetmask));
if (ret < 0) if (ret < 0)
{ {
net_unlock();
return ret; return ret;
} }
@@ -463,7 +450,6 @@ got_lladdr:
/* On success, the new address was already set (in icmpv_rnotify()). */ /* On success, the new address was already set (in icmpv_rnotify()). */
net_unlock();
return ret; return ret;
} }
+1
View File
@@ -125,6 +125,7 @@ void icmpv6_free(FAR struct icmpv6_conn_s *conn)
/* Remove the connection from the active list */ /* Remove the connection from the active list */
dq_rem(&conn->sconn.node, &g_active_icmpv6_connections); dq_rem(&conn->sconn.node, &g_active_icmpv6_connections);
nxmutex_destroy(&conn->sconn.s_lock);
/* Free the connection. */ /* Free the connection. */
+3 -2
View File
@@ -38,6 +38,7 @@
#include <nuttx/mm/iob.h> #include <nuttx/mm/iob.h>
#include <nuttx/net/net.h> #include <nuttx/net/net.h>
#include "utils/utils.h"
#include "icmpv6/icmpv6.h" #include "icmpv6/icmpv6.h"
/**************************************************************************** /****************************************************************************
@@ -62,7 +63,7 @@ int icmpv6_ioctl(FAR struct socket *psock, int cmd, unsigned long arg)
FAR struct icmpv6_conn_s *conn = psock->s_conn; FAR struct icmpv6_conn_s *conn = psock->s_conn;
int ret = OK; int ret = OK;
net_lock(); conn_lock(&conn->sconn);
switch (cmd) switch (cmd)
{ {
@@ -91,7 +92,7 @@ int icmpv6_ioctl(FAR struct socket *psock, int cmd, unsigned long arg)
break; break;
} }
net_unlock(); conn_unlock(&conn->sconn);
return ret; return ret;
} }
+2 -2
View File
@@ -272,7 +272,7 @@ int icmpv6_neighbor(FAR struct net_driver_s *dev,
* want anything to happen until we are ready. * want anything to happen until we are ready.
*/ */
net_lock(); netdev_lock(dev);
state.snd_cb = devif_callback_alloc((dev), state.snd_cb = devif_callback_alloc((dev),
&(dev)->d_conncb, &(dev)->d_conncb,
&(dev)->d_conncb_tail); &(dev)->d_conncb_tail);
@@ -367,7 +367,7 @@ int icmpv6_neighbor(FAR struct net_driver_s *dev,
devif_dev_callback_free(dev, state.snd_cb); devif_dev_callback_free(dev, state.snd_cb);
errout_with_lock: errout_with_lock:
net_unlock(); netdev_unlock(dev);
errout: errout:
return ret; return ret;
+12 -13
View File
@@ -36,6 +36,7 @@
#include "devif/devif.h" #include "devif/devif.h"
#include "netdev/netdev.h" #include "netdev/netdev.h"
#include "utils/utils.h"
#include "icmpv6/icmpv6.h" #include "icmpv6/icmpv6.h"
/**************************************************************************** /****************************************************************************
@@ -144,20 +145,19 @@ int icmpv6_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
pollevent_t eventset = 0; pollevent_t eventset = 0;
int ret = OK; int ret = OK;
/* Some of the following must be atomic */
net_lock();
conn = psock->s_conn; conn = psock->s_conn;
/* Sanity check */ /* Sanity check */
if (!conn || !fds) if (!conn || !fds)
{ {
ret = -EINVAL; return -EINVAL;
goto errout_with_lock;
} }
/* Some of the following must be atomic */
conn_dev_lock(&conn->sconn, conn->dev);
/* Find a container to hold the poll information */ /* Find a container to hold the poll information */
info = conn->pollinfo; info = conn->pollinfo;
@@ -225,7 +225,7 @@ int icmpv6_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
poll_notify(&fds, 1, eventset); poll_notify(&fds, 1, eventset);
errout_with_lock: errout_with_lock:
net_unlock(); conn_dev_unlock(&conn->sconn, conn->dev);
return ret; return ret;
} }
@@ -250,20 +250,19 @@ int icmpv6_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
FAR struct icmpv6_conn_s *conn; FAR struct icmpv6_conn_s *conn;
FAR struct icmpv6_poll_s *info; FAR struct icmpv6_poll_s *info;
/* Some of the following must be atomic */
net_lock();
conn = psock->s_conn; conn = psock->s_conn;
/* Sanity check */ /* Sanity check */
if (!conn || !fds->priv) if (!conn || !fds->priv)
{ {
net_unlock();
return -EINVAL; return -EINVAL;
} }
/* Some of the following must be atomic */
conn_dev_lock(&conn->sconn, conn->dev);
/* Recover the socket descriptor poll state info from the poll structure */ /* Recover the socket descriptor poll state info from the poll structure */
info = (FAR struct icmpv6_poll_s *)fds->priv; info = (FAR struct icmpv6_poll_s *)fds->priv;
@@ -284,7 +283,7 @@ int icmpv6_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
info->psock = NULL; info->psock = NULL;
} }
net_unlock(); conn_dev_unlock(&conn->sconn, conn->dev);
return OK; return OK;
} }
+2 -3
View File
@@ -331,9 +331,8 @@ ssize_t icmpv6_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
} }
} }
net_lock();
conn = psock->s_conn; conn = psock->s_conn;
conn_dev_lock(&conn->sconn, conn->dev);
if (psock->s_type != SOCK_RAW) if (psock->s_type != SOCK_RAW)
{ {
/* Get the device that was used to send the ICMPv6 request. */ /* Get the device that was used to send the ICMPv6 request. */
@@ -440,7 +439,7 @@ errout:
} }
} }
net_unlock(); conn_dev_unlock(&conn->sconn, conn->dev);
return ret; return ret;
} }
+2 -2
View File
@@ -98,7 +98,7 @@ void icmpv6_setaddresses(FAR struct net_driver_s *dev,
* using only the MAC address which is not being changed here. * using only the MAC address which is not being changed here.
*/ */
net_lock(); netdev_lock(dev);
/* Create an address mask from the prefix */ /* Create an address mask from the prefix */
@@ -152,7 +152,7 @@ void icmpv6_setaddresses(FAR struct net_driver_s *dev,
NTOHS(dev->d_ipv6draddr[4]), NTOHS(dev->d_ipv6draddr[5]), NTOHS(dev->d_ipv6draddr[4]), NTOHS(dev->d_ipv6draddr[5]),
NTOHS(dev->d_ipv6draddr[6]), NTOHS(dev->d_ipv6draddr[7])); NTOHS(dev->d_ipv6draddr[6]), NTOHS(dev->d_ipv6draddr[7]));
net_unlock(); netdev_unlock(dev);
} }
/**************************************************************************** /****************************************************************************
+4 -2
View File
@@ -377,7 +377,7 @@ ssize_t icmpv6_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
net_ipv6addr_copy(state.snd_toaddr.s6_addr16, net_ipv6addr_copy(state.snd_toaddr.s6_addr16,
inaddr->sin6_addr.s6_addr16); inaddr->sin6_addr.s6_addr16);
net_lock(); conn_dev_lock(&conn->sconn, dev);
/* Set up the callback */ /* Set up the callback */
@@ -405,8 +405,10 @@ ssize_t icmpv6_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
* net_sem_timedwait will also terminate if a signal is received. * net_sem_timedwait will also terminate if a signal is received.
*/ */
conn_dev_unlock(&conn->sconn, dev);
ret = net_sem_timedwait(&state.snd_sem, ret = net_sem_timedwait(&state.snd_sem,
_SO_TIMEOUT(conn->sconn.s_sndtimeo)); _SO_TIMEOUT(conn->sconn.s_sndtimeo));
conn_dev_lock(&conn->sconn, dev);
if (ret < 0) if (ret < 0)
{ {
if (ret == -ETIMEDOUT) if (ret == -ETIMEDOUT)
@@ -439,7 +441,7 @@ ssize_t icmpv6_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
nxsem_destroy(&state.snd_sem); nxsem_destroy(&state.snd_sem);
net_unlock(); conn_dev_unlock(&conn->sconn, dev);
/* Return the negated error number in the event of a failure, or the /* Return the negated error number in the event of a failure, or the
* number of bytes sent on success. * number of bytes sent on success.
+7 -4
View File
@@ -40,6 +40,7 @@
#include "icmpv6/icmpv6.h" #include "icmpv6/icmpv6.h"
#include "inet/inet.h" #include "inet/inet.h"
#include "utils/utils.h"
#ifdef CONFIG_NET_ICMPv6_SOCKET #ifdef CONFIG_NET_ICMPv6_SOCKET
@@ -143,6 +144,8 @@ static int icmpv6_setup(FAR struct socket *psock)
memset(&conn->filter, 0xff, sizeof(conn->filter)); memset(&conn->filter, 0xff, sizeof(conn->filter));
} }
nxmutex_init(&conn->sconn.s_lock);
/* Save the pre-allocated connection in the socket structure */ /* Save the pre-allocated connection in the socket structure */
psock->s_conn = conn; psock->s_conn = conn;
@@ -322,7 +325,6 @@ static int icmpv6_getsockopt_internal(FAR struct socket *psock, int option,
return -ENOPROTOOPT; return -ENOPROTOOPT;
} }
net_lock();
switch (option) switch (option)
{ {
case ICMP6_FILTER: case ICMP6_FILTER:
@@ -334,7 +336,9 @@ static int icmpv6_getsockopt_internal(FAR struct socket *psock, int option,
*value_len = sizeof(struct icmp6_filter); *value_len = sizeof(struct icmp6_filter);
} }
conn_lock(&conn->sconn);
memcpy(value, &conn->filter, *value_len); memcpy(value, &conn->filter, *value_len);
conn_unlock(&conn->sconn);
ret = OK; ret = OK;
} }
break; break;
@@ -345,7 +349,6 @@ static int icmpv6_getsockopt_internal(FAR struct socket *psock, int option,
break; break;
} }
net_unlock();
return ret; return ret;
} }
@@ -430,7 +433,6 @@ static int icmpv6_setsockopt_internal(FAR struct socket *psock, int option,
return -ENOPROTOOPT; return -ENOPROTOOPT;
} }
net_lock();
switch (option) switch (option)
{ {
case ICMP6_FILTER: case ICMP6_FILTER:
@@ -442,7 +444,9 @@ static int icmpv6_setsockopt_internal(FAR struct socket *psock, int option,
value_len = sizeof(struct icmp6_filter); value_len = sizeof(struct icmp6_filter);
} }
conn_lock(&conn->sconn);
memcpy(&conn->filter, value, value_len); memcpy(&conn->filter, value, value_len);
conn_unlock(&conn->sconn);
ret = OK; ret = OK;
} }
break; break;
@@ -453,7 +457,6 @@ static int icmpv6_setsockopt_internal(FAR struct socket *psock, int option,
break; break;
} }
net_unlock();
return ret; return ret;
} }