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:
parent
dffab1e0c6
commit
d98bfc3e49
@ -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
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user