]> git.hungrycats.org Git - linux/commitdiff
[IPV6]: Autoconfig link-local address on ip6-ip6 tunnel device.
authorVille Nuorvala <vnourval@tcs.hut.fi>
Wed, 7 Jan 2004 04:17:51 +0000 (20:17 -0800)
committerDavid S. Miller <davem@nuts.ninka.net>
Wed, 7 Jan 2004 04:17:51 +0000 (20:17 -0800)
net/ipv6/addrconf.c
net/ipv6/ip6_tunnel.c

index 0d4b1688a8016edf579e305f569f2906b70b076c..17e1346baaff90fd2295e5775bc960cc1529591c 100644 (file)
@@ -1809,6 +1809,54 @@ static void addrconf_sit_config(struct net_device *dev)
                sit_route_add(dev);
 }
 
+static inline int
+ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
+{
+       struct in6_addr lladdr;
+
+       if (!ipv6_get_lladdr(link_dev, &lladdr)) {
+               addrconf_add_linklocal(idev, &lladdr);
+               return 0;
+       }
+       return -1;
+}
+
+static void ip6_tnl_add_linklocal(struct inet6_dev *idev)
+{
+       struct net_device *link_dev;
+
+       /* first try to inherit the link-local address from the link device */
+       if (idev->dev->iflink &&
+           (link_dev = __dev_get_by_index(idev->dev->iflink))) {
+               if (!ipv6_inherit_linklocal(idev, link_dev))
+                       return;
+       }
+       /* then try to inherit it from any device */
+       for (link_dev = dev_base; link_dev; link_dev = link_dev->next) {
+               if (!ipv6_inherit_linklocal(idev, link_dev))
+                       return;
+       }
+       printk(KERN_DEBUG "init ip6-ip6: add_linklocal failed\n");
+}
+
+/*
+ * Autoconfigure tunnel with a link-local address so routing protocols,
+ * DHCPv6, MLD etc. can be run over the virtual link
+ */
+
+static void addrconf_ip6_tnl_config(struct net_device *dev)
+{
+       struct inet6_dev *idev;
+
+       ASSERT_RTNL();
+
+       if ((idev = addrconf_add_dev(dev)) == NULL) {
+               printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n");
+               return;
+       }
+       ip6_tnl_add_linklocal(idev);
+       addrconf_add_mroute(dev);
+}
 
 int addrconf_notify(struct notifier_block *this, unsigned long event, 
                    void * data)
@@ -1822,7 +1870,9 @@ int addrconf_notify(struct notifier_block *this, unsigned long event,
                case ARPHRD_SIT:
                        addrconf_sit_config(dev);
                        break;
-
+               case ARPHRD_TUNNEL6:
+                       addrconf_ip6_tnl_config(dev);
+                       break;
                case ARPHRD_LOOPBACK:
                        init_loopback(dev);
                        break;
@@ -2121,6 +2171,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
         */
 
        if (ifp->idev->cnf.forwarding == 0 &&
+           ifp->idev->cnf.rtr_solicits > 0 &&
            (dev->flags&IFF_LOOPBACK) == 0 &&
            (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
                struct in6_addr all_routers;
index 148c6151087085542df1a599f66516bb3bd56640..7f02c1901e9dcf213bee27bb0e29d3eb579602ff 100644 (file)
@@ -821,6 +821,8 @@ static void ip6ip6_tnl_link_config(struct ip6_tnl *t)
        else
                dev->flags &= ~IFF_POINTOPOINT;
 
+       dev->iflink = p->link;
+
        if (p->flags & IP6_TNL_F_CAP_XMIT) {
                struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr,
                                                 p->link, 0);
@@ -829,8 +831,6 @@ static void ip6ip6_tnl_link_config(struct ip6_tnl *t)
                        return;
 
                if (rt->rt6i_dev) {
-                       dev->iflink = rt->rt6i_dev->ifindex;
-
                        dev->hard_header_len = rt->rt6i_dev->hard_header_len +
                                sizeof (struct ipv6hdr);
 
@@ -1040,7 +1040,6 @@ static void ip6ip6_tnl_dev_setup(struct net_device *dev)
        dev->hard_header_len = LL_MAX_HEADER + sizeof (struct ipv6hdr);
        dev->mtu = ETH_DATA_LEN - sizeof (struct ipv6hdr);
        dev->flags |= IFF_NOARP;
-       dev->iflink = 0;
        dev->addr_len = sizeof(struct in6_addr);
 }