Blame view
net/xfrm/xfrm_input.c
12.6 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 |
/* * xfrm_input.c * * Changes: * YOSHIFUJI Hideaki @USAGI * Split up af-specific portion |
a716c1197 [NET] XFRM: Fix w... |
8 |
* |
1da177e4c Linux-2.6.12-rc2 |
9 |
*/ |
e095ecaec xfrm: Reinject tr... |
10 11 |
#include <linux/bottom_half.h> #include <linux/interrupt.h> |
1da177e4c Linux-2.6.12-rc2 |
12 13 |
#include <linux/slab.h> #include <linux/module.h> |
716062fd4 [IPSEC]: Merge mo... |
14 |
#include <linux/netdevice.h> |
e095ecaec xfrm: Reinject tr... |
15 |
#include <linux/percpu.h> |
716062fd4 [IPSEC]: Merge mo... |
16 |
#include <net/dst.h> |
1da177e4c Linux-2.6.12-rc2 |
17 18 |
#include <net/ip.h> #include <net/xfrm.h> |
049f8e2e2 xfrm: Override sk... |
19 20 |
#include <net/ip_tunnels.h> #include <net/ip6_tunnel.h> |
1da177e4c Linux-2.6.12-rc2 |
21 |
|
e095ecaec xfrm: Reinject tr... |
22 23 24 25 26 27 |
struct xfrm_trans_tasklet { struct tasklet_struct tasklet; struct sk_buff_head queue; }; struct xfrm_trans_cb { |
58be6253b xfrm: Fix transpo... |
28 29 30 31 32 33 |
union { struct inet_skb_parm h4; #if IS_ENABLED(CONFIG_IPV6) struct inet6_skb_parm h6; #endif } header; |
e095ecaec xfrm: Reinject tr... |
34 35 36 37 |
int (*finish)(struct net *net, struct sock *sk, struct sk_buff *skb); }; #define XFRM_TRANS_SKB_CB(__skb) ((struct xfrm_trans_cb *)&((__skb)->cb[0])) |
e18b890bb [PATCH] slab: rem... |
38 |
static struct kmem_cache *secpath_cachep __read_mostly; |
1da177e4c Linux-2.6.12-rc2 |
39 |
|
2f32b51b6 xfrm: Introduce x... |
40 |
static DEFINE_SPINLOCK(xfrm_input_afinfo_lock); |
960fdfdeb xfrm: input: cons... |
41 |
static struct xfrm_input_afinfo const __rcu *xfrm_input_afinfo[AF_INET6 + 1]; |
2f32b51b6 xfrm: Introduce x... |
42 |
|
1995876a0 xfrm: Add a dummy... |
43 44 |
static struct gro_cells gro_cells; static struct net_device xfrm_napi_dev; |
e095ecaec xfrm: Reinject tr... |
45 |
static DEFINE_PER_CPU(struct xfrm_trans_tasklet, xfrm_trans_tasklet); |
960fdfdeb xfrm: input: cons... |
46 |
int xfrm_input_register_afinfo(const struct xfrm_input_afinfo *afinfo) |
2f32b51b6 xfrm: Introduce x... |
47 48 |
{ int err = 0; |
960fdfdeb xfrm: input: cons... |
49 |
if (WARN_ON(afinfo->family >= ARRAY_SIZE(xfrm_input_afinfo))) |
2f32b51b6 xfrm: Introduce x... |
50 |
return -EAFNOSUPPORT; |
960fdfdeb xfrm: input: cons... |
51 |
|
2f32b51b6 xfrm: Introduce x... |
52 53 |
spin_lock_bh(&xfrm_input_afinfo_lock); if (unlikely(xfrm_input_afinfo[afinfo->family] != NULL)) |
f31e8d4f7 xfrm: fix the ret... |
54 |
err = -EEXIST; |
2f32b51b6 xfrm: Introduce x... |
55 56 57 58 59 60 |
else rcu_assign_pointer(xfrm_input_afinfo[afinfo->family], afinfo); spin_unlock_bh(&xfrm_input_afinfo_lock); return err; } EXPORT_SYMBOL(xfrm_input_register_afinfo); |
960fdfdeb xfrm: input: cons... |
61 |
int xfrm_input_unregister_afinfo(const struct xfrm_input_afinfo *afinfo) |
2f32b51b6 xfrm: Introduce x... |
62 63 |
{ int err = 0; |
2f32b51b6 xfrm: Introduce x... |
64 65 66 67 68 69 70 71 72 73 74 75 |
spin_lock_bh(&xfrm_input_afinfo_lock); if (likely(xfrm_input_afinfo[afinfo->family] != NULL)) { if (unlikely(xfrm_input_afinfo[afinfo->family] != afinfo)) err = -EINVAL; else RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->family], NULL); } spin_unlock_bh(&xfrm_input_afinfo_lock); synchronize_rcu(); return err; } EXPORT_SYMBOL(xfrm_input_unregister_afinfo); |
960fdfdeb xfrm: input: cons... |
76 |
static const struct xfrm_input_afinfo *xfrm_input_get_afinfo(unsigned int family) |
2f32b51b6 xfrm: Introduce x... |
77 |
{ |
960fdfdeb xfrm: input: cons... |
78 |
const struct xfrm_input_afinfo *afinfo; |
2f32b51b6 xfrm: Introduce x... |
79 |
|
960fdfdeb xfrm: input: cons... |
80 |
if (WARN_ON_ONCE(family >= ARRAY_SIZE(xfrm_input_afinfo))) |
2f32b51b6 xfrm: Introduce x... |
81 |
return NULL; |
960fdfdeb xfrm: input: cons... |
82 |
|
2f32b51b6 xfrm: Introduce x... |
83 84 85 86 87 88 |
rcu_read_lock(); afinfo = rcu_dereference(xfrm_input_afinfo[family]); if (unlikely(!afinfo)) rcu_read_unlock(); return afinfo; } |
2f32b51b6 xfrm: Introduce x... |
89 90 91 92 |
static int xfrm_rcv_cb(struct sk_buff *skb, unsigned int family, u8 protocol, int err) { int ret; |
960fdfdeb xfrm: input: cons... |
93 |
const struct xfrm_input_afinfo *afinfo = xfrm_input_get_afinfo(family); |
2f32b51b6 xfrm: Introduce x... |
94 95 96 97 98 |
if (!afinfo) return -EAFNOSUPPORT; ret = afinfo->callback(skb, protocol, err); |
960fdfdeb xfrm: input: cons... |
99 |
rcu_read_unlock(); |
2f32b51b6 xfrm: Introduce x... |
100 101 102 |
return ret; } |
1da177e4c Linux-2.6.12-rc2 |
103 104 105 106 |
void __secpath_destroy(struct sec_path *sp) { int i; for (i = 0; i < sp->len; i++) |
dbe5b4aaa [IPSEC]: Kill unu... |
107 |
xfrm_state_put(sp->xvec[i]); |
1da177e4c Linux-2.6.12-rc2 |
108 109 110 111 112 113 114 |
kmem_cache_free(secpath_cachep, sp); } EXPORT_SYMBOL(__secpath_destroy); struct sec_path *secpath_dup(struct sec_path *src) { struct sec_path *sp; |
54e6ecb23 [PATCH] slab: rem... |
115 |
sp = kmem_cache_alloc(secpath_cachep, GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
116 117 118 119 |
if (!sp) return NULL; sp->len = 0; |
54ef207ac xfrm: Extend the ... |
120 |
sp->olen = 0; |
d77e38e61 xfrm: Add an IPse... |
121 |
memset(sp->ovec, 0, sizeof(sp->ovec[XFRM_MAX_OFFLOAD_DEPTH])); |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 125 126 |
if (src) { int i; memcpy(sp, src, sizeof(*sp)); for (i = 0; i < sp->len; i++) |
dbe5b4aaa [IPSEC]: Kill unu... |
127 |
xfrm_state_hold(sp->xvec[i]); |
1da177e4c Linux-2.6.12-rc2 |
128 |
} |
55eabed60 net, xfrm: conver... |
129 |
refcount_set(&sp->refcnt, 1); |
1da177e4c Linux-2.6.12-rc2 |
130 131 132 |
return sp; } EXPORT_SYMBOL(secpath_dup); |
b0fcee825 xfrm: Add a secpa... |
133 134 135 136 137 |
int secpath_set(struct sk_buff *skb) { struct sec_path *sp; /* Allocate new secpath or COW existing one. */ |
55eabed60 net, xfrm: conver... |
138 |
if (!skb->sp || refcount_read(&skb->sp->refcnt) != 1) { |
b0fcee825 xfrm: Add a secpa... |
139 140 141 142 143 144 145 146 147 148 149 |
sp = secpath_dup(skb->sp); if (!sp) return -ENOMEM; if (skb->sp) secpath_put(skb->sp); skb->sp = sp; } return 0; } EXPORT_SYMBOL(secpath_set); |
1da177e4c Linux-2.6.12-rc2 |
150 |
/* Fetch spi and seq from ipsec header */ |
6067b2bab [XFRM]: xfrm_pars... |
151 |
int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) |
1da177e4c Linux-2.6.12-rc2 |
152 153 |
{ int offset, offset_seq; |
440725000 [IPSEC]: Fix leng... |
154 |
int hlen; |
1da177e4c Linux-2.6.12-rc2 |
155 156 157 |
switch (nexthdr) { case IPPROTO_AH: |
440725000 [IPSEC]: Fix leng... |
158 |
hlen = sizeof(struct ip_auth_hdr); |
1da177e4c Linux-2.6.12-rc2 |
159 160 161 162 |
offset = offsetof(struct ip_auth_hdr, spi); offset_seq = offsetof(struct ip_auth_hdr, seq_no); break; case IPPROTO_ESP: |
440725000 [IPSEC]: Fix leng... |
163 |
hlen = sizeof(struct ip_esp_hdr); |
1da177e4c Linux-2.6.12-rc2 |
164 165 166 167 168 169 |
offset = offsetof(struct ip_esp_hdr, spi); offset_seq = offsetof(struct ip_esp_hdr, seq_no); break; case IPPROTO_COMP: if (!pskb_may_pull(skb, sizeof(struct ip_comp_hdr))) return -EINVAL; |
3e94c2dcf xfrm: checkpatch ... |
170 |
*spi = htonl(ntohs(*(__be16 *)(skb_transport_header(skb) + 2))); |
1da177e4c Linux-2.6.12-rc2 |
171 172 173 174 175 |
*seq = 0; return 0; default: return 1; } |
440725000 [IPSEC]: Fix leng... |
176 |
if (!pskb_may_pull(skb, hlen)) |
1da177e4c Linux-2.6.12-rc2 |
177 |
return -EINVAL; |
3e94c2dcf xfrm: checkpatch ... |
178 179 |
*spi = *(__be32 *)(skb_transport_header(skb) + offset); *seq = *(__be32 *)(skb_transport_header(skb) + offset_seq); |
1da177e4c Linux-2.6.12-rc2 |
180 181 |
return 0; } |
1e2953703 xfrm: Export xfrm... |
182 |
EXPORT_SYMBOL(xfrm_parse_spi); |
1da177e4c Linux-2.6.12-rc2 |
183 |
|
227620e29 [IPSEC]: Separate... |
184 185 |
int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) { |
df9dcb458 [IPSEC]: Fix inte... |
186 |
struct xfrm_mode *inner_mode = x->inner_mode; |
227620e29 [IPSEC]: Separate... |
187 188 189 190 191 |
int err; err = x->outer_mode->afinfo->extract_input(x, skb); if (err) return err; |
df9dcb458 [IPSEC]: Fix inte... |
192 193 194 195 196 197 198 199 |
if (x->sel.family == AF_UNSPEC) { inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); if (inner_mode == NULL) return -EAFNOSUPPORT; } skb->protocol = inner_mode->afinfo->eth_proto; return inner_mode->input2(x, skb); |
227620e29 [IPSEC]: Separate... |
200 201 |
} EXPORT_SYMBOL(xfrm_prepare_input); |
716062fd4 [IPSEC]: Merge mo... |
202 203 |
int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) { |
bd235e3cf netns xfrm: xfrm_... |
204 |
struct net *net = dev_net(skb->dev); |
716062fd4 [IPSEC]: Merge mo... |
205 206 |
int err; __be32 seq; |
2cd084678 xfrm: Add support... |
207 |
__be32 seq_hi; |
3328715e6 xfrm4: Add IPsec ... |
208 |
struct xfrm_state *x = NULL; |
1bf06cd2e [IPSEC]: Add asyn... |
209 |
xfrm_address_t *daddr; |
df9dcb458 [IPSEC]: Fix inte... |
210 |
struct xfrm_mode *inner_mode; |
049f8e2e2 xfrm: Override sk... |
211 |
u32 mark = skb->mark; |
c232fd3d7 xfrm: Fix xfrm_in... |
212 |
unsigned int family = AF_UNSPEC; |
716062fd4 [IPSEC]: Merge mo... |
213 |
int decaps = 0; |
1bf06cd2e [IPSEC]: Add asyn... |
214 |
int async = 0; |
7785bba29 esp: Add a softwa... |
215 |
bool xfrm_gro = false; |
d77e38e61 xfrm: Add an IPse... |
216 217 |
bool crypto_done = false; struct xfrm_offload *xo = xfrm_offload(skb); |
1bf06cd2e [IPSEC]: Add asyn... |
218 |
|
1bf06cd2e [IPSEC]: Add asyn... |
219 |
if (encap_type < 0) { |
005011211 [IPSEC]: Add xfrm... |
220 |
x = xfrm_input_state(skb); |
c232fd3d7 xfrm: Fix xfrm_in... |
221 222 223 224 225 226 227 228 229 |
if (unlikely(x->km.state != XFRM_STATE_VALID)) { if (x->km.state == XFRM_STATE_ACQ) XFRM_INC_STATS(net, LINUX_MIB_XFRMACQUIREERROR); else XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEINVALID); goto drop; } |
3328715e6 xfrm4: Add IPsec ... |
230 |
family = x->outer_mode->afinfo->family; |
7785bba29 esp: Add a softwa... |
231 232 233 234 235 236 237 |
/* An encap_type of -1 indicates async resumption. */ if (encap_type == -1) { async = 1; seq = XFRM_SKB_CB(skb)->seq.input.low; goto resume; } |
bcd1f8a45 xfrm: Prepare the... |
238 |
|
7785bba29 esp: Add a softwa... |
239 240 241 |
/* encap_type < -1 indicates a GRO call. */ encap_type = 0; seq = XFRM_SPI_SKB_CB(skb)->seq; |
716062fd4 [IPSEC]: Merge mo... |
242 |
|
bcd1f8a45 xfrm: Prepare the... |
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
if (xo && (xo->flags & CRYPTO_DONE)) { crypto_done = true; x = xfrm_input_state(skb); family = XFRM_SPI_SKB_CB(skb)->family; if (!(xo->status & CRYPTO_SUCCESS)) { if (xo->status & (CRYPTO_TRANSPORT_AH_AUTH_FAILED | CRYPTO_TRANSPORT_ESP_AUTH_FAILED | CRYPTO_TUNNEL_AH_AUTH_FAILED | CRYPTO_TUNNEL_ESP_AUTH_FAILED)) { xfrm_audit_state_icvfail(x, skb, x->type->proto); x->stats.integrity_failed++; XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEPROTOERROR); goto drop; } |
47ebcc0bb xfrm: Add support... |
261 262 263 264 |
if (xo->status & CRYPTO_INVALID_PROTOCOL) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEPROTOERROR); goto drop; } |
bcd1f8a45 xfrm: Prepare the... |
265 |
XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); |
d77e38e61 xfrm: Add an IPse... |
266 267 |
goto drop; } |
bcd1f8a45 xfrm: Prepare the... |
268 269 270 271 |
if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); goto drop; } |
d77e38e61 xfrm: Add an IPse... |
272 |
} |
7785bba29 esp: Add a softwa... |
273 |
goto lock; |
1bf06cd2e [IPSEC]: Add asyn... |
274 |
} |
716062fd4 [IPSEC]: Merge mo... |
275 |
|
3328715e6 xfrm4: Add IPsec ... |
276 |
family = XFRM_SPI_SKB_CB(skb)->family; |
049f8e2e2 xfrm: Override sk... |
277 |
/* if tunnel is present override skb->mark value with tunnel i_key */ |
1625f4529 net/xfrm_input: f... |
278 279 280 |
switch (family) { case AF_INET: if (XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4) |
049f8e2e2 xfrm: Override sk... |
281 |
mark = be32_to_cpu(XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4->parms.i_key); |
1625f4529 net/xfrm_input: f... |
282 283 284 |
break; case AF_INET6: if (XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6) |
049f8e2e2 xfrm: Override sk... |
285 |
mark = be32_to_cpu(XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6->parms.i_key); |
1625f4529 net/xfrm_input: f... |
286 |
break; |
049f8e2e2 xfrm: Override sk... |
287 |
} |
b0fcee825 xfrm: Add a secpa... |
288 289 290 291 |
err = secpath_set(skb); if (err) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR); goto drop; |
b2aa5e9d4 [IPSEC]: Store xf... |
292 |
} |
716062fd4 [IPSEC]: Merge mo... |
293 |
seq = 0; |
0aa647746 [XFRM]: Support t... |
294 |
if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) { |
59c9940ed netns xfrm: per-n... |
295 |
XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
716062fd4 [IPSEC]: Merge mo... |
296 |
goto drop; |
0aa647746 [XFRM]: Support t... |
297 |
} |
716062fd4 [IPSEC]: Merge mo... |
298 |
|
cb79a180f xfrm: defer daddr... |
299 300 |
daddr = (xfrm_address_t *)(skb_network_header(skb) + XFRM_SPI_SKB_CB(skb)->daddroff); |
716062fd4 [IPSEC]: Merge mo... |
301 |
do { |
0aa647746 [XFRM]: Support t... |
302 |
if (skb->sp->len == XFRM_MAX_DEPTH) { |
59c9940ed netns xfrm: per-n... |
303 |
XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); |
716062fd4 [IPSEC]: Merge mo... |
304 |
goto drop; |
0aa647746 [XFRM]: Support t... |
305 |
} |
716062fd4 [IPSEC]: Merge mo... |
306 |
|
049f8e2e2 xfrm: Override sk... |
307 |
x = xfrm_state_lookup(net, mark, daddr, spi, nexthdr, family); |
0aa647746 [XFRM]: Support t... |
308 |
if (x == NULL) { |
59c9940ed netns xfrm: per-n... |
309 |
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); |
afeb14b49 [XFRM]: RFC4303 c... |
310 |
xfrm_audit_state_notfound(skb, family, spi, seq); |
716062fd4 [IPSEC]: Merge mo... |
311 |
goto drop; |
0aa647746 [XFRM]: Support t... |
312 |
} |
716062fd4 [IPSEC]: Merge mo... |
313 |
|
b2aa5e9d4 [IPSEC]: Store xf... |
314 |
skb->sp->xvec[skb->sp->len++] = x; |
7785bba29 esp: Add a softwa... |
315 |
lock: |
716062fd4 [IPSEC]: Merge mo... |
316 |
spin_lock(&x->lock); |
4c4d41f20 xfrm: add LINUX_M... |
317 |
|
0aa647746 [XFRM]: Support t... |
318 |
if (unlikely(x->km.state != XFRM_STATE_VALID)) { |
dc0565ce6 xfrm: slightly op... |
319 320 321 322 323 |
if (x->km.state == XFRM_STATE_ACQ) XFRM_INC_STATS(net, LINUX_MIB_XFRMACQUIREERROR); else XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEINVALID); |
716062fd4 [IPSEC]: Merge mo... |
324 |
goto drop_unlock; |
0aa647746 [XFRM]: Support t... |
325 |
} |
716062fd4 [IPSEC]: Merge mo... |
326 |
|
3de77cf23 Revert "xfrm: Acc... |
327 328 329 330 |
if ((x->encap ? x->encap->encap_type : 0) != encap_type) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMISMATCH); goto drop_unlock; } |
36ae0148d xfrm: Move the te... |
331 |
if (x->repl->check(x, skb, seq)) { |
59c9940ed netns xfrm: per-n... |
332 |
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); |
716062fd4 [IPSEC]: Merge mo... |
333 |
goto drop_unlock; |
0aa647746 [XFRM]: Support t... |
334 |
} |
716062fd4 [IPSEC]: Merge mo... |
335 |
|
0aa647746 [XFRM]: Support t... |
336 |
if (xfrm_state_check_expire(x)) { |
59c9940ed netns xfrm: per-n... |
337 |
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEEXPIRED); |
716062fd4 [IPSEC]: Merge mo... |
338 |
goto drop_unlock; |
0aa647746 [XFRM]: Support t... |
339 |
} |
716062fd4 [IPSEC]: Merge mo... |
340 |
|
0ebea8ef3 [IPSEC]: Move sta... |
341 |
spin_unlock(&x->lock); |
68c11e98e xfrm: fix xfrm_in... |
342 343 344 345 |
if (xfrm_tunnel_check(skb, x, family)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR); goto drop; } |
2cd084678 xfrm: Add support... |
346 |
seq_hi = htonl(xfrm_replay_seqhi(x, seq)); |
1ce3644ad xfrm: Use separat... |
347 |
XFRM_SKB_CB(skb)->seq.input.low = seq; |
2cd084678 xfrm: Add support... |
348 |
XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; |
1bf06cd2e [IPSEC]: Add asyn... |
349 |
|
3bc07321c xfrm: Force a dst... |
350 |
skb_dst_force(skb); |
071d36bf2 xfrm: Fix crash o... |
351 |
dev_hold(skb->dev); |
3bc07321c xfrm: Force a dst... |
352 |
|
d77e38e61 xfrm: Add an IPse... |
353 354 355 356 |
if (crypto_done) nexthdr = x->type_offload->input_tail(x, skb); else nexthdr = x->type->input(x, skb); |
0ebea8ef3 [IPSEC]: Move sta... |
357 |
|
1bf06cd2e [IPSEC]: Add asyn... |
358 359 |
if (nexthdr == -EINPROGRESS) return 0; |
1bf06cd2e [IPSEC]: Add asyn... |
360 |
resume: |
071d36bf2 xfrm: Fix crash o... |
361 |
dev_put(skb->dev); |
0ebea8ef3 [IPSEC]: Move sta... |
362 |
spin_lock(&x->lock); |
668dc8af3 [IPSEC]: Move int... |
363 |
if (nexthdr <= 0) { |
9dd3245a2 [IPSEC]: Move all... |
364 365 366 |
if (nexthdr == -EBADMSG) { xfrm_audit_state_icvfail(x, skb, x->type->proto); |
668dc8af3 [IPSEC]: Move int... |
367 |
x->stats.integrity_failed++; |
9dd3245a2 [IPSEC]: Move all... |
368 |
} |
59c9940ed netns xfrm: per-n... |
369 |
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEPROTOERROR); |
716062fd4 [IPSEC]: Merge mo... |
370 |
goto drop_unlock; |
668dc8af3 [IPSEC]: Move int... |
371 |
} |
716062fd4 [IPSEC]: Merge mo... |
372 |
|
716062fd4 [IPSEC]: Merge mo... |
373 374 |
/* only the first xfrm gets the encap type */ encap_type = 0; |
3b59df46a xfrm: Workaround ... |
375 |
if (async && x->repl->recheck(x, skb, seq)) { |
bcf66bf54 xfrm: Perform a r... |
376 377 378 |
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); goto drop_unlock; } |
9fdc4883d xfrm: Move IPsec ... |
379 |
x->repl->advance(x, seq); |
716062fd4 [IPSEC]: Merge mo... |
380 381 382 383 384 |
x->curlft.bytes += skb->len; x->curlft.packets++; spin_unlock(&x->lock); |
60d5fcfb1 [IPSEC]: Remove n... |
385 |
XFRM_MODE_SKB_CB(skb)->protocol = nexthdr; |
df9dcb458 [IPSEC]: Fix inte... |
386 387 388 389 |
inner_mode = x->inner_mode; if (x->sel.family == AF_UNSPEC) { inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); |
cb866e329 xfrm: Increment s... |
390 391 |
if (inner_mode == NULL) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR); |
df9dcb458 [IPSEC]: Fix inte... |
392 |
goto drop; |
cb866e329 xfrm: Increment s... |
393 |
} |
df9dcb458 [IPSEC]: Fix inte... |
394 395 396 |
} if (inner_mode->input(x, skb)) { |
59c9940ed netns xfrm: per-n... |
397 |
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR); |
716062fd4 [IPSEC]: Merge mo... |
398 |
goto drop; |
0aa647746 [XFRM]: Support t... |
399 |
} |
716062fd4 [IPSEC]: Merge mo... |
400 401 402 403 404 |
if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { decaps = 1; break; } |
1bf06cd2e [IPSEC]: Add asyn... |
405 406 407 408 409 |
/* * We need the inner address. However, we only get here for * transport mode so the outer address is identical. */ daddr = &x->id.daddr; |
2fcb45b6b [IPSEC]: Use the ... |
410 |
family = x->outer_mode->afinfo->family; |
1bf06cd2e [IPSEC]: Add asyn... |
411 |
|
716062fd4 [IPSEC]: Merge mo... |
412 |
err = xfrm_parse_spi(skb, nexthdr, &spi, &seq); |
0aa647746 [XFRM]: Support t... |
413 |
if (err < 0) { |
59c9940ed netns xfrm: per-n... |
414 |
XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
716062fd4 [IPSEC]: Merge mo... |
415 |
goto drop; |
0aa647746 [XFRM]: Support t... |
416 |
} |
716062fd4 [IPSEC]: Merge mo... |
417 |
} while (!err); |
3328715e6 xfrm4: Add IPsec ... |
418 419 420 |
err = xfrm_rcv_cb(skb, family, x->type->proto, 0); if (err) goto drop; |
716062fd4 [IPSEC]: Merge mo... |
421 422 423 |
nf_reset(skb); if (decaps) { |
23e9fcfef vti: fix NULL der... |
424 425 |
if (skb->sp) skb->sp->olen = 0; |
adf30907d net: skb->dst acc... |
426 |
skb_dst_drop(skb); |
1995876a0 xfrm: Add a dummy... |
427 |
gro_cells_receive(&gro_cells, skb); |
716062fd4 [IPSEC]: Merge mo... |
428 429 |
return 0; } else { |
7785bba29 esp: Add a softwa... |
430 431 432 |
xo = xfrm_offload(skb); if (xo) xfrm_gro = xo->flags & XFRM_GRO; |
cfcf99f98 xfrm: fix GRO for... |
433 |
err = x->inner_mode->afinfo->transport_finish(skb, xfrm_gro || async); |
7785bba29 esp: Add a softwa... |
434 |
if (xfrm_gro) { |
23e9fcfef vti: fix NULL der... |
435 436 |
if (skb->sp) skb->sp->olen = 0; |
7785bba29 esp: Add a softwa... |
437 438 439 440 441 442 |
skb_dst_drop(skb); gro_cells_receive(&gro_cells, skb); return err; } return err; |
716062fd4 [IPSEC]: Merge mo... |
443 444 445 446 |
} drop_unlock: spin_unlock(&x->lock); |
716062fd4 [IPSEC]: Merge mo... |
447 |
drop: |
3328715e6 xfrm4: Add IPsec ... |
448 |
xfrm_rcv_cb(skb, family, x && x->type ? x->type->proto : nexthdr, -1); |
716062fd4 [IPSEC]: Merge mo... |
449 450 451 452 |
kfree_skb(skb); return 0; } EXPORT_SYMBOL(xfrm_input); |
1bf06cd2e [IPSEC]: Add asyn... |
453 454 455 456 457 |
int xfrm_input_resume(struct sk_buff *skb, int nexthdr) { return xfrm_input(skb, nexthdr, 0, -1); } EXPORT_SYMBOL(xfrm_input_resume); |
e095ecaec xfrm: Reinject tr... |
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 |
static void xfrm_trans_reinject(unsigned long data) { struct xfrm_trans_tasklet *trans = (void *)data; struct sk_buff_head queue; struct sk_buff *skb; __skb_queue_head_init(&queue); skb_queue_splice_init(&trans->queue, &queue); while ((skb = __skb_dequeue(&queue))) XFRM_TRANS_SKB_CB(skb)->finish(dev_net(skb->dev), NULL, skb); } int xfrm_trans_queue(struct sk_buff *skb, int (*finish)(struct net *, struct sock *, struct sk_buff *)) { struct xfrm_trans_tasklet *trans; trans = this_cpu_ptr(&xfrm_trans_tasklet); if (skb_queue_len(&trans->queue) >= netdev_max_backlog) return -ENOBUFS; XFRM_TRANS_SKB_CB(skb)->finish = finish; |
d2d85f8d2 xfrm: Use __skb_q... |
483 |
__skb_queue_tail(&trans->queue, skb); |
e095ecaec xfrm: Reinject tr... |
484 485 486 487 |
tasklet_schedule(&trans->tasklet); return 0; } EXPORT_SYMBOL(xfrm_trans_queue); |
1da177e4c Linux-2.6.12-rc2 |
488 489 |
void __init xfrm_input_init(void) { |
1995876a0 xfrm: Add a dummy... |
490 |
int err; |
e095ecaec xfrm: Reinject tr... |
491 |
int i; |
1995876a0 xfrm: Add a dummy... |
492 493 494 495 496 |
init_dummy_netdev(&xfrm_napi_dev); err = gro_cells_init(&gro_cells, &xfrm_napi_dev); if (err) gro_cells.cells = NULL; |
1da177e4c Linux-2.6.12-rc2 |
497 498 |
secpath_cachep = kmem_cache_create("secpath_cache", sizeof(struct sec_path), |
e5d679f33 [NET]: Use SLAB_P... |
499 |
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, |
20c2df83d mm: Remove slab d... |
500 |
NULL); |
e095ecaec xfrm: Reinject tr... |
501 502 503 504 505 506 507 508 509 |
for_each_possible_cpu(i) { struct xfrm_trans_tasklet *trans; trans = &per_cpu(xfrm_trans_tasklet, i); __skb_queue_head_init(&trans->queue); tasklet_init(&trans->tasklet, xfrm_trans_reinject, (unsigned long)trans); } |
1da177e4c Linux-2.6.12-rc2 |
510 |
} |