[IPSEC]: Rename mode to outer_mode and add inner_mode
authorHerbert Xu <herbert@gondor.apana.org.au>
Thu, 18 Oct 2007 04:35:51 +0000 (21:35 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 18 Oct 2007 04:35:51 +0000 (21:35 -0700)
This patch adds a new field to xfrm states called inner_mode.  The existing
mode object is renamed to outer_mode.

This is the first part of an attempt to fix inter-family transforms.  As it
is we always use the outer family when determining which mode to use.  As a
result we may end up shoving IPv4 packets into netfilter6 and vice versa.

What we really want is to use the inner family for the first part of outbound
processing and the outer family for the second part.  For inbound processing
we'd use the opposite pairing.

I've also added a check to prevent silly combinations such as transport mode
with inter-family transforms.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/xfrm.h
net/core/pktgen.c
net/ipv4/xfrm4_input.c
net/ipv4/xfrm4_output.c
net/ipv4/xfrm4_policy.c
net/ipv6/xfrm6_input.c
net/ipv6/xfrm6_output.c
net/ipv6/xfrm6_policy.c
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c

index f0f3318f6550e45f55c9b8f77f7d5f4999901ad3..688f6f5d3285bf1cc6ae88850c7008ff1fd6d5a2 100644 (file)
@@ -186,7 +186,8 @@ struct xfrm_state
        /* Reference to data common to all the instances of this
         * transformer. */
        struct xfrm_type        *type;
-       struct xfrm_mode        *mode;
+       struct xfrm_mode        *inner_mode;
+       struct xfrm_mode        *outer_mode;
 
        /* Security context */
        struct xfrm_sec_ctx     *security;
index 2100c734b102c9bde14ef3e86a362621996f37b9..8cae60c5338304f17cc6f59197c6bb447229b3eb 100644 (file)
@@ -2454,7 +2454,7 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
        spin_lock(&x->lock);
        iph = ip_hdr(skb);
 
-       err = x->mode->output(x, skb);
+       err = x->outer_mode->output(x, skb);
        if (err)
                goto error;
        err = x->type->output(x, skb);
index bc5dc0747cd2eb6423ba460f3891d3303d0d844e..5e95c8a07efbad59809f5370c62b317b58e1fe9c 100644 (file)
@@ -91,10 +91,10 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
 
                xfrm_vec[xfrm_nr++] = x;
 
-               if (x->mode->input(x, skb))
+               if (x->outer_mode->input(x, skb))
                        goto drop;
 
-               if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) {
+               if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
                        decaps = 1;
                        break;
                }
index dcbc2743069c9d1c6f7d485d72b738ff90ee6a63..c4a7156962bd58797d93b7c21051bcc797c98de9 100644 (file)
@@ -47,7 +47,7 @@ static inline int xfrm4_output_one(struct sk_buff *skb)
        struct iphdr *iph;
        int err;
 
-       if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) {
+       if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
                err = xfrm4_tunnel_check_size(skb);
                if (err)
                        goto error_nolock;
index 1f0ea0e0371bb172feeacd135590e5faf2a1a641..cc86fb110dd882050848053e94406d6870803a01 100644 (file)
@@ -168,7 +168,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
                /* Copy neighbout for reachability confirmation */
                dst_prev->neighbour     = neigh_clone(rt->u.dst.neighbour);
                dst_prev->input         = rt->u.dst.input;
-               dst_prev->output = dst_prev->xfrm->mode->afinfo->output;
+               dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output;
                if (rt0->peer)
                        atomic_inc(&rt0->peer->refcnt);
                x->u.rt.peer = rt0->peer;
index c6ee1a3ba19a4ed93c0b1e620efb749663631211..515783707e86b0338d003dab53fe9b2310652aa3 100644 (file)
@@ -68,10 +68,10 @@ int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
 
                xfrm_vec[xfrm_nr++] = x;
 
-               if (x->mode->input(x, skb))
+               if (x->outer_mode->input(x, skb))
                        goto drop;
 
-               if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) {
+               if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
                        decaps = 1;
                        break;
                }
