static int snmp6_alloc_dev(struct inet6_dev *idev)
{
- int err = -ENOMEM;
-
- if (!idev || !idev->dev)
- return -EINVAL;
-
if (snmp_mib_init((void **)idev->stats.ipv6,
sizeof(struct ipstats_mib),
__alignof__(struct ipstats_mib)) < 0)
err_icmp:
snmp_mib_free((void **)idev->stats.ipv6);
err_ip:
- return err;
+ return -ENOMEM;
}
-static int snmp6_free_dev(struct inet6_dev *idev)
+static void snmp6_free_dev(struct inet6_dev *idev)
{
snmp_mib_free((void **)idev->stats.icmpv6msg);
snmp_mib_free((void **)idev->stats.icmpv6);
snmp_mib_free((void **)idev->stats.ipv6);
- return 0;
}
/* Nobody refers to this device, we may destroy it. */
in6_dev_hold(ndev);
#ifdef CONFIG_IPV6_PRIVACY
- init_timer(&ndev->regen_timer);
- ndev->regen_timer.function = ipv6_regen_rndid;
- ndev->regen_timer.data = (unsigned long) ndev;
+ setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev);
if ((dev->flags&IFF_LOOPBACK) ||
dev->type == ARPHRD_TUNNEL ||
#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
}
/* static matching label */
-static inline int ipv6_saddr_label(const struct in6_addr *addr, int type)
+static inline int ipv6_addr_label(const struct in6_addr *addr, int type,
+ int ifindex)
{
/*
* prefix (longest match) label
struct inet6_ifaddr *ifa_result = NULL;
int daddr_type = __ipv6_addr_type(daddr);
int daddr_scope = __ipv6_addr_src_scope(daddr_type);
- u32 daddr_label = ipv6_saddr_label(daddr, daddr_type);
+ int daddr_ifindex = daddr_dev ? daddr_dev->ifindex : 0;
+ u32 daddr_label = ipv6_addr_label(daddr, daddr_type, daddr_ifindex);
struct net_device *dev;
memset(&hiscore, 0, sizeof(hiscore));
if (unlikely(score.addr_type == IPV6_ADDR_ANY ||
score.addr_type & IPV6_ADDR_MULTICAST)) {
LIMIT_NETDEBUG(KERN_DEBUG
- "ADDRCONF: unspecified / multicast address"
+ "ADDRCONF: unspecified / multicast address "
"assigned as unicast address on %s",
dev->name);
continue;
/* Rule 6: Prefer matching label */
if (hiscore.rule < 6) {
- if (ipv6_saddr_label(&ifa_result->addr, hiscore.addr_type) == daddr_label)
+ if (ipv6_addr_label(&ifa_result->addr,
+ hiscore.addr_type,
+ ifa_result->idev->dev->ifindex) == daddr_label)
hiscore.attrs |= IPV6_SADDR_SCORE_LABEL;
hiscore.rule++;
}
- if (ipv6_saddr_label(&ifa->addr, score.addr_type) == daddr_label) {
+ if (ipv6_addr_label(&ifa->addr,
+ score.addr_type,
+ ifa->idev->dev->ifindex) == daddr_label) {
score.attrs |= IPV6_SADDR_SCORE_LABEL;
if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) {
score.rule = 6;
break;
}
+ if (!idev && dev->mtu >= IPV6_MIN_MTU)
+ idev = ipv6_add_dev(dev);
+
if (idev)
idev->if_flags |= IF_READY;
} else {
break;
case NETDEV_CHANGEMTU:
- if ( idev && dev->mtu >= IPV6_MIN_MTU) {
+ if (idev && dev->mtu >= IPV6_MIN_MTU) {
rt6_mtu_change(dev, dev->mtu);
idev->cnf.mtu6 = dev->mtu;
break;
}
+ if (!idev && dev->mtu >= IPV6_MIN_MTU) {
+ idev = ipv6_add_dev(dev);
+ if (idev)
+ break;
+ }
+
/* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */
case NETDEV_DOWN:
del_timer(&addr_chk_timer);
rtnl_unlock();
-
-#ifdef CONFIG_PROC_FS
- proc_net_remove(&init_net, "if_inet6");
-#endif
}