mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 11:56:10 +08:00
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:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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. */
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user