diff options
author | Steffen Klassert <steffen.klassert@secunet.com> | 2014-02-21 02:41:08 -0500 |
---|---|---|
committer | Steffen Klassert <steffen.klassert@secunet.com> | 2014-02-25 01:04:16 -0500 |
commit | 3328715e6c1fcb10cd86b0f3212d18290b7e4463 (patch) | |
tree | 15ba89891638afb7075b5a5046d357c9263ac265 /net/xfrm/xfrm_input.c | |
parent | 51adfcc333e1490d3a22490f5b3504f64c7b28b4 (diff) |
xfrm4: Add IPsec protocol multiplexer
This patch add an IPsec protocol multiplexer. With this
it is possible to add alternative protocol handlers as
needed for IPsec virtual tunnel interfaces.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm/xfrm_input.c')
-rw-r--r-- | net/xfrm/xfrm_input.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 6c7ac016ce3a..99e3a9e5285e 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
@@ -108,7 +108,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
108 | int err; | 108 | int err; |
109 | __be32 seq; | 109 | __be32 seq; |
110 | __be32 seq_hi; | 110 | __be32 seq_hi; |
111 | struct xfrm_state *x; | 111 | struct xfrm_state *x = NULL; |
112 | xfrm_address_t *daddr; | 112 | xfrm_address_t *daddr; |
113 | struct xfrm_mode *inner_mode; | 113 | struct xfrm_mode *inner_mode; |
114 | unsigned int family; | 114 | unsigned int family; |
@@ -120,9 +120,14 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
120 | async = 1; | 120 | async = 1; |
121 | x = xfrm_input_state(skb); | 121 | x = xfrm_input_state(skb); |
122 | seq = XFRM_SKB_CB(skb)->seq.input.low; | 122 | seq = XFRM_SKB_CB(skb)->seq.input.low; |
123 | family = x->outer_mode->afinfo->family; | ||
123 | goto resume; | 124 | goto resume; |
124 | } | 125 | } |
125 | 126 | ||
127 | daddr = (xfrm_address_t *)(skb_network_header(skb) + | ||
128 | XFRM_SPI_SKB_CB(skb)->daddroff); | ||
129 | family = XFRM_SPI_SKB_CB(skb)->family; | ||
130 | |||
126 | /* Allocate new secpath or COW existing one. */ | 131 | /* Allocate new secpath or COW existing one. */ |
127 | if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { | 132 | if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { |
128 | struct sec_path *sp; | 133 | struct sec_path *sp; |
@@ -137,10 +142,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
137 | skb->sp = sp; | 142 | skb->sp = sp; |
138 | } | 143 | } |
139 | 144 | ||
140 | daddr = (xfrm_address_t *)(skb_network_header(skb) + | ||
141 | XFRM_SPI_SKB_CB(skb)->daddroff); | ||
142 | family = XFRM_SPI_SKB_CB(skb)->family; | ||
143 | |||
144 | seq = 0; | 145 | seq = 0; |
145 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) { | 146 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) { |
146 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); | 147 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
@@ -201,7 +202,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
201 | 202 | ||
202 | if (nexthdr == -EINPROGRESS) | 203 | if (nexthdr == -EINPROGRESS) |
203 | return 0; | 204 | return 0; |
204 | |||
205 | resume: | 205 | resume: |
206 | spin_lock(&x->lock); | 206 | spin_lock(&x->lock); |
207 | if (nexthdr <= 0) { | 207 | if (nexthdr <= 0) { |
@@ -263,6 +263,10 @@ resume: | |||
263 | } | 263 | } |
264 | } while (!err); | 264 | } while (!err); |
265 | 265 | ||
266 | err = xfrm_rcv_cb(skb, family, x->type->proto, 0); | ||
267 | if (err) | ||
268 | goto drop; | ||
269 | |||
266 | nf_reset(skb); | 270 | nf_reset(skb); |
267 | 271 | ||
268 | if (decaps) { | 272 | if (decaps) { |
@@ -276,6 +280,7 @@ resume: | |||
276 | drop_unlock: | 280 | drop_unlock: |
277 | spin_unlock(&x->lock); | 281 | spin_unlock(&x->lock); |
278 | drop: | 282 | drop: |
283 | xfrm_rcv_cb(skb, family, x && x->type ? x->type->proto : nexthdr, -1); | ||
279 | kfree_skb(skb); | 284 | kfree_skb(skb); |
280 | return 0; | 285 | return 0; |
281 | } | 286 | } |