Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[linux] / net / ipv6 / ip6_tunnel.c
index 4b15fe9..da66aaa 100644 (file)
@@ -297,13 +297,16 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
        struct net_device *dev;
        struct ip6_tnl *t;
        char name[IFNAMSIZ];
-       int err = -ENOMEM;
+       int err = -E2BIG;
 
-       if (p->name[0])
+       if (p->name[0]) {
+               if (!dev_valid_name(p->name))
+                       goto failed;
                strlcpy(name, p->name, IFNAMSIZ);
-       else
+       } else {
                sprintf(name, "ip6tnl%%d");
-
+       }
+       err = -ENOMEM;
        dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN,
                           ip6_tnl_dev_setup);
        if (!dev)
@@ -679,7 +682,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
                /* Try to guess incoming interface */
                rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr,
-                               NULL, 0, 0);
+                               NULL, 0, skb2, 0);
 
                if (rt && rt->dst.dev)
                        skb2->dev = rt->dst.dev;
@@ -758,9 +761,11 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t,
                        ldev = dev_get_by_index_rcu(net, p->link);
 
                if ((ipv6_addr_is_multicast(laddr) ||
-                    likely(ipv6_chk_addr(net, laddr, ldev, 0))) &&
+                    likely(ipv6_chk_addr_and_flags(net, laddr, ldev, false,
+                                                   0, IFA_F_TENTATIVE))) &&
                    ((p->flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) ||
-                    likely(!ipv6_chk_addr(net, raddr, NULL, 0))))
+                    likely(!ipv6_chk_addr_and_flags(net, raddr, ldev, true,
+                                                    0, IFA_F_TENTATIVE))))
                        ret = 1;
        }
        return ret;
@@ -990,12 +995,14 @@ int ip6_tnl_xmit_ctl(struct ip6_tnl *t,
                if (p->link)
                        ldev = dev_get_by_index_rcu(net, p->link);
 
-               if (unlikely(!ipv6_chk_addr(net, laddr, ldev, 0)))
+               if (unlikely(!ipv6_chk_addr_and_flags(net, laddr, ldev, false,
+                                                     0, IFA_F_TENTATIVE)))
                        pr_warn("%s xmit: Local address not yet configured!\n",
                                p->name);
                else if (!(p->flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) &&
                         !ipv6_addr_is_multicast(raddr) &&
-                        unlikely(ipv6_chk_addr(net, raddr, NULL, 0)))
+                        unlikely(ipv6_chk_addr_and_flags(net, raddr, ldev,
+                                                         true, 0, IFA_F_TENTATIVE)))
                        pr_warn("%s xmit: Routing loop! Remote address found on this node!\n",
                                p->name);
                else
@@ -1444,7 +1451,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
 
                struct rt6_info *rt = rt6_lookup(t->net,
                                                 &p->raddr, &p->laddr,
-                                                p->link, strict);
+                                                p->link, NULL, strict);
 
                if (!rt)
                        return;
@@ -1982,14 +1989,14 @@ static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
 {
        struct net *net = dev_net(dev);
        struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
-       struct ip6_tnl *nt, *t;
        struct ip_tunnel_encap ipencap;
+       struct ip6_tnl *nt, *t;
+       int err;
 
        nt = netdev_priv(dev);
 
        if (ip6_tnl_netlink_encap_parms(data, &ipencap)) {
-               int err = ip6_tnl_encap_setup(nt, &ipencap);
-
+               err = ip6_tnl_encap_setup(nt, &ipencap);
                if (err < 0)
                        return err;
        }
@@ -2005,7 +2012,11 @@ static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
                        return -EEXIST;
        }
 
-       return ip6_tnl_create2(dev);
+       err = ip6_tnl_create2(dev);
+       if (!err && tb[IFLA_MTU])
+               ip6_tnl_change_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
+
+       return err;
 }
 
 static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
@@ -2201,6 +2212,8 @@ static int __net_init ip6_tnl_init_net(struct net *net)
        ip6n->tnls[0] = ip6n->tnls_wc;
        ip6n->tnls[1] = ip6n->tnls_r_l;
 
+       if (!net_has_fallback_tunnels(net))
+               return 0;
        err = -ENOMEM;
        ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0",
                                        NET_NAME_UNKNOWN, ip6_tnl_dev_setup);