]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/xfrm/xfrm_policy.c
Merge branch 'master' into upstream
[linux-2.6-omap-h63xx.git] / net / xfrm / xfrm_policy.c
index 1cf3209cdf4b371543ab53a1365766913082482e..b6e2e79d72612be4f99d82d3b8eb7027010c386b 100644 (file)
@@ -1107,6 +1107,20 @@ int __xfrm_sk_clone_policy(struct sock *sk)
        return 0;
 }
 
+static int
+xfrm_get_saddr(xfrm_address_t *local, xfrm_address_t *remote,
+              unsigned short family)
+{
+       int err;
+       struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+
+       if (unlikely(afinfo == NULL))
+               return -EINVAL;
+       err = afinfo->get_saddr(local, remote);
+       xfrm_policy_put_afinfo(afinfo);
+       return err;
+}
+
 /* Resolve list of templates for the flow, given policy. */
 
 static int
@@ -1118,6 +1132,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl,
        int i, error;
        xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family);
        xfrm_address_t *saddr = xfrm_flowi_saddr(fl, family);
+       xfrm_address_t tmp;
 
        for (nx=0, i = 0; i < policy->xfrm_nr; i++) {
                struct xfrm_state *x;
@@ -1128,6 +1143,12 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl,
                if (tmpl->mode == XFRM_MODE_TUNNEL) {
                        remote = &tmpl->id.daddr;
                        local = &tmpl->saddr;
+                       if (xfrm_addr_any(local, family)) {
+                               error = xfrm_get_saddr(&tmp, remote, family);
+                               if (error)
+                                       goto fail;
+                               local = &tmp;
+                       }
                }
 
                x = xfrm_state_find(remote, local, fl, tmpl, policy, &error, family);
@@ -1514,8 +1535,7 @@ static inline int secpath_has_nontransport(struct sec_path *sp, int k, int *idxp
 {
        for (; k < sp->len; k++) {
                if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT) {
-                       if (idxp)
-                               *idxp = k;
+                       *idxp = k;
                        return 1;
                }
        }
@@ -1534,7 +1554,6 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
        struct flowi fl;
        u8 fl_dir = policy_to_flow_dir(dir);
        int xerr_idx = -1;
-       int *xerr_idxp = &xerr_idx;
 
        if (xfrm_decode_session(skb, &fl, family) < 0)
                return 0;
@@ -1560,7 +1579,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                                        xfrm_policy_lookup);
 
        if (!pol) {
-               if (skb->sp && secpath_has_nontransport(skb->sp, 0, xerr_idxp)) {
+               if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) {
                        xfrm_secpath_reject(xerr_idx, skb, &fl);
                        return 0;
                }
@@ -1619,13 +1638,14 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
                        k = xfrm_policy_ok(tpp[i], sp, k, family);
                        if (k < 0) {
-                               if (k < -1 && xerr_idxp)
-                                       *xerr_idxp = -(2+k);
+                               if (k < -1)
+                                       /* "-2 - errored_index" returned */
+                                       xerr_idx = -(2+k);
                                goto reject;
                        }
                }
 
-               if (secpath_has_nontransport(sp, k, xerr_idxp))
+               if (secpath_has_nontransport(sp, k, &xerr_idx))
                        goto reject;
 
                xfrm_pols_put(pols, npols);
@@ -1985,10 +2005,8 @@ static void __init xfrm_policy_init(void)
 
        xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache",
                                           sizeof(struct xfrm_dst),
-                                          0, SLAB_HWCACHE_ALIGN,
+                                          0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
                                           NULL, NULL);
-       if (!xfrm_dst_cache)
-               panic("XFRM: failed to allocate xfrm_dst_cache\n");
 
        hmask = 8 - 1;
        sz = (hmask+1) * sizeof(struct hlist_head);