diff options
Diffstat (limited to 'net/xfrm/xfrm_input.c')
| -rw-r--r-- | net/xfrm/xfrm_input.c | 22 |
1 files changed, 19 insertions, 3 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 | } |
