net/icmpv6: Fix `icmpv6_neighbor` for link-local address

The netdev of link-local address cannot be auto decided, and the link-local address should always be reguarded as address on local network.

The problem we met:
When using `icmpv6_autoconfig` with multiple netdev, the `icmpv6_neighbor` may take out wrong netdev with ip address already set, then it may send solicitation with wrong address (`dev->d_ipv6draddr`) on wrong device, and regard the link-local address as conflict (because `dev->d_ipv6draddr` exists on this network).

Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
Zhe Weng 2023-08-10 11:43:27 +08:00 committed by Xiang Xiao
parent dffab1e0c6
commit d98bfc3e49
12 changed files with 26 additions and 16 deletions

View File

@ -205,6 +205,8 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen);
* ICMPv6 Neighbor Advertisement.
*
* Input Parameters:
* dev The suggested device driver structure to do the solicitation,
* can be NULL for auto decision, must set for link-local ipaddr.
* ipaddr The IPv6 address to be queried.
*
* Returned Value:
@ -221,9 +223,10 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen);
****************************************************************************/
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
int icmpv6_neighbor(const net_ipv6addr_t ipaddr);
int icmpv6_neighbor(FAR struct net_driver_s *dev,
const net_ipv6addr_t ipaddr);
#else
# define icmpv6_neighbor(i) (0)
# define icmpv6_neighbor(d,i) (0)
#endif
/****************************************************************************

View File

@ -332,7 +332,7 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
* method must be employed.
*/
ret = icmpv6_neighbor(lladdr);
ret = icmpv6_neighbor(dev, lladdr);
if (ret >= 0)
{
/* Hmmm... someone else responded to our Neighbor Solicitation. We

View File

@ -161,6 +161,8 @@ static uint16_t icmpv6_neighbor_eventhandler(FAR struct net_driver_s *dev,
* ICMPv6 Neighbor Advertisement.
*
* Input Parameters:
* dev The suggested device driver structure to do the solicitation,
* can be NULL for auto decision, must set for link-local ipaddr.
* ipaddr The IPv6 address to be queried.
*
* Returned Value:
@ -176,9 +178,9 @@ static uint16_t icmpv6_neighbor_eventhandler(FAR struct net_driver_s *dev,
*
****************************************************************************/
int icmpv6_neighbor(const net_ipv6addr_t ipaddr)
int icmpv6_neighbor(FAR struct net_driver_s *dev,
const net_ipv6addr_t ipaddr)
{
FAR struct net_driver_s *dev;
struct icmpv6_notify_s notify;
struct icmpv6_neighbor_s state;
net_ipv6addr_t lookup;
@ -202,7 +204,11 @@ int icmpv6_neighbor(const net_ipv6addr_t ipaddr)
/* Get the device that can route this request */
dev = netdev_findby_ripv6addr(g_ipv6_unspecaddr, ipaddr);
if (!dev)
{
dev = netdev_findby_ripv6addr(g_ipv6_unspecaddr, ipaddr);
}
if (!dev)
{
nerr("ERROR: Unreachable: %08lx\n", (unsigned long)ipaddr);
@ -212,7 +218,8 @@ int icmpv6_neighbor(const net_ipv6addr_t ipaddr)
/* Check if the destination address is on the local network. */
if (net_ipv6addr_maskcmp(ipaddr, dev->d_ipv6addr, dev->d_ipv6netmask))
if (net_ipv6addr_maskcmp(ipaddr, dev->d_ipv6addr, dev->d_ipv6netmask) ||
net_is_addr_linklocal(ipaddr))
{
/* Yes.. use the input address for the lookup */

View File

@ -338,7 +338,7 @@ ssize_t icmpv6_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
/* Make sure that the IP address mapping is in the Neighbor Table */
ret = icmpv6_neighbor(inaddr->sin6_addr.s6_addr16);
ret = icmpv6_neighbor(dev, inaddr->sin6_addr.s6_addr16);
if (ret < 0)
{
nerr("ERROR: Not reachable\n");

View File

@ -774,7 +774,7 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
/* Make sure that the IP address mapping is in the Neighbor Table */
ret = icmpv6_neighbor(conn->u.ipv6.raddr);
ret = icmpv6_neighbor(dev, conn->u.ipv6.raddr);
if (ret < 0)
{
nerr("ERROR: Not reachable\n");

View File

@ -213,7 +213,7 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
/* Make sure that the IP address mapping is in the Neighbor Table */
ret = icmpv6_neighbor(to6->sin6_addr.in6_u.u6_addr16);
ret = icmpv6_neighbor(dev, to6->sin6_addr.in6_u.u6_addr16);
if (ret < 0)
{
nerr("ERROR: Not reachable\n");

View File

@ -1494,7 +1494,7 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
{
/* Make sure that the IP address mapping is in the Neighbor Table */
ret = icmpv6_neighbor(conn->u.ipv6.raddr);
ret = icmpv6_neighbor(NULL, conn->u.ipv6.raddr);
}
#endif /* CONFIG_NET_ICMPv6_NEIGHBOR */

View File

@ -1299,7 +1299,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
{
/* Make sure that the IP address mapping is in the Neighbor Table */
ret = icmpv6_neighbor(conn->u.ipv6.raddr);
ret = icmpv6_neighbor(NULL, conn->u.ipv6.raddr);
}
#endif /* CONFIG_NET_ICMPv6_NEIGHBOR */

View File

@ -525,7 +525,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
{
/* Make sure that the IP address mapping is in the Neighbor Table */
ret = icmpv6_neighbor(conn->u.ipv6.raddr);
ret = icmpv6_neighbor(NULL, conn->u.ipv6.raddr);
}
#endif /* CONFIG_NET_ICMPv6_NEIGHBOR */

View File

@ -450,7 +450,7 @@ ssize_t tcp_sendfile(FAR struct socket *psock, FAR struct file *infile,
{
/* Make sure that the IP address mapping is in the Neighbor Table */
ret = icmpv6_neighbor(conn->u.ipv6.raddr);
ret = icmpv6_neighbor(NULL, conn->u.ipv6.raddr);
}
#endif /* CONFIG_NET_ICMPv6_NEIGHBOR */

View File

@ -651,7 +651,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
/* Make sure that the IP address mapping is in the Neighbor Table */
ret = icmpv6_neighbor(destipaddr);
ret = icmpv6_neighbor(NULL, destipaddr);
}
#endif /* CONFIG_NET_ICMPv6_NEIGHBOR */

View File

@ -382,7 +382,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
/* Make sure that the IP address mapping is in the Neighbor Table */
ret = icmpv6_neighbor(destipaddr);
ret = icmpv6_neighbor(NULL, destipaddr);
}
#endif /* CONFIG_NET_ICMPv6_NEIGHBOR */