Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[sfrench/cifs-2.6.git] / net / ipv6 / ip6_tunnel.c
index e528a42a52be2114e2e2df72519802faa4ce0aab..c1b1bd312df24d45ec46c10264ed669dc9c170a2 100644 (file)
@@ -536,7 +536,6 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        int err;
        struct sk_buff *skb2;
        struct iphdr *eiph;
-       struct flowi fl;
        struct rtable *rt;
 
        err = ip6_tnl_err(skb, IPPROTO_IPIP, opt, &rel_type, &rel_code,
@@ -578,11 +577,11 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        eiph = ip_hdr(skb2);
 
        /* Try to guess incoming interface */
-       memset(&fl, 0, sizeof(fl));
-       fl.fl4_dst = eiph->saddr;
-       fl.fl4_tos = RT_TOS(eiph->tos);
-       fl.proto = IPPROTO_IPIP;
-       if (ip_route_output_key(dev_net(skb->dev), &rt, &fl))
+       rt = ip_route_output_ports(dev_net(skb->dev), NULL,
+                                  eiph->saddr, 0,
+                                  0, 0,
+                                  IPPROTO_IPIP, RT_TOS(eiph->tos), 0);
+       if (IS_ERR(rt))
                goto out;
 
        skb2->dev = rt->dst.dev;
@@ -591,15 +590,18 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        if (rt->rt_flags & RTCF_LOCAL) {
                ip_rt_put(rt);
                rt = NULL;
-               fl.fl4_dst = eiph->daddr;
-               fl.fl4_src = eiph->saddr;
-               fl.fl4_tos = eiph->tos;
-               if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) ||
+               rt = ip_route_output_ports(dev_net(skb->dev), NULL,
+                                          eiph->daddr, eiph->saddr,
+                                          0, 0,
+                                          IPPROTO_IPIP,
+                                          RT_TOS(eiph->tos), 0);
+               if (IS_ERR(rt) ||
                    rt->dst.dev->type != ARPHRD_TUNNEL) {
-                       ip_rt_put(rt);
+                       if (!IS_ERR(rt))
+                               ip_rt_put(rt);
                        goto out;
                }
-               skb_dst_set(skb2, (struct dst_entry *)rt);
+               skb_dst_set(skb2, &rt->dst);
        } else {
                ip_rt_put(rt);
                if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos,
@@ -882,7 +884,7 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t)
 static int ip6_tnl_xmit2(struct sk_buff *skb,
                         struct net_device *dev,
                         __u8 dsfield,
-                        struct flowi *fl,
+                        struct flowi6 *fl6,
                         int encap_limit,
                         __u32 *pmtu)
 {
@@ -902,10 +904,16 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
        if ((dst = ip6_tnl_dst_check(t)) != NULL)
                dst_hold(dst);
        else {
-               dst = ip6_route_output(net, NULL, fl);
+               dst = ip6_route_output(net, NULL, fl6);
 
-               if (dst->error || xfrm_lookup(net, &dst, fl, NULL, 0) < 0)
+               if (dst->error)
                        goto tx_err_link_failure;
+               dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), NULL, 0);
+               if (IS_ERR(dst)) {
+                       err = PTR_ERR(dst);
+                       dst = NULL;
+                       goto tx_err_link_failure;
+               }
        }
 
        tdev = dst->dev;
@@ -955,7 +963,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
 
        skb->transport_header = skb->network_header;
 
-       proto = fl->proto;
+       proto = fl6->flowi6_proto;
        if (encap_limit >= 0) {
                init_tel_txopt(&opt, encap_limit);
                ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL);
@@ -963,13 +971,13 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
        skb_push(skb, sizeof(struct ipv6hdr));
        skb_reset_network_header(skb);
        ipv6h = ipv6_hdr(skb);
