aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c54
1 files changed, 47 insertions, 7 deletions
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)
1963int xfrm_init_state(struct xfrm_state *x) 1967int 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)