index c9f42d1c2dff9be5c1f291396e51e8e152d67c3e..656976760ad47175afa8bc6ac7d2152d5e7f95b4 100644 (file)
@@ -50,7 +50,7 @@ static inline int xfrm6_output_one(struct sk_buff *skb)
        struct ipv6hdr *iph;
        int err;
 
-       if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) {
+       if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
                err = xfrm6_tunnel_check_size(skb);
                if (err)
                        goto error_nolock;
index 324268329f698d80e0f8110e720ad13b6a08d226..82e27b80d07d3d060112eb873d7b0a9774853cba 100644 (file)
@@ -230,7 +230,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
                /* Copy neighbour for reachability confirmation */
                dst_prev->neighbour     = neigh_clone(rt->u.dst.neighbour);
                dst_prev->input         = rt->u.dst.input;
-               dst_prev->output = dst_prev->xfrm->mode->afinfo->output;
+               dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output;
                /* Sheit... I remember I did this right. Apparently,
                 * it was magically lost, so this code needs audit */
                x->u.rt6.rt6i_flags    = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
index 8bf71ba2345f36006b6745ab940e46e45ed3064f..f4bfd6c4565119f9f3be6cb80547922b930b4f73 100644 (file)
@@ -63,7 +63,7 @@ int xfrm_output(struct sk_buff *skb)
                                xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
                }
 
-               err = x->mode->output(x, skb);
+               err = x->outer_mode->output(x, skb);
                if (err)
                        goto error;
 
@@ -82,7 +82,7 @@ int xfrm_output(struct sk_buff *skb)
                }
                dst = skb->dst;
                x = dst->xfrm;
-       } while (x && !(x->mode->flags & XFRM_MODE_FLAG_TUNNEL));
+       } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
 
        err = 0;
 
index 1d66fb42c9cbe87f81b56fd5e5de06fbcd9c096e..b702bd8a3893b7f2471df1c23df25a7105da70da 100644 (file)
@@ -1941,7 +1941,7 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
                        return 0;
 
                if (strict && fl &&
-                   !(dst->xfrm->mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
+                   !(dst->xfrm->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
                    !xfrm_state_addr_flow_check(dst->xfrm, fl, family))
                        return 0;
 
index 48b4a06b3d1a2e15138231055e0e92817440ea8c..224b44e31a07b934091f79e42b85888ab143925f 100644 (file)
@@ -377,8 +377,10 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
        kfree(x->calg);
        kfree(x->encap);
        kfree(x->coaddr);
-       if (x->mode)
-               xfrm_put_mode(x->mode);
+       if (x->inner_mode)
+               xfrm_put_mode(x->inner_mode);
+       if (x->outer_mode)
+               xfrm_put_mode(x->outer_mode);
        if (x->type) {
                x->type->destructor(x);
                xfrm_put_type(x->type);
@@ -1947,6 +1949,14 @@ int xfrm_init_state(struct xfrm_state *x)
                goto error;
 
        err = -EPROTONOSUPPORT;
+       x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family);
+       if (x->inner_mode == NULL)
+               goto error;
+
+       if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
+           family != x->sel.family)
+               goto error;
+
        x->type = xfrm_get_type(x->id.proto, family);
        if (x->type == NULL)
                goto error;
@@ -1955,8 +1965,8 @@ int xfrm_init_state(struct xfrm_state *x)
        if (err)
                goto error;
 
-       x->mode = xfrm_get_mode(x->props.mode, family);
-       if (x->mode == NULL)
+       x->outer_mode = xfrm_get_mode(x->props.mode, family);
+       if (x->outer_mode == NULL)
                goto error;
 
        x->km.state = XFRM_STATE_VALID;