--- net/ipv6/addrconf.c.orig 2009-03-01 00:51:40.000000000 +0100 +++ net/ipv6/addrconf.c 2009-03-01 01:07:31.000000000 +0100 @@ -36,6 +36,8 @@ * YOSHIFUJI Hideaki @USAGI : improved source address * selection; consider scope, * status etc. + * Sascha Hlusiak isatap: assign linklocal + * addresses from link dev */ #include @@ -1556,13 +1558,6 @@ } EXPORT_SYMBOL(__ipv6_isatap_ifid); -static int addrconf_ifid_sit(u8 *eui, struct net_device *dev) -{ - if (dev->priv_flags & IFF_ISATAP) - return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr); - return -1; -} - static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) { switch (dev->type) { @@ -1574,8 +1569,6 @@ return addrconf_ifid_arcnet(eui, dev); case ARPHRD_INFINIBAND: return addrconf_ifid_infiniband(eui, dev); - case ARPHRD_SIT: - return addrconf_ifid_sit(eui, dev); } return -1; } @@ -2363,6 +2356,25 @@ } #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) +static void +isatap_add_v4_addrs(struct inet6_dev *idev, struct net_device *link_dev) +{ + struct in_device *in_dev = __in_dev_get_rtnl(link_dev); + struct in6_addr addr; + struct in_ifaddr *ifa; + + if (!link_dev->flags & IFF_UP) + return; + if (!in_dev) + return; + + for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { + ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); + if (!__ipv6_isatap_ifid(addr.s6_addr + 8, ifa->ifa_local)) + addrconf_add_linklocal(idev, &addr); + } +} + static void addrconf_sit_config(struct net_device *dev) { struct inet6_dev *idev; @@ -2382,11 +2394,23 @@ if (dev->priv_flags & IFF_ISATAP) { struct in6_addr addr; + struct net_device *link_dev; + struct net *net = dev_net(dev); ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); addrconf_prefix_route(&addr, 64, dev, 0, 0); - if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) - addrconf_add_linklocal(idev, &addr); + + if (*(__be32 *)dev->dev_addr) { + if (!__ipv6_isatap_ifid(addr.s6_addr + 8, + *(__be32 *)dev->dev_addr)) + addrconf_add_linklocal(idev, &addr); + } + /* Add all v4 addrs from the tunnel dev */ + if (idev->dev->iflink && + (link_dev = __dev_get_by_index(net, idev->dev->iflink))) { + isatap_add_v4_addrs(idev, link_dev); + } + return; }