From d5991ced12962a31a7f4354a8e23fd13823a8639 Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Tue, 6 Jan 2004 20:17:51 -0800 Subject: [PATCH] [IPV6]: Autoconfig link-local address on ip6-ip6 tunnel device. --- net/ipv6/addrconf.c | 53 ++++++++++++++++++++++++++++++++++++++++++- net/ipv6/ip6_tunnel.c | 5 ++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 0d4b1688a8016..17e1346baaff9 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -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; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 148c615108708..7f02c1901e9dc 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -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); } -- 2.53.0