-       *(__be32*)ipv6h = fl->fl6_flowlabel | htonl(0x60000000);
+       *(__be32*)ipv6h = fl6->flowlabel | htonl(0x60000000);
        dsfield = INET_ECN_encapsulate(0, dsfield);
        ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield);
        ipv6h->hop_limit = t->parms.hop_limit;
        ipv6h->nexthdr = proto;
-       ipv6_addr_copy(&ipv6h->saddr, &fl->fl6_src);
-       ipv6_addr_copy(&ipv6h->daddr, &fl->fl6_dst);
+       ipv6_addr_copy(&ipv6h->saddr, &fl6->saddr);
+       ipv6_addr_copy(&ipv6h->daddr, &fl6->daddr);
        nf_reset(skb);
        pkt_len = skb->len;
        err = ip6_local_out(skb);
@@ -999,7 +1007,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        struct ip6_tnl *t = netdev_priv(dev);
        struct iphdr  *iph = ip_hdr(skb);
        int encap_limit = -1;
-       struct flowi fl;
+       struct flowi6 fl6;
        __u8 dsfield;
        __u32 mtu;
        int err;
@@ -1011,16 +1019,16 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
                encap_limit = t->parms.encap_limit;
 
-       memcpy(&fl, &t->fl, sizeof (fl));
-       fl.proto = IPPROTO_IPIP;
+       memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6));
+       fl6.flowi6_proto = IPPROTO_IPIP;
 
        dsfield = ipv4_get_dsfield(iph);
 
        if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS))
-               fl.fl6_flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
+               fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
                                          & IPV6_TCLASS_MASK;
 
-       err = ip6_tnl_xmit2(skb, dev, dsfield, &fl, encap_limit, &mtu);
+       err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
        if (err != 0) {
                /* XXX: send ICMP error even if DF is not set. */
                if (err == -EMSGSIZE)
@@ -1039,7 +1047,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        struct ipv6hdr *ipv6h = ipv6_hdr(skb);
        int encap_limit = -1;
        __u16 offset;
-       struct flowi fl;
+       struct flowi6 fl6;
        __u8 dsfield;
        __u32 mtu;
        int err;
@@ -1061,16 +1069,16 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
                encap_limit = t->parms.encap_limit;
 
-       memcpy(&fl, &t->fl, sizeof (fl));
-       fl.proto = IPPROTO_IPV6;
+       memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6));
+       fl6.flowi6_proto = IPPROTO_IPV6;
 
        dsfield = ipv6_get_dsfield(ipv6h);
        if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS))
-               fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK);
+               fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK);
        if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL))
-               fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK);
+               fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK);
 
-       err = ip6_tnl_xmit2(skb, dev, dsfield, &fl, encap_limit, &mtu);
+       err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
        if (err != 0) {
                if (err == -EMSGSIZE)
                        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
@@ -1133,21 +1141,21 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
 {
        struct net_device *dev = t->dev;
        struct ip6_tnl_parm *p = &t->parms;
-       struct flowi *fl = &t->fl;
+       struct flowi6 *fl6 = &t->fl.u.ip6;
 
        memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr));
        memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr));
 
        /* Set up flowi template */
-       ipv6_addr_copy(&fl->fl6_src, &p->laddr);
-       ipv6_addr_copy(&fl->fl6_dst, &p->raddr);
-       fl->oif = p->link;
-       fl->fl6_flowlabel = 0;
+       ipv6_addr_copy(&fl6->saddr, &p->laddr);
+       ipv6_addr_copy(&fl6->daddr, &p->raddr);
+       fl6->flowi6_oif = p->link;
+       fl6->flowlabel = 0;
 
        if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS))
-               fl->fl6_flowlabel |= IPV6_TCLASS_MASK & p->flowinfo;
+               fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo;
        if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL))
-               fl->fl6_flowlabel |= IPV6_FLOWLABEL_MASK & p->flowinfo;
+               fl6->flowlabel |= IPV6_FLOWLABEL_MASK & p->flowinfo;
 
        ip6_tnl_set_cap(t);