]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/xfrm/xfrm_policy.c
xfrm: Return dst directly from xfrm_lookup()
[mirror_ubuntu-artful-kernel.git] / net / xfrm / xfrm_policy.c
index 0248afa11cdaa8227ceeba5746c2a79bf1fb6a94..b1932a629ef8e4213635c8ac57e321f5e452d3b4 100644 (file)
@@ -1757,14 +1757,14 @@ static struct dst_entry *make_blackhole(struct net *net, u16 family,
  * At the moment we eat a raw IP route. Mostly to speed up lookups
  * on interfaces with disabled IPsec.
  */
-int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
-               const struct flowi *fl,
-               struct sock *sk, int flags)
+struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
+                             const struct flowi *fl,
+                             struct sock *sk, int flags)
 {
        struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
        struct flow_cache_object *flo;
        struct xfrm_dst *xdst;
-       struct dst_entry *dst, *dst_orig = *dst_p, *route;
+       struct dst_entry *dst, *route;
        u16 family = dst_orig->ops->family;
        u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
        int i, err, num_pols, num_xfrms = 0, drop_pols = 0;
@@ -1847,11 +1847,7 @@ restart:
                        xfrm_pols_put(pols, drop_pols);
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
 
-                       dst = make_blackhole(net, family, dst_orig);
-                       if (IS_ERR(dst))
-                               return PTR_ERR(dst);
-                       *dst_p = dst;
-                       return 0;
+                       return make_blackhole(net, family, dst_orig);
                }
                if (fl->flags & FLOWI_FLAG_CAN_SLEEP) {
                        DECLARE_WAITQUEUE(wait, current);
@@ -1895,27 +1891,28 @@ no_transform:
                goto error;
        } else if (num_xfrms > 0) {
                /* Flow transformed */
-               *dst_p = dst;
                dst_release(dst_orig);
        } else {
                /* Flow passes untransformed */
                dst_release(dst);
+               dst = dst_orig;
        }
 ok:
        xfrm_pols_put(pols, drop_pols);
-       return 0;
+       return dst;
 
 nopol:
-       if (!(flags & XFRM_LOOKUP_ICMP))
+       if (!(flags & XFRM_LOOKUP_ICMP)) {
+               dst = dst_orig;
                goto ok;
+       }
        err = -ENOENT;
 error:
        dst_release(dst);
 dropdst:
        dst_release(dst_orig);
-       *dst_p = NULL;
        xfrm_pols_put(pols, drop_pols);
-       return err;
+       return ERR_PTR(err);
 }
 EXPORT_SYMBOL(xfrm_lookup);
 
@@ -2175,7 +2172,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
        struct net *net = dev_net(skb->dev);
        struct flowi fl;
        struct dst_entry *dst;
-       int res;
+       int res = 0;
 
        if (xfrm_decode_session(skb, &fl, family) < 0) {
                XFRM_INC_STATS(net, LINUX_MIB_XFRMFWDHDRERROR);
@@ -2183,9 +2180,12 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
        }
 
        skb_dst_force(skb);
-       dst = skb_dst(skb);
 
-       res = xfrm_lookup(net, &dst, &fl, NULL, 0) == 0;
+       dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, 0);
+       if (IS_ERR(dst)) {
+               res = 1;
+               dst = NULL;
+       }
        skb_dst_set(skb, dst);
        return res;
 }