--- zzzz-none-000/linux-4.4.271/net/ipv6/addrconf.c 2021-06-03 06:22:09.000000000 +0000 +++ dakota-7530ac-750/linux-4.4.271/net/ipv6/addrconf.c 2023-01-11 09:25:44.000000000 +0000 @@ -1779,6 +1779,35 @@ return result; } +/* ipv6_dev_find() + * Find (and hold) net device that has the given address. + * Or NULL on failure. + */ +struct net_device *ipv6_dev_find(struct net *net, struct in6_addr *addr, + int strict) +{ + struct inet6_ifaddr *ifp; + struct net_device *dev; + + ifp = ipv6_get_ifaddr(net, addr, NULL, strict); + if (!ifp) + return NULL; + + if (!ifp->idev) { + in6_ifa_put(ifp); + return NULL; + } + + dev = ifp->idev->dev; + if (dev) + dev_hold(dev); + + in6_ifa_put(ifp); + + return dev; +} +EXPORT_SYMBOL(ipv6_dev_find); + /* Gets referenced address, destroys ifaddr */ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) @@ -2064,6 +2093,7 @@ case ARPHRD_IEEE1394: return addrconf_ifid_ieee1394(eui, dev); case ARPHRD_TUNNEL6: + case ARPHRD_RAWIP: return addrconf_ifid_ip6tnl(eui, dev); } return -1; @@ -3088,7 +3118,8 @@ (dev->type != ARPHRD_IEEE802154) && (dev->type != ARPHRD_IEEE1394) && (dev->type != ARPHRD_TUNNEL6) && - (dev->type != ARPHRD_6LOWPAN)) { + (dev->type != ARPHRD_6LOWPAN) && + (dev->type != ARPHRD_RAWIP)) { /* Alas, we support only Ethernet autoconfiguration. */ return; } @@ -3356,6 +3387,7 @@ struct net *net = dev_net(dev); struct inet6_dev *idev; struct inet6_ifaddr *ifa; + bool was_ready; int state, i; ASSERT_RTNL(); @@ -3402,7 +3434,10 @@ addrconf_del_rs_timer(idev); - /* Step 2: clear flags for stateless addrconf */ + /* Step 2: clear flags for stateless addrconf, repeated down + * detection + */ + was_ready = idev->if_flags & IF_READY; if (!how) idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); @@ -3455,7 +3490,7 @@ if (how) { ipv6_ac_destroy_dev(idev); ipv6_mc_destroy_dev(idev); - } else { + } else if (was_ready) { ipv6_mc_down(idev); }