aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-10-18 00:35:51 -0400
committerDavid S. Miller <davem@davemloft.net>2007-10-18 00:35:51 -0400
commit13996378e6585fb25e582afe7489bf52dde78deb (patch)
tree4a1eb75c81a5a9d23c68f9818259f3b357dc8265
parentca68145f16359f71cd62b2671aa3e8c58f45ef19 (diff)
[IPSEC]: Rename mode to outer_mode and add inner_mode
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>
-rw-r--r--include/net/xfrm.h3
-rw-r--r--net/core/pktgen.c2
-rw-r--r--net/ipv4/xfrm4_input.c4
-rw-r--r--net/ipv4/xfrm4_output.c2
-rw-r--r--net/ipv4/xfrm4_policy.c2
-rw-r--r--net/ipv6/xfrm6_input.c4
-rw-r--r--net/ipv6/xfrm6_output.c2
-rw-r--r--net/ipv6/xfrm6_policy.c2
-rw-r--r--net/xfrm/xfrm_output.c4
-rw-r--r--net/xfrm/xfrm_policy.c2
-rw-r--r--net/xfrm/xfrm_state.c18
11 files changed, 28 insertions, 17 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index f0f3318f6550..688f6f5d3285 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -186,7 +186,8 @@ struct xfrm_state
186 /* Reference to data common to all the instances of this 186 /* Reference to data common to all the instances of this
187 * transformer. */ 187 * transformer. */
188 struct xfrm_type *type; 188 struct xfrm_type *type;
189 struct xfrm_mode *mode; 189 struct xfrm_mode *inner_mode;
190 struct xfrm_mode *outer_mode;
190 191
191 /* Security context */ 192 /* Security context */
192 struct xfrm_sec_ctx *security; 193 struct xfrm_sec_ctx *security;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 2100c734b102..8cae60c53383 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2454,7 +2454,7 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
2454 spin_lock(&x->lock); 2454 spin_lock(&x->lock);
2455 iph = ip_hdr(skb); 2455 iph = ip_hdr(skb);
2456 2456
2457 err = x->mode->output(x, skb); 2457 err = x->outer_mode->output(x, skb);
2458 if (err) 2458 if (err)
2459 goto error; 2459 goto error;
2460 err = x->type->output(x, skb); 2460 err = x->type->output(x, skb);
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index bc5dc0747cd2..5e95c8a07efb 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -91,10 +91,10 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
91 91
92 xfrm_vec[xfrm_nr++] = x; 92 xfrm_vec[xfrm_nr++] = x;
93 93
94 if (x->mode->input(x, skb)) 94 if (x->outer_mode->input(x, skb))
95 goto drop; 95 goto drop;
96 96
97 if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) { 97 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
98 decaps = 1; 98 decaps = 1;
99 break; 99 break;
100 } 100 }
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index dcbc2743069c..c4a7156962bd 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -47,7 +47,7 @@ static inline int xfrm4_output_one(struct sk_buff *skb)
47 struct iphdr *iph; 47 struct iphdr *iph;
48 int err; 48 int err;
49 49
50 if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) { 50 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
51 err = xfrm4_tunnel_check_size(skb); 51 err = xfrm4_tunnel_check_size(skb);
52 if (err) 52 if (err)
53 goto error_nolock; 53 goto error_nolock;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 1f0ea0e0371b..cc86fb110dd8 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -168,7 +168,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
168 /* Copy neighbout for reachability confirmation */ 168 /* Copy neighbout for reachability confirmation */
169 dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); 169 dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
170 dst_prev->input = rt->u.dst.input; 170 dst_prev->input = rt->u.dst.input;
171 dst_prev->output = dst_prev->xfrm->mode->afinfo->output; 171 dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output;
172 if (rt0->peer) 172 if (rt0->peer)
173 atomic_inc(&rt0->peer->refcnt); 173 atomic_inc(&rt0->peer->refcnt);
174 x->u.rt.peer = rt0->peer; 174 x->u.rt.peer = rt0->peer;
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index c6ee1a3ba19a..515783707e86 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -68,10 +68,10 @@ int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
68 68
69 xfrm_vec[xfrm_nr++] = x; 69 xfrm_vec[xfrm_nr++] = x;
70 70
71 if (x->mode->input(x, skb)) 71 if (x->outer_mode->input(x, skb))
72 goto drop; 72 goto drop;
73 73
74 if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) { 74 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
75 decaps = 1; 75 decaps = 1;
76 break; 76 break;
77 } 77 }
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index c9f42d1c2dff..656976760ad4 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -50,7 +50,7 @@ static inline int xfrm6_output_one(struct sk_buff *skb)
50 struct ipv6hdr *iph; 50 struct ipv6hdr *iph;
51 int err; 51 int err;
52 52
53 if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) { 53 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
54 err = xfrm6_tunnel_check_size(skb); 54 err = xfrm6_tunnel_check_size(skb);
55 if (err) 55 if (err)
56 goto error_nolock; 56 goto error_nolock;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 324268329f69..82e27b80d07d 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -230,7 +230,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
230 /* Copy neighbour for reachability confirmation */ 230 /* Copy neighbour for reachability confirmation */
231 dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); 231 dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
232 dst_prev->input = rt->u.dst.input; 232 dst_prev->input = rt->u.dst.input;
233 dst_prev->output = dst_prev->xfrm->mode->afinfo->output; 233 dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output;
234 /* Sheit... I remember I did this right. Apparently, 234 /* Sheit... I remember I did this right. Apparently,
235 * it was magically lost, so this code needs audit */ 235 * it was magically lost, so this code needs audit */
236 x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL); 236 x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 8bf71ba2345f..f4bfd6c45651 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -63,7 +63,7 @@ int xfrm_output(struct sk_buff *skb)
63 xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); 63 xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
64 } 64 }
65 65
66 err = x->mode->output(x, skb); 66 err = x->outer_mode->output(x, skb);
67 if (err) 67 if (err)
68 goto error; 68 goto error;
69 69
@@ -82,7 +82,7 @@ int xfrm_output(struct sk_buff *skb)
82 } 82 }
83 dst = skb->dst; 83 dst = skb->dst;
84 x = dst->xfrm; 84 x = dst->xfrm;
85 } while (x && !(x->mode->flags & XFRM_MODE_FLAG_TUNNEL)); 85 } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
86 86
87 err = 0; 87 err = 0;
88 88
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 1d66fb42c9cb..b702bd8a3893 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1941,7 +1941,7 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
1941 return 0; 1941 return 0;
1942 1942
1943 if (strict && fl && 1943 if (strict && fl &&
1944 !(dst->xfrm->mode->flags & XFRM_MODE_FLAG_TUNNEL) && 1944 !(dst->xfrm->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
1945 !xfrm_state_addr_flow_check(dst->xfrm, fl, family)) 1945 !xfrm_state_addr_flow_check(dst->xfrm, fl, family))
1946 return 0; 1946 return 0;
1947 1947
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 48b4a06b3d1a..224b44e31a07 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -377,8 +377,10 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
377 kfree(x->calg); 377 kfree(x->calg);
378 kfree(x->encap); 378 kfree(x->encap);
379 kfree(x->coaddr); 379 kfree(x->coaddr);
380 if (x->mode) 380 if (x->inner_mode)
381 xfrm_put_mode(x->mode); 381 xfrm_put_mode(x->inner_mode);
382 if (x->outer_mode)
383 xfrm_put_mode(x->outer_mode);
382 if (x->type) { 384 if (x->type) {
383 x->type->destructor(x); 385 x->type->destructor(x);
384 xfrm_put_type(x->type); 386 xfrm_put_type(x->type);
@@ -1947,6 +1949,14 @@ int xfrm_init_state(struct xfrm_state *x)
1947 goto error; 1949 goto error;
1948 1950
1949 err = -EPROTONOSUPPORT; 1951 err = -EPROTONOSUPPORT;
1952 x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family);
1953 if (x->inner_mode == NULL)
1954 goto error;
1955
1956 if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
1957 family != x->sel.family)
1958 goto error;
1959
1950 x->type = xfrm_get_type(x->id.proto, family); 1960 x->type = xfrm_get_type(x->id.proto, family);
1951 if (x->type == NULL) 1961 if (x->type == NULL)
1952 goto error; 1962 goto error;
@@ -1955,8 +1965,8 @@ int xfrm_init_state(struct xfrm_state *x)
1955 if (err) 1965 if (err)
1956 goto error; 1966 goto error;
1957 1967
1958 x->mode = xfrm_get_mode(x->props.mode, family); 1968 x->outer_mode = xfrm_get_mode(x->props.mode, family);
1959 if (x->mode == NULL) 1969 if (x->outer_mode == NULL)
1960 goto error; 1970 goto error;
1961 1971
1962 x->km.state = XFRM_STATE_VALID; 1972 x->km.state = XFRM_STATE_VALID;