diff options
author | David S. Miller <davem@davemloft.net> | 2008-03-27 21:48:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-27 21:48:56 -0400 |
commit | 8e8e43843ba3ced0c657cbc0fdb10644ec60f772 (patch) | |
tree | e64954326ced9c365c52c256f01b5f9fb1bcae66 /net/xfrm | |
parent | ed85f2c3b2b72bd20f617ac749f5c22be8d0f66e (diff) | |
parent | 50fd4407b8bfbde7c1a0bfe4f24de7df37164342 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/usb/rndis_host.c
drivers/net/wireless/b43/dma.c
net/ipv6/ndisc.c
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_input.c | 22 | ||||
-rw-r--r-- | net/xfrm/xfrm_output.c | 18 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 54 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 7 |
4 files changed, 85 insertions, 16 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 62188c6a06dd..75279402ccf4 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
@@ -84,14 +84,21 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) | |||
84 | 84 | ||
85 | int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) | 85 | int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) |
86 | { | 86 | { |
87 | struct xfrm_mode *inner_mode = x->inner_mode; | ||
87 | int err; | 88 | int err; |
88 | 89 | ||
89 | err = x->outer_mode->afinfo->extract_input(x, skb); | 90 | err = x->outer_mode->afinfo->extract_input(x, skb); |
90 | if (err) | 91 | if (err) |
91 | return err; | 92 | return err; |
92 | 93 | ||
93 | skb->protocol = x->inner_mode->afinfo->eth_proto; | 94 | if (x->sel.family == AF_UNSPEC) { |
94 | return x->inner_mode->input2(x, skb); | 95 | inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); |
96 | if (inner_mode == NULL) | ||
97 | return -EAFNOSUPPORT; | ||
98 | } | ||
99 | |||
100 | skb->protocol = inner_mode->afinfo->eth_proto; | ||
101 | return inner_mode->input2(x, skb); | ||
95 | } | 102 | } |
96 | EXPORT_SYMBOL(xfrm_prepare_input); | 103 | EXPORT_SYMBOL(xfrm_prepare_input); |
97 | 104 | ||
@@ -101,6 +108,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
101 | __be32 seq; | 108 | __be32 seq; |
102 | struct xfrm_state *x; | 109 | struct xfrm_state *x; |
103 | xfrm_address_t *daddr; | 110 | xfrm_address_t *daddr; |
111 | struct xfrm_mode *inner_mode; | ||
104 | unsigned int family; | 112 | unsigned int family; |
105 | int decaps = 0; | 113 | int decaps = 0; |
106 | int async = 0; | 114 | int async = 0; |
@@ -207,7 +215,15 @@ resume: | |||
207 | 215 | ||
208 | XFRM_MODE_SKB_CB(skb)->protocol = nexthdr; | 216 | XFRM_MODE_SKB_CB(skb)->protocol = nexthdr; |
209 | 217 | ||
210 | if (x->inner_mode->input(x, skb)) { | 218 | inner_mode = x->inner_mode; |
219 | |||
220 | if (x->sel.family == AF_UNSPEC) { | ||
221 | inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); | ||
222 | if (inner_mode == NULL) | ||
223 | goto drop; | ||
224 | } | ||
225 | |||
226 | if (inner_mode->input(x, skb)) { | ||
211 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMODEERROR); | 227 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMODEERROR); |
212 | goto drop; | 228 | goto drop; |
213 | } | 229 | } |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 569d377932c4..2519129c6d21 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -124,7 +124,7 @@ int xfrm_output_resume(struct sk_buff *skb, int err) | |||
124 | if (!x) | 124 | if (!x) |
125 | return dst_output(skb); | 125 | return dst_output(skb); |
126 | 126 | ||
127 | err = nf_hook(x->inner_mode->afinfo->family, | 127 | err = nf_hook(skb->dst->ops->family, |
128 | NF_INET_POST_ROUTING, skb, | 128 | NF_INET_POST_ROUTING, skb, |
129 | NULL, skb->dst->dev, xfrm_output2); | 129 | NULL, skb->dst->dev, xfrm_output2); |
130 | if (unlikely(err != 1)) | 130 | if (unlikely(err != 1)) |
@@ -193,4 +193,20 @@ int xfrm_output(struct sk_buff *skb) | |||
193 | 193 | ||
194 | return xfrm_output2(skb); | 194 | return xfrm_output2(skb); |
195 | } | 195 | } |
196 | |||
197 | int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb) | ||
198 | { | ||
199 | struct xfrm_mode *inner_mode; | ||
200 | if (x->sel.family == AF_UNSPEC) | ||
201 | inner_mode = xfrm_ip2inner_mode(x, | ||
202 | xfrm_af2proto(skb->dst->ops->family)); | ||
203 | else | ||
204 | inner_mode = x->inner_mode; | ||
205 | |||
206 | if (inner_mode == NULL) | ||
207 | return -EAFNOSUPPORT; | ||
208 | return inner_mode->afinfo->extract_output(x, skb); | ||
209 | } | ||
210 | |||
196 | EXPORT_SYMBOL_GPL(xfrm_output); | 211 | EXPORT_SYMBOL_GPL(xfrm_output); |
212 | EXPORT_SYMBOL_GPL(xfrm_inner_extract_output); | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 9880b792e6a5..5dcc10b93c86 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -389,6 +389,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
389 | kfree(x->coaddr); | 389 | kfree(x->coaddr); |
390 | if (x->inner_mode) | 390 | if (x->inner_mode) |
391 | xfrm_put_mode(x->inner_mode); | 391 | xfrm_put_mode(x->inner_mode); |
392 | if (x->inner_mode_iaf) | ||
393 | xfrm_put_mode(x->inner_mode_iaf); | ||
392 | if (x->outer_mode) | 394 | if (x->outer_mode) |
393 | xfrm_put_mode(x->outer_mode); | 395 | xfrm_put_mode(x->outer_mode); |
394 | if (x->type) { | 396 | if (x->type) { |
@@ -525,6 +527,8 @@ struct xfrm_state *xfrm_state_alloc(void) | |||
525 | x->lft.hard_packet_limit = XFRM_INF; | 527 | x->lft.hard_packet_limit = XFRM_INF; |
526 | x->replay_maxage = 0; | 528 | x->replay_maxage = 0; |
527 | x->replay_maxdiff = 0; | 529 | x->replay_maxdiff = 0; |
530 | x->inner_mode = NULL; | ||
531 | x->inner_mode_iaf = NULL; | ||
528 | spin_lock_init(&x->lock); | 532 | spin_lock_init(&x->lock); |
529 | } | 533 | } |
530 | return x; | 534 | return x; |
@@ -802,7 +806,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
802 | selector. | 806 | selector. |
803 | */ | 807 | */ |
804 | if (x->km.state == XFRM_STATE_VALID) { | 808 | if (x->km.state == XFRM_STATE_VALID) { |
805 | if (!xfrm_selector_match(&x->sel, fl, x->sel.family) || | 809 | if ((x->sel.family && !xfrm_selector_match(&x->sel, fl, x->sel.family)) || |
806 | !security_xfrm_state_pol_flow_match(x, pol, fl)) | 810 | !security_xfrm_state_pol_flow_match(x, pol, fl)) |
807 | continue; | 811 | continue; |
808 | if (!best || | 812 | if (!best || |
@@ -1963,6 +1967,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) | |||
1963 | int xfrm_init_state(struct xfrm_state *x) | 1967 | int xfrm_init_state(struct xfrm_state *x) |
1964 | { | 1968 | { |
1965 | struct xfrm_state_afinfo *afinfo; | 1969 | struct xfrm_state_afinfo *afinfo; |
1970 | struct xfrm_mode *inner_mode; | ||
1966 | int family = x->props.family; | 1971 | int family = x->props.family; |
1967 | int err; | 1972 | int err; |
1968 | 1973 | ||
@@ -1981,13 +1986,48 @@ int xfrm_init_state(struct xfrm_state *x) | |||
1981 | goto error; | 1986 | goto error; |
1982 | 1987 | ||
1983 | err = -EPROTONOSUPPORT; | 1988 | err = -EPROTONOSUPPORT; |
1984 | x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); | ||
1985 | if (x->inner_mode == NULL) | ||
1986 | goto error; | ||
1987 | 1989 | ||
1988 | if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | 1990 | if (x->sel.family != AF_UNSPEC) { |
1989 | family != x->sel.family) | 1991 | inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); |
1990 | goto error; | 1992 | if (inner_mode == NULL) |
1993 | goto error; | ||
1994 | |||
1995 | if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | ||
1996 | family != x->sel.family) { | ||
1997 | xfrm_put_mode(inner_mode); | ||
1998 | goto error; | ||
1999 | } | ||
2000 | |||
2001 | x->inner_mode = inner_mode; | ||
2002 | } else { | ||
2003 | struct xfrm_mode *inner_mode_iaf; | ||
2004 | |||
2005 | inner_mode = xfrm_get_mode(x->props.mode, AF_INET); | ||
2006 | if (inner_mode == NULL) | ||
2007 | goto error; | ||
2008 | |||
2009 | if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) { | ||
2010 | xfrm_put_mode(inner_mode); | ||
2011 | goto error; | ||
2012 | } | ||
2013 | |||
2014 | inner_mode_iaf = xfrm_get_mode(x->props.mode, AF_INET6); | ||
2015 | if (inner_mode_iaf == NULL) | ||
2016 | goto error; | ||
2017 | |||
2018 | if (!(inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)) { | ||
2019 | xfrm_put_mode(inner_mode_iaf); | ||
2020 | goto error; | ||
2021 | } | ||
2022 | |||
2023 | if (x->props.family == AF_INET) { | ||
2024 | x->inner_mode = inner_mode; | ||
2025 | x->inner_mode_iaf = inner_mode_iaf; | ||
2026 | } else { | ||
2027 | x->inner_mode = inner_mode_iaf; | ||
2028 | x->inner_mode_iaf = inner_mode; | ||
2029 | } | ||
2030 | } | ||
1991 | 2031 | ||
1992 | x->type = xfrm_get_type(x->id.proto, family); | 2032 | x->type = xfrm_get_type(x->id.proto, family); |
1993 | if (x->type == NULL) | 2033 | if (x->type == NULL) |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index f5fd5b3147cc..5578c909fcf6 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -288,12 +288,9 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * | |||
288 | memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); | 288 | memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); |
289 | x->props.flags = p->flags; | 289 | x->props.flags = p->flags; |
290 | 290 | ||
291 | /* | 291 | if (x->props.mode == XFRM_MODE_TRANSPORT) |
292 | * Set inner address family if the KM left it as zero. | ||
293 | * See comment in validate_tmpl. | ||
294 | */ | ||
295 | if (!x->sel.family) | ||
296 | x->sel.family = p->family; | 292 | x->sel.family = p->family; |
293 | |||
297 | } | 294 | } |
298 | 295 | ||
299 | /* | 296 | /* |