diff options
Diffstat (limited to 'net/xfrm/xfrm_state.c')
| -rw-r--r-- | net/xfrm/xfrm_state.c | 54 |
1 files changed, 47 insertions, 7 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 7ba65e82941c..58f1f9347b54 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -388,6 +388,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
| 388 | kfree(x->coaddr); | 388 | kfree(x->coaddr); |
| 389 | if (x->inner_mode) | 389 | if (x->inner_mode) |
| 390 | xfrm_put_mode(x->inner_mode); | 390 | xfrm_put_mode(x->inner_mode); |
| 391 | if (x->inner_mode_iaf) | ||
| 392 | xfrm_put_mode(x->inner_mode_iaf); | ||
| 391 | if (x->outer_mode) | 393 | if (x->outer_mode) |
| 392 | xfrm_put_mode(x->outer_mode); | 394 | xfrm_put_mode(x->outer_mode); |
| 393 | if (x->type) { | 395 | if (x->type) { |
| @@ -523,6 +525,8 @@ struct xfrm_state *xfrm_state_alloc(void) | |||
| 523 | x->lft.hard_packet_limit = XFRM_INF; | 525 | x->lft.hard_packet_limit = XFRM_INF; |
| 524 | x->replay_maxage = 0; | 526 | x->replay_maxage = 0; |
| 525 | x->replay_maxdiff = 0; | 527 | x->replay_maxdiff = 0; |
| 528 | x->inner_mode = NULL; | ||
| 529 | x->inner_mode_iaf = NULL; | ||
| 526 | spin_lock_init(&x->lock); | 530 | spin_lock_init(&x->lock); |
| 527 | } | 531 | } |
| 528 | return x; | 532 | return x; |
| @@ -796,7 +800,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
| 796 | selector. | 800 | selector. |
| 797 | */ | 801 | */ |
| 798 | if (x->km.state == XFRM_STATE_VALID) { | 802 | if (x->km.state == XFRM_STATE_VALID) { |
| 799 | if (!xfrm_selector_match(&x->sel, fl, x->sel.family) || | 803 | if ((x->sel.family && !xfrm_selector_match(&x->sel, fl, x->sel.family)) || |
| 800 | !security_xfrm_state_pol_flow_match(x, pol, fl)) | 804 | !security_xfrm_state_pol_flow_match(x, pol, fl)) |
| 801 | continue; | 805 | continue; |
| 802 | if (!best || | 806 | if (!best || |
| @@ -1944,6 +1948,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) | |||
| 1944 | int xfrm_init_state(struct xfrm_state *x) | 1948 | int xfrm_init_state(struct xfrm_state *x) |
| 1945 | { | 1949 | { |
| 1946 | struct xfrm_state_afinfo *afinfo; | 1950 | struct xfrm_state_afinfo *afinfo; |
| 1951 | struct xfrm_mode *inner_mode; | ||
| 1947 | int family = x->props.family; | 1952 | int family = x->props.family; |
| 1948 | int err; | 1953 | int err; |
| 1949 | 1954 | ||
| @@ -1962,13 +1967,48 @@ int xfrm_init_state(struct xfrm_state *x) | |||
| 1962 | goto error; | 1967 | goto error; |
| 1963 | 1968 | ||
| 1964 | err = -EPROTONOSUPPORT; | 1969 | err = -EPROTONOSUPPORT; |
| 1965 | x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); | ||
| 1966 | if (x->inner_mode == NULL) | ||
| 1967 | goto error; | ||
| 1968 | 1970 | ||
| 1969 | if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | 1971 | if (x->sel.family != AF_UNSPEC) { |
| 1970 | family != x->sel.family) | 1972 | inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); |
| 1971 | goto error; | 1973 | if (inner_mode == NULL) |
| 1974 | goto error; | ||
| 1975 | |||
| 1976 | if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | ||
| 1977 | family != x->sel.family) { | ||
| 1978 | xfrm_put_mode(inner_mode); | ||
| 1979 | goto error; | ||
| 1980 | } | ||
| 1981 | |||
| 1982 | x->inner_mode = inner_mode; | ||
| 1983 | } else { | ||
| 1984 | struct xfrm_mode *inner_mode_iaf; | ||
| 1985 | |||
| 1986 | inner_mode = xfrm_get_mode(x->props.mode, AF_INET); | ||
| 1987 | if (inner_mode == NULL) | ||
| 1988 | goto error; | ||
| 1989 | |||
| 1990 | if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) { | ||
| 1991 | xfrm_put_mode(inner_mode); | ||
| 1992 | goto error; | ||
| 1993 | } | ||
| 1994 | |||
| 1995 | inner_mode_iaf = xfrm_get_mode(x->props.mode, AF_INET6); | ||
| 1996 | if (inner_mode_iaf == NULL) | ||
| 1997 | goto error; | ||
| 1998 | |||
| 1999 | if (!(inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)) { | ||
| 2000 | xfrm_put_mode(inner_mode_iaf); | ||
| 2001 | goto error; | ||
| 2002 | } | ||
| 2003 | |||
| 2004 | if (x->props.family == AF_INET) { | ||
| 2005 | x->inner_mode = inner_mode; | ||
| 2006 | x->inner_mode_iaf = inner_mode_iaf; | ||
| 2007 | } else { | ||
| 2008 | x->inner_mode = inner_mode_iaf; | ||
| 2009 | x->inner_mode_iaf = inner_mode; | ||
| 2010 | } | ||
| 2011 | } | ||
| 1972 | 2012 | ||
| 1973 | x->type = xfrm_get_type(x->id.proto, family); | 2013 | x->type = xfrm_get_type(x->id.proto, family); |
| 1974 | if (x->type == NULL) | 2014 | if (x->type == NULL) |
