]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - net/xfrm/xfrm_state.c
xfrm: state: add sequence count to detect hash resizes
[mirror_ubuntu-artful-kernel.git] / net / xfrm / xfrm_state.c
CommitLineData
1da177e4
LT
1/*
2 * xfrm_state.c
3 *
4 * Changes:
5 * Mitsuru KANDA @USAGI
6 * Kazunori MIYAZAWA @USAGI
7 * Kunihiro Ishiguro <kunihiro@ipinfusion.com>
8 * IPv6 support
9 * YOSHIFUJI Hideaki @USAGI
10 * Split up af-specific functions
11 * Derek Atkins <derek@ihtfp.com>
12 * Add UDP Encapsulation
df71837d 13 *
1da177e4
LT
14 */
15
16#include <linux/workqueue.h>
17#include <net/xfrm.h>
18#include <linux/pfkeyv2.h>
19#include <linux/ipsec.h>
20#include <linux/module.h>
f034b5d4 21#include <linux/cache.h>
68277acc 22#include <linux/audit.h>
b5890d8b 23#include <asm/uaccess.h>
9e0d57fd 24#include <linux/ktime.h>
5a0e3ad6 25#include <linux/slab.h>
9e0d57fd
YP
26#include <linux/interrupt.h>
27#include <linux/kernel.h>
1da177e4 28
44e36b42
DM
29#include "xfrm_hash.h"
30
1da177e4
LT
31/* Each xfrm_state may be linked to two tables:
32
33 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
a624c108 34 2. Hash table by (daddr,family,reqid) to find what SAs exist for given
1da177e4
LT
35 destination/tunnel endpoint. (output)
36 */
37
f034b5d4 38static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
b65e3d7b 39static __read_mostly seqcount_t xfrm_state_hash_generation = SEQCNT_ZERO(xfrm_state_hash_generation);
f034b5d4 40
02efdff7
FW
41static inline bool xfrm_state_hold_rcu(struct xfrm_state __rcu *x)
42{
43 return atomic_inc_not_zero(&x->refcnt);
44}
45
64d0cd00 46static inline unsigned int xfrm_dst_hash(struct net *net,
2ab38503
DM
47 const xfrm_address_t *daddr,
48 const xfrm_address_t *saddr,
c1969f29 49 u32 reqid,
a624c108 50 unsigned short family)
f034b5d4 51{
64d0cd00 52 return __xfrm_dst_hash(daddr, saddr, reqid, family, net->xfrm.state_hmask);
f034b5d4
DM
53}
54
64d0cd00 55static inline unsigned int xfrm_src_hash(struct net *net,
2ab38503
DM
56 const xfrm_address_t *daddr,
57 const xfrm_address_t *saddr,
44e36b42 58 unsigned short family)
f034b5d4 59{
64d0cd00 60 return __xfrm_src_hash(daddr, saddr, family, net->xfrm.state_hmask);
f034b5d4
DM
61}
62
f034b5d4 63static inline unsigned int
2ab38503
DM
64xfrm_spi_hash(struct net *net, const xfrm_address_t *daddr,
65 __be32 spi, u8 proto, unsigned short family)
f034b5d4 66{
64d0cd00 67 return __xfrm_spi_hash(daddr, spi, proto, family, net->xfrm.state_hmask);
f034b5d4
DM
68}
69
f034b5d4
DM
70static void xfrm_hash_transfer(struct hlist_head *list,
71 struct hlist_head *ndsttable,
72 struct hlist_head *nsrctable,
73 struct hlist_head *nspitable,
74 unsigned int nhashmask)
75{
b67bfe0d 76 struct hlist_node *tmp;
f034b5d4
DM
77 struct xfrm_state *x;
78
b67bfe0d 79 hlist_for_each_entry_safe(x, tmp, list, bydst) {
f034b5d4
DM
80 unsigned int h;
81
c1969f29
DM
82 h = __xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
83 x->props.reqid, x->props.family,
84 nhashmask);
ae3fb6d3 85 hlist_add_head_rcu(&x->bydst, ndsttable + h);
f034b5d4 86
667bbcb6
MN
87 h = __xfrm_src_hash(&x->id.daddr, &x->props.saddr,
88 x->props.family,
f034b5d4 89 nhashmask);
ae3fb6d3 90 hlist_add_head_rcu(&x->bysrc, nsrctable + h);
f034b5d4 91
7b4dc360
MN
92 if (x->id.spi) {
93 h = __xfrm_spi_hash(&x->id.daddr, x->id.spi,
94 x->id.proto, x->props.family,
95 nhashmask);
ae3fb6d3 96 hlist_add_head_rcu(&x->byspi, nspitable + h);
7b4dc360 97 }
f034b5d4
DM
98 }
99}
100
63082733 101static unsigned long xfrm_hash_new_size(unsigned int state_hmask)
f034b5d4 102{
63082733 103 return ((state_hmask + 1) << 1) * sizeof(struct hlist_head);
f034b5d4
DM
104}
105
63082733 106static void xfrm_hash_resize(struct work_struct *work)
f034b5d4 107{
63082733 108 struct net *net = container_of(work, struct net, xfrm.state_hash_work);
f034b5d4
DM
109 struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi;
110 unsigned long nsize, osize;
111 unsigned int nhashmask, ohashmask;
112 int i;
113
63082733 114 nsize = xfrm_hash_new_size(net->xfrm.state_hmask);
44e36b42 115 ndst = xfrm_hash_alloc(nsize);
f034b5d4 116 if (!ndst)
0244790c 117 return;
44e36b42 118 nsrc = xfrm_hash_alloc(nsize);
f034b5d4 119 if (!nsrc) {
44e36b42 120 xfrm_hash_free(ndst, nsize);
0244790c 121 return;
f034b5d4 122 }
44e36b42 123 nspi = xfrm_hash_alloc(nsize);
f034b5d4 124 if (!nspi) {
44e36b42
DM
125 xfrm_hash_free(ndst, nsize);
126 xfrm_hash_free(nsrc, nsize);
0244790c 127 return;
f034b5d4
DM
128 }
129
283bc9f3 130 spin_lock_bh(&net->xfrm.xfrm_state_lock);
b65e3d7b 131 write_seqcount_begin(&xfrm_state_hash_generation);
f034b5d4
DM
132
133 nhashmask = (nsize / sizeof(struct hlist_head)) - 1U;
63082733
AD
134 for (i = net->xfrm.state_hmask; i >= 0; i--)
135 xfrm_hash_transfer(net->xfrm.state_bydst+i, ndst, nsrc, nspi,
f034b5d4
DM
136 nhashmask);
137
63082733
AD
138 odst = net->xfrm.state_bydst;
139 osrc = net->xfrm.state_bysrc;
140 ospi = net->xfrm.state_byspi;
141 ohashmask = net->xfrm.state_hmask;
f034b5d4 142
63082733
AD
143 net->xfrm.state_bydst = ndst;
144 net->xfrm.state_bysrc = nsrc;
145 net->xfrm.state_byspi = nspi;
146 net->xfrm.state_hmask = nhashmask;
f034b5d4 147
b65e3d7b 148 write_seqcount_end(&xfrm_state_hash_generation);
283bc9f3 149 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
f034b5d4
DM
150
151 osize = (ohashmask + 1) * sizeof(struct hlist_head);
df7274eb
FW
152
153 synchronize_rcu();
154
44e36b42
DM
155 xfrm_hash_free(odst, osize);
156 xfrm_hash_free(osrc, osize);
157 xfrm_hash_free(ospi, osize);
f034b5d4
DM
158}
159
44abdc30
CW
160static DEFINE_SPINLOCK(xfrm_state_afinfo_lock);
161static struct xfrm_state_afinfo __rcu *xfrm_state_afinfo[NPROTO];
1da177e4 162
1da177e4
LT
163static DEFINE_SPINLOCK(xfrm_state_gc_lock);
164
53bc6b4d 165int __xfrm_state_delete(struct xfrm_state *x);
1da177e4 166
980ebd25 167int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
0f24558e 168bool km_is_alive(const struct km_event *c);
15e47304 169void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
1da177e4 170
7a9885b9 171static DEFINE_SPINLOCK(xfrm_type_lock);
533cb5b0 172int xfrm_register_type(const struct xfrm_type *type, unsigned short family)
aa5d62cc 173{
7a9885b9 174 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
533cb5b0 175 const struct xfrm_type **typemap;
aa5d62cc
HX
176 int err = 0;
177
178 if (unlikely(afinfo == NULL))
179 return -EAFNOSUPPORT;
180 typemap = afinfo->type_map;
7a9885b9 181 spin_lock_bh(&xfrm_type_lock);
aa5d62cc
HX
182
183 if (likely(typemap[type->proto] == NULL))
184 typemap[type->proto] = type;
185 else
186 err = -EEXIST;
7a9885b9
CW
187 spin_unlock_bh(&xfrm_type_lock);
188 xfrm_state_put_afinfo(afinfo);
aa5d62cc
HX
189 return err;
190}
191EXPORT_SYMBOL(xfrm_register_type);
192
533cb5b0 193int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family)
aa5d62cc 194{
7a9885b9 195 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
533cb5b0 196 const struct xfrm_type **typemap;
aa5d62cc
HX
197 int err = 0;
198
199 if (unlikely(afinfo == NULL))
200 return -EAFNOSUPPORT;
201 typemap = afinfo->type_map;
7a9885b9 202 spin_lock_bh(&xfrm_type_lock);
aa5d62cc
HX
203
204 if (unlikely(typemap[type->proto] != type))
205 err = -ENOENT;
206 else
207 typemap[type->proto] = NULL;
7a9885b9
CW
208 spin_unlock_bh(&xfrm_type_lock);
209 xfrm_state_put_afinfo(afinfo);
aa5d62cc
HX
210 return err;
211}
212EXPORT_SYMBOL(xfrm_unregister_type);
213
533cb5b0 214static const struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
aa5d62cc
HX
215{
216 struct xfrm_state_afinfo *afinfo;
533cb5b0
ED
217 const struct xfrm_type **typemap;
218 const struct xfrm_type *type;
aa5d62cc
HX
219 int modload_attempted = 0;
220
221retry:
222 afinfo = xfrm_state_get_afinfo(family);
223 if (unlikely(afinfo == NULL))
224 return NULL;
225 typemap = afinfo->type_map;
226
227 type = typemap[proto];
228 if (unlikely(type && !try_module_get(type->owner)))
229 type = NULL;
230 if (!type && !modload_attempted) {
231 xfrm_state_put_afinfo(afinfo);
232 request_module("xfrm-type-%d-%d", family, proto);
233 modload_attempted = 1;
234 goto retry;
235 }
236
237 xfrm_state_put_afinfo(afinfo);
238 return type;
239}
240
533cb5b0 241static void xfrm_put_type(const struct xfrm_type *type)
aa5d62cc
HX
242{
243 module_put(type->owner);
244}
245
7a9885b9 246static DEFINE_SPINLOCK(xfrm_mode_lock);
aa5d62cc
HX
247int xfrm_register_mode(struct xfrm_mode *mode, int family)
248{
249 struct xfrm_state_afinfo *afinfo;
250 struct xfrm_mode **modemap;
251 int err;
252
253 if (unlikely(mode->encap >= XFRM_MODE_MAX))
254 return -EINVAL;
255
7a9885b9 256 afinfo = xfrm_state_get_afinfo(family);
aa5d62cc
HX
257 if (unlikely(afinfo == NULL))
258 return -EAFNOSUPPORT;
259
260 err = -EEXIST;
261 modemap = afinfo->mode_map;
7a9885b9 262 spin_lock_bh(&xfrm_mode_lock);
17c2a42a
HX
263 if (modemap[mode->encap])
264 goto out;
aa5d62cc 265
17c2a42a
HX
266 err = -ENOENT;
267 if (!try_module_get(afinfo->owner))
268 goto out;
269
270 mode->afinfo = afinfo;
271 modemap[mode->encap] = mode;
272 err = 0;
273
274out:
7a9885b9
CW
275 spin_unlock_bh(&xfrm_mode_lock);
276 xfrm_state_put_afinfo(afinfo);
aa5d62cc
HX
277 return err;
278}
279EXPORT_SYMBOL(xfrm_register_mode);
280
281int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
282{
283 struct xfrm_state_afinfo *afinfo;
284 struct xfrm_mode **modemap;
285 int err;
286
287 if (unlikely(mode->encap >= XFRM_MODE_MAX))
288 return -EINVAL;
289
7a9885b9 290 afinfo = xfrm_state_get_afinfo(family);
aa5d62cc
HX
291 if (unlikely(afinfo == NULL))
292 return -EAFNOSUPPORT;
293
294 err = -ENOENT;
295 modemap = afinfo->mode_map;
7a9885b9 296 spin_lock_bh(&xfrm_mode_lock);
aa5d62cc
HX
297 if (likely(modemap[mode->encap] == mode)) {
298 modemap[mode->encap] = NULL;
17c2a42a 299 module_put(mode->afinfo->owner);
aa5d62cc
HX
300 err = 0;
301 }
302
7a9885b9
CW
303 spin_unlock_bh(&xfrm_mode_lock);
304 xfrm_state_put_afinfo(afinfo);
aa5d62cc
HX
305 return err;
306}
307EXPORT_SYMBOL(xfrm_unregister_mode);
308
309static struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
310{
311 struct xfrm_state_afinfo *afinfo;
312 struct xfrm_mode *mode;
313 int modload_attempted = 0;
314
315 if (unlikely(encap >= XFRM_MODE_MAX))
316 return NULL;
317
318retry:
319 afinfo = xfrm_state_get_afinfo(family);
320 if (unlikely(afinfo == NULL))
321 return NULL;
322
323 mode = afinfo->mode_map[encap];
324 if (unlikely(mode && !try_module_get(mode->owner)))
325 mode = NULL;
326 if (!mode && !modload_attempted) {
327 xfrm_state_put_afinfo(afinfo);
328 request_module("xfrm-mode-%d-%d", family, encap);
329 modload_attempted = 1;
330 goto retry;
331 }
332
333 xfrm_state_put_afinfo(afinfo);
334 return mode;
335}
336
337static void xfrm_put_mode(struct xfrm_mode *mode)
338{
339 module_put(mode->owner);
340}
341
1da177e4
LT
342static void xfrm_state_gc_destroy(struct xfrm_state *x)
343{
9e0d57fd 344 tasklet_hrtimer_cancel(&x->mtimer);
a47f0ce0 345 del_timer_sync(&x->rtimer);
a51482bd
JJ
346 kfree(x->aalg);
347 kfree(x->ealg);
348 kfree(x->calg);
349 kfree(x->encap);
060f02a3 350 kfree(x->coaddr);
d8647b79
SK
351 kfree(x->replay_esn);
352 kfree(x->preplay_esn);
13996378
HX
353 if (x->inner_mode)
354 xfrm_put_mode(x->inner_mode);
df9dcb45
KM
355 if (x->inner_mode_iaf)
356 xfrm_put_mode(x->inner_mode_iaf);
13996378
HX
357 if (x->outer_mode)
358 xfrm_put_mode(x->outer_mode);
1da177e4
LT
359 if (x->type) {
360 x->type->destructor(x);
361 xfrm_put_type(x->type);
362 }
df71837d 363 security_xfrm_state_free(x);
1da177e4
LT
364 kfree(x);
365}
366
c7837144 367static void xfrm_state_gc_task(struct work_struct *work)
1da177e4 368{
c7837144 369 struct net *net = container_of(work, struct net, xfrm.state_gc_work);
12a169e7 370 struct xfrm_state *x;
b67bfe0d 371 struct hlist_node *tmp;
12a169e7 372 struct hlist_head gc_list;
1da177e4 373
1da177e4 374 spin_lock_bh(&xfrm_state_gc_lock);
c7837144 375 hlist_move_list(&net->xfrm.state_gc_list, &gc_list);
1da177e4
LT
376 spin_unlock_bh(&xfrm_state_gc_lock);
377
df7274eb
FW
378 synchronize_rcu();
379
b67bfe0d 380 hlist_for_each_entry_safe(x, tmp, &gc_list, gclist)
1da177e4 381 xfrm_state_gc_destroy(x);
1da177e4
LT
382}
383
384static inline unsigned long make_jiffies(long secs)
385{
386 if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
387 return MAX_SCHEDULE_TIMEOUT-1;
388 else
a716c119 389 return secs*HZ;
1da177e4
LT
390}
391
3e94c2dc 392static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
1da177e4 393{
9e0d57fd
YP
394 struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
395 struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer);
9d729f72 396 unsigned long now = get_seconds();
1da177e4
LT
397 long next = LONG_MAX;
398 int warn = 0;
161a09e7 399 int err = 0;
1da177e4
LT
400
401 spin_lock(&x->lock);
402 if (x->km.state == XFRM_STATE_DEAD)
403 goto out;
404 if (x->km.state == XFRM_STATE_EXPIRED)
405 goto expired;
406 if (x->lft.hard_add_expires_seconds) {
407 long tmo = x->lft.hard_add_expires_seconds +
408 x->curlft.add_time - now;
e3c0d047
FD
409 if (tmo <= 0) {
410 if (x->xflags & XFRM_SOFT_EXPIRE) {
411 /* enter hard expire without soft expire first?!
412 * setting a new date could trigger this.
413 * workarbound: fix x->curflt.add_time by below:
414 */
415 x->curlft.add_time = now - x->saved_tmo - 1;
416 tmo = x->lft.hard_add_expires_seconds - x->saved_tmo;
417 } else
418 goto expired;
419 }
1da177e4
LT
420 if (tmo < next)
421 next = tmo;
422 }
423 if (x->lft.hard_use_expires_seconds) {
424 long tmo = x->lft.hard_use_expires_seconds +
425 (x->curlft.use_time ? : now) - now;
426 if (tmo <= 0)
427 goto expired;
428 if (tmo < next)
429 next = tmo;
430 }
431 if (x->km.dying)
432 goto resched;
433 if (x->lft.soft_add_expires_seconds) {
434 long tmo = x->lft.soft_add_expires_seconds +
435 x->curlft.add_time - now;
e3c0d047 436 if (tmo <= 0) {
1da177e4 437 warn = 1;
e3c0d047
FD
438 x->xflags &= ~XFRM_SOFT_EXPIRE;
439 } else if (tmo < next) {
1da177e4 440 next = tmo;
e3c0d047
FD
441 x->xflags |= XFRM_SOFT_EXPIRE;
442 x->saved_tmo = tmo;
443 }
1da177e4
LT
444 }
445 if (x->lft.soft_use_expires_seconds) {
446 long tmo = x->lft.soft_use_expires_seconds +
447 (x->curlft.use_time ? : now) - now;
448 if (tmo <= 0)
449 warn = 1;
450 else if (tmo < next)
451 next = tmo;
452 }
453
4666faab 454 x->km.dying = warn;
1da177e4 455 if (warn)
53bc6b4d 456 km_state_expired(x, 0, 0);
1da177e4 457resched:
9b7a787d 458 if (next != LONG_MAX) {
9e0d57fd
YP
459 tasklet_hrtimer_start(&x->mtimer, ktime_set(next, 0), HRTIMER_MODE_REL);
460 }
a47f0ce0 461
1da177e4
LT
462 goto out;
463
464expired:
5b8ef341 465 if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0)
1da177e4 466 x->km.state = XFRM_STATE_EXPIRED;
161a09e7
JL
467
468 err = __xfrm_state_delete(x);
0806ae4c 469 if (!err)
53bc6b4d 470 km_state_expired(x, 1, 0);
1da177e4 471
2e71029e 472 xfrm_audit_state_delete(x, err ? 0 : 1, true);
161a09e7 473
1da177e4
LT
474out:
475 spin_unlock(&x->lock);
9e0d57fd 476 return HRTIMER_NORESTART;
1da177e4
LT
477}
478
0ac84752
DM
479static void xfrm_replay_timer_handler(unsigned long data);
480
673c09be 481struct xfrm_state *xfrm_state_alloc(struct net *net)
1da177e4
LT
482{
483 struct xfrm_state *x;
484
0da974f4 485 x = kzalloc(sizeof(struct xfrm_state), GFP_ATOMIC);
1da177e4
LT
486
487 if (x) {
673c09be 488 write_pnet(&x->xs_net, net);
1da177e4
LT
489 atomic_set(&x->refcnt, 1);
490 atomic_set(&x->tunnel_users, 0);
12a169e7 491 INIT_LIST_HEAD(&x->km.all);
8f126e37
DM
492 INIT_HLIST_NODE(&x->bydst);
493 INIT_HLIST_NODE(&x->bysrc);
494 INIT_HLIST_NODE(&x->byspi);
99565a6c
FD
495 tasklet_hrtimer_init(&x->mtimer, xfrm_timer_handler,
496 CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
b24b8a24
PE
497 setup_timer(&x->rtimer, xfrm_replay_timer_handler,
498 (unsigned long)x);
9d729f72 499 x->curlft.add_time = get_seconds();
1da177e4
LT
500 x->lft.soft_byte_limit = XFRM_INF;
501 x->lft.soft_packet_limit = XFRM_INF;
502 x->lft.hard_byte_limit = XFRM_INF;
503 x->lft.hard_packet_limit = XFRM_INF;
f8cd5488
JHS
504 x->replay_maxage = 0;
505 x->replay_maxdiff = 0;
df9dcb45
KM
506 x->inner_mode = NULL;
507 x->inner_mode_iaf = NULL;
1da177e4
LT
508 spin_lock_init(&x->lock);
509 }
510 return x;
511}
512EXPORT_SYMBOL(xfrm_state_alloc);
513
514void __xfrm_state_destroy(struct xfrm_state *x)
515{
98806f75
AD
516 struct net *net = xs_net(x);
517
547b792c 518 WARN_ON(x->km.state != XFRM_STATE_DEAD);
1da177e4
LT
519
520 spin_lock_bh(&xfrm_state_gc_lock);
98806f75 521 hlist_add_head(&x->gclist, &net->xfrm.state_gc_list);
1da177e4 522 spin_unlock_bh(&xfrm_state_gc_lock);
98806f75 523 schedule_work(&net->xfrm.state_gc_work);
1da177e4
LT
524}
525EXPORT_SYMBOL(__xfrm_state_destroy);
526
53bc6b4d 527int __xfrm_state_delete(struct xfrm_state *x)
1da177e4 528{
98806f75 529 struct net *net = xs_net(x);
26b15dad
JHS
530 int err = -ESRCH;
531
1da177e4
LT
532 if (x->km.state != XFRM_STATE_DEAD) {
533 x->km.state = XFRM_STATE_DEAD;
283bc9f3 534 spin_lock(&net->xfrm.xfrm_state_lock);
12a169e7 535 list_del(&x->km.all);
ae3fb6d3
FW
536 hlist_del_rcu(&x->bydst);
537 hlist_del_rcu(&x->bysrc);
a47f0ce0 538 if (x->id.spi)
ae3fb6d3 539 hlist_del_rcu(&x->byspi);
98806f75 540 net->xfrm.state_num--;
283bc9f3 541 spin_unlock(&net->xfrm.xfrm_state_lock);
1da177e4 542
1da177e4
LT
543 /* All xfrm_state objects are created by xfrm_state_alloc.
544 * The xfrm_state_alloc call gives a reference, and that
545 * is what we are dropping here.
546 */
5dba4797 547 xfrm_state_put(x);
26b15dad 548 err = 0;
1da177e4 549 }
26b15dad
JHS
550
551 return err;
1da177e4 552}
53bc6b4d 553EXPORT_SYMBOL(__xfrm_state_delete);
1da177e4 554
26b15dad 555int xfrm_state_delete(struct xfrm_state *x)
1da177e4 556{
26b15dad
JHS
557 int err;
558
1da177e4 559 spin_lock_bh(&x->lock);
26b15dad 560 err = __xfrm_state_delete(x);
1da177e4 561 spin_unlock_bh(&x->lock);
26b15dad
JHS
562
563 return err;
1da177e4
LT
564}
565EXPORT_SYMBOL(xfrm_state_delete);
566
4aa2e62c
JL
567#ifdef CONFIG_SECURITY_NETWORK_XFRM
568static inline int
2e71029e 569xfrm_state_flush_secctx_check(struct net *net, u8 proto, bool task_valid)
1da177e4 570{
4aa2e62c
JL
571 int i, err = 0;
572
0e602451 573 for (i = 0; i <= net->xfrm.state_hmask; i++) {
4aa2e62c
JL
574 struct xfrm_state *x;
575
b67bfe0d 576 hlist_for_each_entry(x, net->xfrm.state_bydst+i, bydst) {
4aa2e62c
JL
577 if (xfrm_id_proto_match(x->id.proto, proto) &&
578 (err = security_xfrm_state_delete(x)) != 0) {
2e71029e 579 xfrm_audit_state_delete(x, 0, task_valid);
4aa2e62c
JL
580 return err;
581 }
582 }
583 }
584
585 return err;
586}
587#else
588static inline int
2e71029e 589xfrm_state_flush_secctx_check(struct net *net, u8 proto, bool task_valid)
4aa2e62c
JL
590{
591 return 0;
592}
593#endif
594
2e71029e 595int xfrm_state_flush(struct net *net, u8 proto, bool task_valid)
4aa2e62c 596{
9e64cc95 597 int i, err = 0, cnt = 0;
1da177e4 598
283bc9f3 599 spin_lock_bh(&net->xfrm.xfrm_state_lock);
2e71029e 600 err = xfrm_state_flush_secctx_check(net, proto, task_valid);
4aa2e62c
JL
601 if (err)
602 goto out;
603
9e64cc95 604 err = -ESRCH;
0e602451 605 for (i = 0; i <= net->xfrm.state_hmask; i++) {
8f126e37 606 struct xfrm_state *x;
1da177e4 607restart:
b67bfe0d 608 hlist_for_each_entry(x, net->xfrm.state_bydst+i, bydst) {
1da177e4 609 if (!xfrm_state_kern(x) &&
5794708f 610 xfrm_id_proto_match(x->id.proto, proto)) {
1da177e4 611 xfrm_state_hold(x);
283bc9f3 612 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
1da177e4 613
161a09e7 614 err = xfrm_state_delete(x);
ab5f5e8b 615 xfrm_audit_state_delete(x, err ? 0 : 1,
2e71029e 616 task_valid);
1da177e4 617 xfrm_state_put(x);
9e64cc95
JHS
618 if (!err)
619 cnt++;
1da177e4 620
283bc9f3 621 spin_lock_bh(&net->xfrm.xfrm_state_lock);
1da177e4
LT
622 goto restart;
623 }
624 }
625 }
9e64cc95
JHS
626 if (cnt)
627 err = 0;
4aa2e62c
JL
628
629out:
283bc9f3 630 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
4aa2e62c 631 return err;
1da177e4
LT
632}
633EXPORT_SYMBOL(xfrm_state_flush);
634
e071041b 635void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
28d8909b 636{
283bc9f3 637 spin_lock_bh(&net->xfrm.xfrm_state_lock);
e071041b
AD
638 si->sadcnt = net->xfrm.state_num;
639 si->sadhcnt = net->xfrm.state_hmask;
28d8909b 640 si->sadhmcnt = xfrm_state_hashmax;
283bc9f3 641 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
28d8909b
JHS
642}
643EXPORT_SYMBOL(xfrm_sad_getinfo);
644
1da177e4 645static int
1a898592 646xfrm_init_tempstate(struct xfrm_state *x, const struct flowi *fl,
04686013 647 const struct xfrm_tmpl *tmpl,
33765d06 648 const xfrm_address_t *daddr, const xfrm_address_t *saddr,
8444cf71 649 unsigned short family)
1da177e4
LT
650{
651 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
652 if (!afinfo)
653 return -1;
8444cf71
TE
654 afinfo->init_tempsel(&x->sel, fl);
655
656 if (family != tmpl->encap_family) {
657 xfrm_state_put_afinfo(afinfo);
658 afinfo = xfrm_state_get_afinfo(tmpl->encap_family);
659 if (!afinfo)
660 return -1;
661 }
662 afinfo->init_temprop(x, tmpl, daddr, saddr);
1da177e4
LT
663 xfrm_state_put_afinfo(afinfo);
664 return 0;
665}
666
9aa60088
DM
667static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark,
668 const xfrm_address_t *daddr,
669 __be32 spi, u8 proto,
670 unsigned short family)
edcd5821 671{
221df1ed 672 unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family);
edcd5821
DM
673 struct xfrm_state *x;
674
ae3fb6d3 675 hlist_for_each_entry_rcu(x, net->xfrm.state_byspi + h, byspi) {
edcd5821
DM
676 if (x->props.family != family ||
677 x->id.spi != spi ||
1802571b 678 x->id.proto != proto ||
70e94e66 679 !xfrm_addr_equal(&x->id.daddr, daddr, family))
edcd5821
DM
680 continue;
681
3d6acfa7
JHS
682 if ((mark & x->mark.m) != x->mark.v)
683 continue;
02efdff7
FW
684 if (!xfrm_state_hold_rcu(x))
685 continue;
edcd5821
DM
686 return x;
687 }
688
689 return NULL;
690}
691
9aa60088
DM
692static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark,
693 const xfrm_address_t *daddr,
694 const xfrm_address_t *saddr,
695 u8 proto, unsigned short family)
edcd5821 696{
221df1ed 697 unsigned int h = xfrm_src_hash(net, daddr, saddr, family);
edcd5821
DM
698 struct xfrm_state *x;
699
ae3fb6d3 700 hlist_for_each_entry_rcu(x, net->xfrm.state_bysrc + h, bysrc) {
edcd5821 701 if (x->props.family != family ||
1802571b 702 x->id.proto != proto ||
70e94e66
YH
703 !xfrm_addr_equal(&x->id.daddr, daddr, family) ||
704 !xfrm_addr_equal(&x->props.saddr, saddr, family))
edcd5821
DM
705 continue;
706
3d6acfa7
JHS
707 if ((mark & x->mark.m) != x->mark.v)
708 continue;
02efdff7
FW
709 if (!xfrm_state_hold_rcu(x))
710 continue;
edcd5821
DM
711 return x;
712 }
713
714 return NULL;
715}
716
717static inline struct xfrm_state *
718__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
719{
221df1ed 720 struct net *net = xs_net(x);
bd55775c 721 u32 mark = x->mark.v & x->mark.m;
221df1ed 722
edcd5821 723 if (use_spi)
bd55775c
JHS
724 return __xfrm_state_lookup(net, mark, &x->id.daddr,
725 x->id.spi, x->id.proto, family);
edcd5821 726 else
bd55775c
JHS
727 return __xfrm_state_lookup_byaddr(net, mark,
728 &x->id.daddr,
edcd5821
DM
729 &x->props.saddr,
730 x->id.proto, family);
731}
732
98806f75 733static void xfrm_hash_grow_check(struct net *net, int have_hash_collision)
2fab22f2
PM
734{
735 if (have_hash_collision &&
98806f75
AD
736 (net->xfrm.state_hmask + 1) < xfrm_state_hashmax &&
737 net->xfrm.state_num > net->xfrm.state_hmask)
738 schedule_work(&net->xfrm.state_hash_work);
2fab22f2
PM
739}
740
08ec9af1 741static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
4a08ab0f 742 const struct flowi *fl, unsigned short family,
08ec9af1
DM
743 struct xfrm_state **best, int *acq_in_progress,
744 int *error)
745{
746 /* Resolution logic:
747 * 1. There is a valid state with matching selector. Done.
748 * 2. Valid state with inappropriate selector. Skip.
749 *
750 * Entering area of "sysdeps".
751 *
752 * 3. If state is not valid, selector is temporary, it selects
753 * only session which triggered previous resolution. Key
754 * manager will do something to install a state with proper
755 * selector.
756 */
757 if (x->km.state == XFRM_STATE_VALID) {
758 if ((x->sel.family &&
759 !xfrm_selector_match(&x->sel, fl, x->sel.family)) ||
760 !security_xfrm_state_pol_flow_match(x, pol, fl))
761 return;
762
763 if (!*best ||
764 (*best)->km.dying > x->km.dying ||
765 ((*best)->km.dying == x->km.dying &&
766 (*best)->curlft.add_time < x->curlft.add_time))
767 *best = x;
768 } else if (x->km.state == XFRM_STATE_ACQ) {
769 *acq_in_progress = 1;
770 } else if (x->km.state == XFRM_STATE_ERROR ||
771 x->km.state == XFRM_STATE_EXPIRED) {
772 if (xfrm_selector_match(&x->sel, fl, x->sel.family) &&
773 security_xfrm_state_pol_flow_match(x, pol, fl))
774 *error = -ESRCH;
775 }
776}
777
1da177e4 778struct xfrm_state *
33765d06 779xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
b520e9f6 780 const struct flowi *fl, struct xfrm_tmpl *tmpl,
1da177e4
LT
781 struct xfrm_policy *pol, int *err,
782 unsigned short family)
783{
08ec9af1 784 static xfrm_address_t saddr_wildcard = { };
5447c5e4 785 struct net *net = xp_net(pol);
6a783c90 786 unsigned int h, h_wildcard;
37b08e34 787 struct xfrm_state *x, *x0, *to_put;
1da177e4
LT
788 int acquire_in_progress = 0;
789 int error = 0;
790 struct xfrm_state *best = NULL;
bd55775c 791 u32 mark = pol->mark.v & pol->mark.m;
8444cf71 792 unsigned short encap_family = tmpl->encap_family;
b65e3d7b 793 unsigned int sequence;
0f24558e 794 struct km_event c;
a716c119 795
37b08e34
DM
796 to_put = NULL;
797
b65e3d7b
FW
798 sequence = read_seqcount_begin(&xfrm_state_hash_generation);
799
283bc9f3 800 spin_lock_bh(&net->xfrm.xfrm_state_lock);
8444cf71 801 h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family);
ae3fb6d3 802 hlist_for_each_entry_rcu(x, net->xfrm.state_bydst + h, bydst) {
8444cf71 803 if (x->props.family == encap_family &&
1da177e4 804 x->props.reqid == tmpl->reqid &&
3d6acfa7 805 (mark & x->mark.m) == x->mark.v &&
fbd9a5b4 806 !(x->props.flags & XFRM_STATE_WILDRECV) &&
8444cf71 807 xfrm_state_addr_check(x, daddr, saddr, encap_family) &&
1da177e4
LT
808 tmpl->mode == x->props.mode &&
809 tmpl->id.proto == x->id.proto &&
08ec9af1 810 (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
1f673c5f 811 xfrm_state_look_at(pol, x, fl, encap_family,
08ec9af1
DM
812 &best, &acquire_in_progress, &error);
813 }
6f115638 814 if (best || acquire_in_progress)
08ec9af1
DM
815 goto found;
816
8444cf71 817 h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, encap_family);
ae3fb6d3 818 hlist_for_each_entry_rcu(x, net->xfrm.state_bydst + h_wildcard, bydst) {
8444cf71 819 if (x->props.family == encap_family &&
08ec9af1 820 x->props.reqid == tmpl->reqid &&
3d6acfa7 821 (mark & x->mark.m) == x->mark.v &&
08ec9af1 822 !(x->props.flags & XFRM_STATE_WILDRECV) &&
f59bbdfa 823 xfrm_addr_equal(&x->id.daddr, daddr, encap_family) &&
08ec9af1
DM
824 tmpl->mode == x->props.mode &&
825 tmpl->id.proto == x->id.proto &&
826 (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
1f673c5f 827 xfrm_state_look_at(pol, x, fl, encap_family,
08ec9af1 828 &best, &acquire_in_progress, &error);
1da177e4
LT
829 }
830
08ec9af1 831found:
1da177e4
LT
832 x = best;
833 if (!x && !error && !acquire_in_progress) {
5c5d281a 834 if (tmpl->id.spi &&
bd55775c 835 (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi,
8444cf71 836 tmpl->id.proto, encap_family)) != NULL) {
37b08e34 837 to_put = x0;
1da177e4
LT
838 error = -EEXIST;
839 goto out;
840 }
0f24558e
HG
841
842 c.net = net;
843 /* If the KMs have no listeners (yet...), avoid allocating an SA
844 * for each and every packet - garbage collection might not
845 * handle the flood.
846 */
847 if (!km_is_alive(&c)) {
848 error = -ESRCH;
849 goto out;
850 }
851
5447c5e4 852 x = xfrm_state_alloc(net);
1da177e4
LT
853 if (x == NULL) {
854 error = -ENOMEM;
855 goto out;
856 }
8444cf71 857 /* Initialize temporary state matching only
1da177e4 858 * to current session. */
8444cf71 859 xfrm_init_tempstate(x, fl, tmpl, daddr, saddr, family);
bd55775c 860 memcpy(&x->mark, &pol->mark, sizeof(x->mark));
1da177e4 861
1d28f42c 862 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->flowi_secid);
e0d1caa7
VY
863 if (error) {
864 x->km.state = XFRM_STATE_DEAD;
37b08e34 865 to_put = x;
e0d1caa7
VY
866 x = NULL;
867 goto out;
868 }
869
1da177e4
LT
870 if (km_query(x, tmpl, pol) == 0) {
871 x->km.state = XFRM_STATE_ACQ;
5447c5e4 872 list_add(&x->km.all, &net->xfrm.state_all);
ae3fb6d3 873 hlist_add_head_rcu(&x->bydst, net->xfrm.state_bydst + h);
8444cf71 874 h = xfrm_src_hash(net, daddr, saddr, encap_family);
ae3fb6d3 875 hlist_add_head_rcu(&x->bysrc, net->xfrm.state_bysrc + h);
1da177e4 876 if (x->id.spi) {
8444cf71 877 h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, encap_family);
ae3fb6d3 878 hlist_add_head_rcu(&x->byspi, net->xfrm.state_byspi + h);
1da177e4 879 }
b27aeadb 880 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
9e0d57fd 881 tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL);
5447c5e4
AD
882 net->xfrm.state_num++;
883 xfrm_hash_grow_check(net, x->bydst.next != NULL);
1da177e4
LT
884 } else {
885 x->km.state = XFRM_STATE_DEAD;
37b08e34 886 to_put = x;
1da177e4
LT
887 x = NULL;
888 error = -ESRCH;
889 }
890 }
891out:
02efdff7
FW
892 if (x) {
893 if (!xfrm_state_hold_rcu(x)) {
894 *err = -EAGAIN;
895 x = NULL;
896 }
897 } else {
1da177e4 898 *err = acquire_in_progress ? -EAGAIN : error;
02efdff7 899 }
283bc9f3 900 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
37b08e34
DM
901 if (to_put)
902 xfrm_state_put(to_put);
b65e3d7b
FW
903
904 if (read_seqcount_retry(&xfrm_state_hash_generation, sequence)) {
905 *err = -EAGAIN;
906 if (x) {
907 xfrm_state_put(x);
908 x = NULL;
909 }
910 }
911
1da177e4
LT
912 return x;
913}
914
628529b6 915struct xfrm_state *
bd55775c 916xfrm_stateonly_find(struct net *net, u32 mark,
5447c5e4 917 xfrm_address_t *daddr, xfrm_address_t *saddr,
628529b6
JHS
918 unsigned short family, u8 mode, u8 proto, u32 reqid)
919{
4bda4f25 920 unsigned int h;
628529b6 921 struct xfrm_state *rx = NULL, *x = NULL;
628529b6 922
4ae770bf 923 spin_lock_bh(&net->xfrm.xfrm_state_lock);
5447c5e4 924 h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
b67bfe0d 925 hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) {
628529b6
JHS
926 if (x->props.family == family &&
927 x->props.reqid == reqid &&
3d6acfa7 928 (mark & x->mark.m) == x->mark.v &&
628529b6
JHS
929 !(x->props.flags & XFRM_STATE_WILDRECV) &&
930 xfrm_state_addr_check(x, daddr, saddr, family) &&
931 mode == x->props.mode &&
932 proto == x->id.proto &&
933 x->km.state == XFRM_STATE_VALID) {
934 rx = x;
935 break;
936 }
937 }
938
939 if (rx)
940 xfrm_state_hold(rx);
4ae770bf 941 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
628529b6
JHS
942
943
944 return rx;
945}
946EXPORT_SYMBOL(xfrm_stateonly_find);
947
c454997e
FD
948struct xfrm_state *xfrm_state_lookup_byspi(struct net *net, __be32 spi,
949 unsigned short family)
950{
951 struct xfrm_state *x;
952 struct xfrm_state_walk *w;
953
954 spin_lock_bh(&net->xfrm.xfrm_state_lock);
955 list_for_each_entry(w, &net->xfrm.state_all, all) {
956 x = container_of(w, struct xfrm_state, km);
957 if (x->props.family != family ||
958 x->id.spi != spi)
959 continue;
960
c454997e 961 xfrm_state_hold(x);
bdddbf69 962 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
c454997e
FD
963 return x;
964 }
965 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
966 return NULL;
967}
968EXPORT_SYMBOL(xfrm_state_lookup_byspi);
969
1da177e4
LT
970static void __xfrm_state_insert(struct xfrm_state *x)
971{
98806f75 972 struct net *net = xs_net(x);
a624c108 973 unsigned int h;
1da177e4 974
98806f75 975 list_add(&x->km.all, &net->xfrm.state_all);
4c563f76 976
98806f75 977 h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr,
c1969f29 978 x->props.reqid, x->props.family);
ae3fb6d3 979 hlist_add_head_rcu(&x->bydst, net->xfrm.state_bydst + h);
1da177e4 980
98806f75 981 h = xfrm_src_hash(net, &x->id.daddr, &x->props.saddr, x->props.family);
ae3fb6d3 982 hlist_add_head_rcu(&x->bysrc, net->xfrm.state_bysrc + h);
1da177e4 983
7b4dc360 984 if (x->id.spi) {
98806f75 985 h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto,
6c44e6b7
MN
986 x->props.family);
987
ae3fb6d3 988 hlist_add_head_rcu(&x->byspi, net->xfrm.state_byspi + h);
6c44e6b7
MN
989 }
990
9e0d57fd 991 tasklet_hrtimer_start(&x->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL);
a47f0ce0
DM
992 if (x->replay_maxage)
993 mod_timer(&x->rtimer, jiffies + x->replay_maxage);
f8cd5488 994
98806f75 995 net->xfrm.state_num++;
f034b5d4 996
98806f75 997 xfrm_hash_grow_check(net, x->bydst.next != NULL);
1da177e4
LT
998}
999
283bc9f3 1000/* net->xfrm.xfrm_state_lock is held */
c7f5ea3a
DM
1001static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
1002{
98806f75 1003 struct net *net = xs_net(xnew);
c7f5ea3a
DM
1004 unsigned short family = xnew->props.family;
1005 u32 reqid = xnew->props.reqid;
1006 struct xfrm_state *x;
c7f5ea3a 1007 unsigned int h;
3d6acfa7 1008 u32 mark = xnew->mark.v & xnew->mark.m;
c7f5ea3a 1009
98806f75 1010 h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family);
b67bfe0d 1011 hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) {
c7f5ea3a
DM
1012 if (x->props.family == family &&
1013 x->props.reqid == reqid &&
3d6acfa7 1014 (mark & x->mark.m) == x->mark.v &&
70e94e66
YH
1015 xfrm_addr_equal(&x->id.daddr, &xnew->id.daddr, family) &&
1016 xfrm_addr_equal(&x->props.saddr, &xnew->props.saddr, family))
34996cb9 1017 x->genid++;
c7f5ea3a
DM
1018 }
1019}
1020
1da177e4
LT
1021void xfrm_state_insert(struct xfrm_state *x)
1022{
283bc9f3
FD
1023 struct net *net = xs_net(x);
1024
1025 spin_lock_bh(&net->xfrm.xfrm_state_lock);
c7f5ea3a 1026 __xfrm_state_bump_genids(x);
1da177e4 1027 __xfrm_state_insert(x);
283bc9f3 1028 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
1da177e4
LT
1029}
1030EXPORT_SYMBOL(xfrm_state_insert);
1031
283bc9f3 1032/* net->xfrm.xfrm_state_lock is held */
e473fcb4
MK
1033static struct xfrm_state *__find_acq_core(struct net *net,
1034 const struct xfrm_mark *m,
a70486f0
DM
1035 unsigned short family, u8 mode,
1036 u32 reqid, u8 proto,
1037 const xfrm_address_t *daddr,
e473fcb4
MK
1038 const xfrm_address_t *saddr,
1039 int create)
2770834c 1040{
5447c5e4 1041 unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
2770834c 1042 struct xfrm_state *x;
3d6acfa7 1043 u32 mark = m->v & m->m;
2770834c 1044
b67bfe0d 1045 hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) {
2770834c
DM
1046 if (x->props.reqid != reqid ||
1047 x->props.mode != mode ||
1048 x->props.family != family ||
1049 x->km.state != XFRM_STATE_ACQ ||
75e252d9 1050 x->id.spi != 0 ||
1802571b 1051 x->id.proto != proto ||
3d6acfa7 1052 (mark & x->mark.m) != x->mark.v ||
70e94e66
YH
1053 !xfrm_addr_equal(&x->id.daddr, daddr, family) ||
1054 !xfrm_addr_equal(&x->props.saddr, saddr, family))
2770834c
DM
1055 continue;
1056
2770834c
DM
1057 xfrm_state_hold(x);
1058 return x;
1059 }
1060
1061 if (!create)
1062 return NULL;
1063
5447c5e4 1064 x = xfrm_state_alloc(net);
2770834c
DM
1065 if (likely(x)) {
1066 switch (family) {
1067 case AF_INET:
1068 x->sel.daddr.a4 = daddr->a4;
1069 x->sel.saddr.a4 = saddr->a4;
1070 x->sel.prefixlen_d = 32;
1071 x->sel.prefixlen_s = 32;
1072 x->props.saddr.a4 = saddr->a4;
1073 x->id.daddr.a4 = daddr->a4;
1074 break;
1075
1076 case AF_INET6:
15e318bd
JB
1077 x->sel.daddr.in6 = daddr->in6;
1078 x->sel.saddr.in6 = saddr->in6;
2770834c
DM
1079 x->sel.prefixlen_d = 128;
1080 x->sel.prefixlen_s = 128;
15e318bd
JB
1081 x->props.saddr.in6 = saddr->in6;
1082 x->id.daddr.in6 = daddr->in6;
2770834c 1083 break;
3ff50b79 1084 }
2770834c
DM
1085
1086 x->km.state = XFRM_STATE_ACQ;
1087 x->id.proto = proto;
1088 x->props.family = family;
1089 x->props.mode = mode;
1090 x->props.reqid = reqid;
bd55775c
JHS
1091 x->mark.v = m->v;
1092 x->mark.m = m->m;
b27aeadb 1093 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
2770834c 1094 xfrm_state_hold(x);
9e0d57fd 1095 tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL);
5447c5e4 1096 list_add(&x->km.all, &net->xfrm.state_all);
ae3fb6d3 1097 hlist_add_head_rcu(&x->bydst, net->xfrm.state_bydst + h);
5447c5e4 1098 h = xfrm_src_hash(net, daddr, saddr, family);
ae3fb6d3 1099 hlist_add_head_rcu(&x->bysrc, net->xfrm.state_bysrc + h);
918049f0 1100
5447c5e4 1101 net->xfrm.state_num++;
918049f0 1102
5447c5e4 1103 xfrm_hash_grow_check(net, x->bydst.next != NULL);
2770834c
DM
1104 }
1105
1106 return x;
1107}
1108
bd55775c 1109static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);
1da177e4
LT
1110
1111int xfrm_state_add(struct xfrm_state *x)
1112{
5447c5e4 1113 struct net *net = xs_net(x);
37b08e34 1114 struct xfrm_state *x1, *to_put;
1da177e4
LT
1115 int family;
1116 int err;
bd55775c 1117 u32 mark = x->mark.v & x->mark.m;
eb2971b6 1118 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
1da177e4
LT
1119
1120 family = x->props.family;
1da177e4 1121
37b08e34
DM
1122 to_put = NULL;
1123
283bc9f3 1124 spin_lock_bh(&net->xfrm.xfrm_state_lock);
1da177e4 1125
edcd5821 1126 x1 = __xfrm_state_locate(x, use_spi, family);
1da177e4 1127 if (x1) {
37b08e34 1128 to_put = x1;
1da177e4
LT
1129 x1 = NULL;
1130 err = -EEXIST;
1131 goto out;
1132 }
1133
eb2971b6 1134 if (use_spi && x->km.seq) {
bd55775c 1135 x1 = __xfrm_find_acq_byseq(net, mark, x->km.seq);
75e252d9 1136 if (x1 && ((x1->id.proto != x->id.proto) ||
70e94e66 1137 !xfrm_addr_equal(&x1->id.daddr, &x->id.daddr, family))) {
37b08e34 1138 to_put = x1;
1da177e4
LT
1139 x1 = NULL;
1140 }
1141 }
1142
eb2971b6 1143 if (use_spi && !x1)
bd55775c
JHS
1144 x1 = __find_acq_core(net, &x->mark, family, x->props.mode,
1145 x->props.reqid, x->id.proto,
2770834c 1146 &x->id.daddr, &x->props.saddr, 0);
1da177e4 1147
c7f5ea3a 1148 __xfrm_state_bump_genids(x);
1da177e4
LT
1149 __xfrm_state_insert(x);
1150 err = 0;
1151
1152out:
283bc9f3 1153 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
1da177e4
LT
1154
1155 if (x1) {
1156 xfrm_state_delete(x1);
1157 xfrm_state_put(x1);
1158 }
1159
37b08e34
DM
1160 if (to_put)
1161 xfrm_state_put(to_put);
1162
1da177e4
LT
1163 return err;
1164}
1165EXPORT_SYMBOL(xfrm_state_add);
1166
80c9abaa 1167#ifdef CONFIG_XFRM_MIGRATE
cc9ab60e 1168static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
80c9abaa 1169{
98806f75 1170 struct net *net = xs_net(orig);
98806f75 1171 struct xfrm_state *x = xfrm_state_alloc(net);
80c9abaa 1172 if (!x)
553f9118 1173 goto out;
80c9abaa
SS
1174
1175 memcpy(&x->id, &orig->id, sizeof(x->id));
1176 memcpy(&x->sel, &orig->sel, sizeof(x->sel));
1177 memcpy(&x->lft, &orig->lft, sizeof(x->lft));
1178 x->props.mode = orig->props.mode;
1179 x->props.replay_window = orig->props.replay_window;
1180 x->props.reqid = orig->props.reqid;
1181 x->props.family = orig->props.family;
1182 x->props.saddr = orig->props.saddr;
1183
1184 if (orig->aalg) {
4447bb33 1185 x->aalg = xfrm_algo_auth_clone(orig->aalg);
80c9abaa
SS
1186 if (!x->aalg)
1187 goto error;
1188 }
1189 x->props.aalgo = orig->props.aalgo;
1190
ee5c2317
SK
1191 if (orig->aead) {
1192 x->aead = xfrm_algo_aead_clone(orig->aead);
1193 if (!x->aead)
1194 goto error;
1195 }
80c9abaa
SS
1196 if (orig->ealg) {
1197 x->ealg = xfrm_algo_clone(orig->ealg);
1198 if (!x->ealg)
1199 goto error;
1200 }
1201 x->props.ealgo = orig->props.ealgo;
1202
1203 if (orig->calg) {
1204 x->calg = xfrm_algo_clone(orig->calg);
1205 if (!x->calg)
1206 goto error;
1207 }
1208 x->props.calgo = orig->props.calgo;
1209
a716c119 1210 if (orig->encap) {
80c9abaa
SS
1211 x->encap = kmemdup(orig->encap, sizeof(*x->encap), GFP_KERNEL);
1212 if (!x->encap)
1213 goto error;
1214 }
1215
1216 if (orig->coaddr) {
1217 x->coaddr = kmemdup(orig->coaddr, sizeof(*x->coaddr),
1218 GFP_KERNEL);
1219 if (!x->coaddr)
1220 goto error;
1221 }
1222
af2f464e 1223 if (orig->replay_esn) {
cc9ab60e 1224 if (xfrm_replay_clone(x, orig))
af2f464e
SK
1225 goto error;
1226 }
1227
bd55775c
JHS
1228 memcpy(&x->mark, &orig->mark, sizeof(x->mark));
1229
cc9ab60e 1230 if (xfrm_init_state(x) < 0)
80c9abaa
SS
1231 goto error;
1232
1233 x->props.flags = orig->props.flags;
a947b0a9 1234 x->props.extra_flags = orig->props.extra_flags;
80c9abaa 1235
ee5c2317
SK
1236 x->tfcpad = orig->tfcpad;
1237 x->replay_maxdiff = orig->replay_maxdiff;
1238 x->replay_maxage = orig->replay_maxage;
80c9abaa
SS
1239 x->curlft.add_time = orig->curlft.add_time;
1240 x->km.state = orig->km.state;
1241 x->km.seq = orig->km.seq;
1242
1243 return x;
1244
1245 error:
553f9118
HX
1246 xfrm_state_put(x);
1247out:
80c9abaa
SS
1248 return NULL;
1249}
80c9abaa 1250
283bc9f3 1251struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net)
80c9abaa
SS
1252{
1253 unsigned int h;
8c0cba22
SK
1254 struct xfrm_state *x = NULL;
1255
1256 spin_lock_bh(&net->xfrm.xfrm_state_lock);
80c9abaa
SS
1257
1258 if (m->reqid) {
283bc9f3 1259 h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr,
80c9abaa 1260 m->reqid, m->old_family);
283bc9f3 1261 hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) {
80c9abaa
SS
1262 if (x->props.mode != m->mode ||
1263 x->id.proto != m->proto)
1264 continue;
1265 if (m->reqid && x->props.reqid != m->reqid)
1266 continue;
70e94e66
YH
1267 if (!xfrm_addr_equal(&x->id.daddr, &m->old_daddr,
1268 m->old_family) ||
1269 !xfrm_addr_equal(&x->props.saddr, &m->old_saddr,
1270 m->old_family))
80c9abaa
SS
1271 continue;
1272 xfrm_state_hold(x);
8c0cba22 1273 break;
80c9abaa
SS
1274 }
1275 } else {
283bc9f3 1276 h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr,
80c9abaa 1277 m->old_family);
283bc9f3 1278 hlist_for_each_entry(x, net->xfrm.state_bysrc+h, bysrc) {
80c9abaa
SS
1279 if (x->props.mode != m->mode ||
1280 x->id.proto != m->proto)
1281 continue;
70e94e66
YH
1282 if (!xfrm_addr_equal(&x->id.daddr, &m->old_daddr,
1283 m->old_family) ||
1284 !xfrm_addr_equal(&x->props.saddr, &m->old_saddr,
1285 m->old_family))
80c9abaa
SS
1286 continue;
1287 xfrm_state_hold(x);
8c0cba22 1288 break;
80c9abaa
SS
1289 }
1290 }
1291
8c0cba22
SK
1292 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
1293
1294 return x;
80c9abaa
SS
1295}
1296EXPORT_SYMBOL(xfrm_migrate_state_find);
1297
3e94c2dc
WC
1298struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
1299 struct xfrm_migrate *m)
80c9abaa
SS
1300{
1301 struct xfrm_state *xc;
80c9abaa 1302
cc9ab60e 1303 xc = xfrm_state_clone(x);
80c9abaa
SS
1304 if (!xc)
1305 return NULL;
1306
1307 memcpy(&xc->id.daddr, &m->new_daddr, sizeof(xc->id.daddr));
1308 memcpy(&xc->props.saddr, &m->new_saddr, sizeof(xc->props.saddr));
1309
1310 /* add state */
70e94e66 1311 if (xfrm_addr_equal(&x->id.daddr, &m->new_daddr, m->new_family)) {
80c9abaa
SS
1312 /* a care is needed when the destination address of the
1313 state is to be updated as it is a part of triplet */
1314 xfrm_state_insert(xc);
1315 } else {
cc9ab60e 1316 if (xfrm_state_add(xc) < 0)
80c9abaa
SS
1317 goto error;
1318 }
1319
1320 return xc;
1321error:
78347c8c 1322 xfrm_state_put(xc);
80c9abaa
SS
1323 return NULL;
1324}
1325EXPORT_SYMBOL(xfrm_state_migrate);
1326#endif
1327
1da177e4
LT
1328int xfrm_state_update(struct xfrm_state *x)
1329{
37b08e34 1330 struct xfrm_state *x1, *to_put;
1da177e4 1331 int err;
eb2971b6 1332 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
283bc9f3 1333 struct net *net = xs_net(x);
1da177e4 1334
37b08e34
DM
1335 to_put = NULL;
1336
283bc9f3 1337 spin_lock_bh(&net->xfrm.xfrm_state_lock);
edcd5821 1338 x1 = __xfrm_state_locate(x, use_spi, x->props.family);
1da177e4
LT
1339
1340 err = -ESRCH;
1341 if (!x1)
1342 goto out;
1343
1344 if (xfrm_state_kern(x1)) {
37b08e34 1345 to_put = x1;
1da177e4
LT
1346 err = -EEXIST;
1347 goto out;
1348 }
1349
1350 if (x1->km.state == XFRM_STATE_ACQ) {
1351 __xfrm_state_insert(x);
1352 x = NULL;
1353 }
1354 err = 0;
1355
1356out:
283bc9f3 1357 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
1da177e4 1358
37b08e34
DM
1359 if (to_put)
1360 xfrm_state_put(to_put);
1361
1da177e4
LT
1362 if (err)
1363 return err;
1364
1365 if (!x) {
1366 xfrm_state_delete(x1);
1367 xfrm_state_put(x1);
1368 return 0;
1369 }
1370
1371 err = -EINVAL;
1372 spin_lock_bh(&x1->lock);
1373 if (likely(x1->km.state == XFRM_STATE_VALID)) {
1374 if (x->encap && x1->encap)
1375 memcpy(x1->encap, x->encap, sizeof(*x1->encap));
060f02a3
NT
1376 if (x->coaddr && x1->coaddr) {
1377 memcpy(x1->coaddr, x->coaddr, sizeof(*x1->coaddr));
1378 }
1379 if (!use_spi && memcmp(&x1->sel, &x->sel, sizeof(x1->sel)))
1380 memcpy(&x1->sel, &x->sel, sizeof(x1->sel));
1da177e4
LT
1381 memcpy(&x1->lft, &x->lft, sizeof(x1->lft));
1382 x1->km.dying = 0;
1383
9e0d57fd 1384 tasklet_hrtimer_start(&x1->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL);
1da177e4
LT
1385 if (x1->curlft.use_time)
1386 xfrm_state_check_expire(x1);
1387
1388 err = 0;
8fcbc637
TG
1389 x->km.state = XFRM_STATE_DEAD;
1390 __xfrm_state_put(x);
1da177e4
LT
1391 }
1392 spin_unlock_bh(&x1->lock);
1393
1394 xfrm_state_put(x1);
1395
1396 return err;
1397}
1398EXPORT_SYMBOL(xfrm_state_update);
1399
1400int xfrm_state_check_expire(struct xfrm_state *x)
1401{
1402 if (!x->curlft.use_time)
9d729f72 1403 x->curlft.use_time = get_seconds();
1da177e4 1404
1da177e4
LT
1405 if (x->curlft.bytes >= x->lft.hard_byte_limit ||
1406 x->curlft.packets >= x->lft.hard_packet_limit) {
4666faab 1407 x->km.state = XFRM_STATE_EXPIRED;
9b7a787d 1408 tasklet_hrtimer_start(&x->mtimer, ktime_set(0, 0), HRTIMER_MODE_REL);
1da177e4
LT
1409 return -EINVAL;
1410 }
1411
1412 if (!x->km.dying &&
1413 (x->curlft.bytes >= x->lft.soft_byte_limit ||
4666faab
HX
1414 x->curlft.packets >= x->lft.soft_packet_limit)) {
1415 x->km.dying = 1;
53bc6b4d 1416 km_state_expired(x, 0, 0);
4666faab 1417 }
1da177e4
LT
1418 return 0;
1419}
1420EXPORT_SYMBOL(xfrm_state_check_expire);
1421
1da177e4 1422struct xfrm_state *
a70486f0 1423xfrm_state_lookup(struct net *net, u32 mark, const xfrm_address_t *daddr, __be32 spi,
bd55775c 1424 u8 proto, unsigned short family)
1da177e4
LT
1425{
1426 struct xfrm_state *x;
1da177e4 1427
283bc9f3 1428 spin_lock_bh(&net->xfrm.xfrm_state_lock);
bd55775c 1429 x = __xfrm_state_lookup(net, mark, daddr, spi, proto, family);
283bc9f3 1430 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
1da177e4
LT
1431 return x;
1432}
1433EXPORT_SYMBOL(xfrm_state_lookup);
1434
1435struct xfrm_state *
bd55775c 1436xfrm_state_lookup_byaddr(struct net *net, u32 mark,
a70486f0 1437 const xfrm_address_t *daddr, const xfrm_address_t *saddr,
eb2971b6
MN
1438 u8 proto, unsigned short family)
1439{
1440 struct xfrm_state *x;
eb2971b6 1441
283bc9f3 1442 spin_lock_bh(&net->xfrm.xfrm_state_lock);
bd55775c 1443 x = __xfrm_state_lookup_byaddr(net, mark, daddr, saddr, proto, family);
283bc9f3 1444 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
eb2971b6
MN
1445 return x;
1446}
1447EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
1448
1449struct xfrm_state *
e473fcb4
MK
1450xfrm_find_acq(struct net *net, const struct xfrm_mark *mark, u8 mode, u32 reqid,
1451 u8 proto, const xfrm_address_t *daddr,
1452 const xfrm_address_t *saddr, int create, unsigned short family)
1da177e4
LT
1453{
1454 struct xfrm_state *x;
1da177e4 1455
283bc9f3 1456 spin_lock_bh(&net->xfrm.xfrm_state_lock);
bd55775c 1457 x = __find_acq_core(net, mark, family, mode, reqid, proto, daddr, saddr, create);
283bc9f3 1458 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
2770834c 1459
1da177e4
LT
1460 return x;
1461}
1462EXPORT_SYMBOL(xfrm_find_acq);
1463
41a49cc3
MN
1464#ifdef CONFIG_XFRM_SUB_POLICY
1465int
1466xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
283bc9f3 1467 unsigned short family, struct net *net)
41a49cc3
MN
1468{
1469 int err = 0;
1470 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
1471 if (!afinfo)
1472 return -EAFNOSUPPORT;
1473
283bc9f3 1474 spin_lock_bh(&net->xfrm.xfrm_state_lock); /*FIXME*/
41a49cc3
MN
1475 if (afinfo->tmpl_sort)
1476 err = afinfo->tmpl_sort(dst, src, n);
283bc9f3 1477 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
41a49cc3
MN
1478 xfrm_state_put_afinfo(afinfo);
1479 return err;
1480}
1481EXPORT_SYMBOL(xfrm_tmpl_sort);
1482
1483int
1484xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
1485 unsigned short family)
1486{
1487 int err = 0;
1488 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
35ea790d 1489 struct net *net = xs_net(*src);
283bc9f3 1490
41a49cc3
MN
1491 if (!afinfo)
1492 return -EAFNOSUPPORT;
1493
283bc9f3 1494 spin_lock_bh(&net->xfrm.xfrm_state_lock);
41a49cc3
MN
1495 if (afinfo->state_sort)
1496 err = afinfo->state_sort(dst, src, n);
283bc9f3 1497 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
41a49cc3
MN
1498 xfrm_state_put_afinfo(afinfo);
1499 return err;
1500}
1501EXPORT_SYMBOL(xfrm_state_sort);
1502#endif
1503
1da177e4
LT
1504/* Silly enough, but I'm lazy to build resolution list */
1505
bd55775c 1506static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
1da177e4
LT
1507{
1508 int i;
1da177e4 1509
5447c5e4 1510 for (i = 0; i <= net->xfrm.state_hmask; i++) {
8f126e37
DM
1511 struct xfrm_state *x;
1512
b67bfe0d 1513 hlist_for_each_entry(x, net->xfrm.state_bydst+i, bydst) {
8f126e37 1514 if (x->km.seq == seq &&
3d6acfa7 1515 (mark & x->mark.m) == x->mark.v &&
8f126e37 1516 x->km.state == XFRM_STATE_ACQ) {
1da177e4
LT
1517 xfrm_state_hold(x);
1518 return x;
1519 }
1520 }
1521 }
1522 return NULL;
1523}
1524
bd55775c 1525struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
1da177e4
LT
1526{
1527 struct xfrm_state *x;
1528
283bc9f3 1529 spin_lock_bh(&net->xfrm.xfrm_state_lock);
bd55775c 1530 x = __xfrm_find_acq_byseq(net, mark, seq);
283bc9f3 1531 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
1da177e4
LT
1532 return x;
1533}
1534EXPORT_SYMBOL(xfrm_find_acq_byseq);
1535
1536u32 xfrm_get_acqseq(void)
1537{
1538 u32 res;
6836b9bd 1539 static atomic_t acqseq;
1540
1541 do {
1542 res = atomic_inc_return(&acqseq);
1543 } while (!res);
1da177e4 1544
1da177e4
LT
1545 return res;
1546}
1547EXPORT_SYMBOL(xfrm_get_acqseq);
1548
776e9dd9
FD
1549int verify_spi_info(u8 proto, u32 min, u32 max)
1550{
1551 switch (proto) {
1552 case IPPROTO_AH:
1553 case IPPROTO_ESP:
1554 break;
1555
1556 case IPPROTO_COMP:
1557 /* IPCOMP spi is 16-bits. */
1558 if (max >= 0x10000)
1559 return -EINVAL;
1560 break;
1561
1562 default:
1563 return -EINVAL;
1564 }
1565
1566 if (min > max)
1567 return -EINVAL;
1568
1569 return 0;
1570}
1571EXPORT_SYMBOL(verify_spi_info);
1572
658b219e 1573int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1da177e4 1574{
221df1ed 1575 struct net *net = xs_net(x);
f034b5d4 1576 unsigned int h;
1da177e4 1577 struct xfrm_state *x0;
658b219e
HX
1578 int err = -ENOENT;
1579 __be32 minspi = htonl(low);
1580 __be32 maxspi = htonl(high);
bd55775c 1581 u32 mark = x->mark.v & x->mark.m;
1da177e4 1582
658b219e
HX
1583 spin_lock_bh(&x->lock);
1584 if (x->km.state == XFRM_STATE_DEAD)
1585 goto unlock;
1586
1587 err = 0;
1da177e4 1588 if (x->id.spi)
658b219e
HX
1589 goto unlock;
1590
1591 err = -ENOENT;
1da177e4
LT
1592
1593 if (minspi == maxspi) {
bd55775c 1594 x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family);
1da177e4
LT
1595 if (x0) {
1596 xfrm_state_put(x0);
658b219e 1597 goto unlock;
1da177e4
LT
1598 }
1599 x->id.spi = minspi;
1600 } else {
1601 u32 spi = 0;
9b7a787d 1602 for (h = 0; h < high-low+1; h++) {
63862b5b 1603 spi = low + prandom_u32()%(high-low+1);
bd55775c 1604 x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family);
1da177e4
LT
1605 if (x0 == NULL) {
1606 x->id.spi = htonl(spi);
1607 break;
1608 }
1609 xfrm_state_put(x0);
1610 }
1611 }
1612 if (x->id.spi) {
283bc9f3 1613 spin_lock_bh(&net->xfrm.xfrm_state_lock);
12604d8a 1614 h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family);
ae3fb6d3 1615 hlist_add_head_rcu(&x->byspi, net->xfrm.state_byspi + h);
283bc9f3 1616 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
658b219e
HX
1617
1618 err = 0;
1da177e4 1619 }
658b219e
HX
1620
1621unlock:
1622 spin_unlock_bh(&x->lock);
1623
1624 return err;
1da177e4
LT
1625}
1626EXPORT_SYMBOL(xfrm_alloc_spi);
1627
d3623099 1628static bool __xfrm_state_filter_match(struct xfrm_state *x,
870a2df4 1629 struct xfrm_address_filter *filter)
d3623099
ND
1630{
1631 if (filter) {
1632 if ((filter->family == AF_INET ||
1633 filter->family == AF_INET6) &&
1634 x->props.family != filter->family)
1635 return false;
1636
1637 return addr_match(&x->props.saddr, &filter->saddr,
1638 filter->splen) &&
1639 addr_match(&x->id.daddr, &filter->daddr,
1640 filter->dplen);
1641 }
1642 return true;
1643}
1644
284fa7da 1645int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
4c563f76 1646 int (*func)(struct xfrm_state *, int, void*),
1da177e4
LT
1647 void *data)
1648{
12a169e7
HX
1649 struct xfrm_state *state;
1650 struct xfrm_state_walk *x;
1da177e4
LT
1651 int err = 0;
1652
12a169e7 1653 if (walk->seq != 0 && list_empty(&walk->all))
4c563f76
TT
1654 return 0;
1655
283bc9f3 1656 spin_lock_bh(&net->xfrm.xfrm_state_lock);
12a169e7 1657 if (list_empty(&walk->all))
284fa7da 1658 x = list_first_entry(&net->xfrm.state_all, struct xfrm_state_walk, all);
12a169e7 1659 else
80077702 1660 x = list_first_entry(&walk->all, struct xfrm_state_walk, all);
284fa7da 1661 list_for_each_entry_from(x, &net->xfrm.state_all, all) {
12a169e7 1662 if (x->state == XFRM_STATE_DEAD)
4c563f76 1663 continue;
12a169e7
HX
1664 state = container_of(x, struct xfrm_state, km);
1665 if (!xfrm_id_proto_match(state->id.proto, walk->proto))
4c563f76 1666 continue;
d3623099
ND
1667 if (!__xfrm_state_filter_match(state, walk->filter))
1668 continue;
12a169e7
HX
1669 err = func(state, walk->seq, data);
1670 if (err) {
1671 list_move_tail(&walk->all, &x->all);
1672 goto out;
1da177e4 1673 }
12a169e7 1674 walk->seq++;
1da177e4 1675 }
12a169e7 1676 if (walk->seq == 0) {
1da177e4
LT
1677 err = -ENOENT;
1678 goto out;
1679 }
12a169e7 1680 list_del_init(&walk->all);
1da177e4 1681out:
283bc9f3 1682 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
1da177e4
LT
1683 return err;
1684}
1685EXPORT_SYMBOL(xfrm_state_walk);
1686
d3623099 1687void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto,
870a2df4 1688 struct xfrm_address_filter *filter)
5c182458 1689{
12a169e7 1690 INIT_LIST_HEAD(&walk->all);
5c182458 1691 walk->proto = proto;
12a169e7
HX
1692 walk->state = XFRM_STATE_DEAD;
1693 walk->seq = 0;
d3623099 1694 walk->filter = filter;
5c182458
HX
1695}
1696EXPORT_SYMBOL(xfrm_state_walk_init);
1697
283bc9f3 1698void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net)
abb81c4f 1699{
d3623099
ND
1700 kfree(walk->filter);
1701
12a169e7 1702 if (list_empty(&walk->all))
5c182458 1703 return;
5c182458 1704
283bc9f3 1705 spin_lock_bh(&net->xfrm.xfrm_state_lock);
12a169e7 1706 list_del(&walk->all);
283bc9f3 1707 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
abb81c4f
HX
1708}
1709EXPORT_SYMBOL(xfrm_state_walk_done);
1710
f8cd5488
JHS
1711static void xfrm_replay_timer_handler(unsigned long data)
1712{
3e94c2dc 1713 struct xfrm_state *x = (struct xfrm_state *)data;
f8cd5488
JHS
1714
1715 spin_lock(&x->lock);
1716
2717096a 1717 if (x->km.state == XFRM_STATE_VALID) {
a6483b79 1718 if (xfrm_aevent_is_on(xs_net(x)))
9fdc4883 1719 x->repl->notify(x, XFRM_REPLAY_TIMEOUT);
2717096a
JHS
1720 else
1721 x->xflags |= XFRM_TIME_DEFER;
1722 }
f8cd5488
JHS
1723
1724 spin_unlock(&x->lock);
1725}
1726
df01812e 1727static LIST_HEAD(xfrm_km_list);
1da177e4 1728
214e005b 1729void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
1da177e4
LT
1730{
1731 struct xfrm_mgr *km;
1732
85168c00
CW
1733 rcu_read_lock();
1734 list_for_each_entry_rcu(km, &xfrm_km_list, list)
26b15dad
JHS
1735 if (km->notify_policy)
1736 km->notify_policy(xp, dir, c);
85168c00 1737 rcu_read_unlock();
26b15dad 1738}
1da177e4 1739
214e005b 1740void km_state_notify(struct xfrm_state *x, const struct km_event *c)
26b15dad
JHS
1741{
1742 struct xfrm_mgr *km;
85168c00
CW
1743 rcu_read_lock();
1744 list_for_each_entry_rcu(km, &xfrm_km_list, list)
26b15dad
JHS
1745 if (km->notify)
1746 km->notify(x, c);
85168c00 1747 rcu_read_unlock();
26b15dad
JHS
1748}
1749
1750EXPORT_SYMBOL(km_policy_notify);
1751EXPORT_SYMBOL(km_state_notify);
1752
15e47304 1753void km_state_expired(struct xfrm_state *x, int hard, u32 portid)
26b15dad
JHS
1754{
1755 struct km_event c;
1756
bf08867f 1757 c.data.hard = hard;
15e47304 1758 c.portid = portid;
f60f6b8f 1759 c.event = XFRM_MSG_EXPIRE;
26b15dad 1760 km_state_notify(x, &c);
1da177e4
LT
1761}
1762
53bc6b4d 1763EXPORT_SYMBOL(km_state_expired);
26b15dad
JHS
1764/*
1765 * We send to all registered managers regardless of failure
1766 * We are happy with one success
1767*/
980ebd25 1768int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
1da177e4 1769{
26b15dad 1770 int err = -EINVAL, acqret;
1da177e4
LT
1771 struct xfrm_mgr *km;
1772
85168c00
CW
1773 rcu_read_lock();
1774 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
65e0736b 1775 acqret = km->acquire(x, t, pol);
26b15dad
JHS
1776 if (!acqret)
1777 err = acqret;
1da177e4 1778 }
85168c00 1779 rcu_read_unlock();
1da177e4
LT
1780 return err;
1781}
980ebd25 1782EXPORT_SYMBOL(km_query);
1da177e4 1783
5d36b180 1784int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
1da177e4
LT
1785{
1786 int err = -EINVAL;
1787 struct xfrm_mgr *km;
1788
85168c00
CW
1789 rcu_read_lock();
1790 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1da177e4
LT
1791 if (km->new_mapping)
1792 err = km->new_mapping(x, ipaddr, sport);
1793 if (!err)
1794 break;
1795 }
85168c00 1796 rcu_read_unlock();
1da177e4
LT
1797 return err;
1798}
1799EXPORT_SYMBOL(km_new_mapping);
1800
15e47304 1801void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid)
1da177e4 1802{
26b15dad 1803 struct km_event c;
1da177e4 1804
bf08867f 1805 c.data.hard = hard;
15e47304 1806 c.portid = portid;
f60f6b8f 1807 c.event = XFRM_MSG_POLEXPIRE;
26b15dad 1808 km_policy_notify(pol, dir, &c);
1da177e4 1809}
a70fcb0b 1810EXPORT_SYMBOL(km_policy_expired);
1da177e4 1811
2d60abc2 1812#ifdef CONFIG_XFRM_MIGRATE
183cad12
DM
1813int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
1814 const struct xfrm_migrate *m, int num_migrate,
1815 const struct xfrm_kmaddress *k)
80c9abaa
SS
1816{
1817 int err = -EINVAL;
1818 int ret;
1819 struct xfrm_mgr *km;
1820
85168c00
CW
1821 rcu_read_lock();
1822 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
80c9abaa 1823 if (km->migrate) {
13c1d189 1824 ret = km->migrate(sel, dir, type, m, num_migrate, k);
80c9abaa
SS
1825 if (!ret)
1826 err = ret;
1827 }
1828 }
85168c00 1829 rcu_read_unlock();
80c9abaa
SS
1830 return err;
1831}
1832EXPORT_SYMBOL(km_migrate);
2d60abc2 1833#endif
80c9abaa 1834
db983c11 1835int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr)
97a64b45
MN
1836{
1837 int err = -EINVAL;
1838 int ret;
1839 struct xfrm_mgr *km;
1840
85168c00
CW
1841 rcu_read_lock();
1842 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
97a64b45 1843 if (km->report) {
db983c11 1844 ret = km->report(net, proto, sel, addr);
97a64b45
MN
1845 if (!ret)
1846 err = ret;
1847 }
1848 }
85168c00 1849 rcu_read_unlock();
97a64b45
MN
1850 return err;
1851}
1852EXPORT_SYMBOL(km_report);
1853
0f24558e
HG
1854bool km_is_alive(const struct km_event *c)
1855{
1856 struct xfrm_mgr *km;
1857 bool is_alive = false;
1858
1859 rcu_read_lock();
1860 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1861 if (km->is_alive && km->is_alive(c)) {
1862 is_alive = true;
1863 break;
1864 }
1865 }
1866 rcu_read_unlock();
1867
1868 return is_alive;
1869}
1870EXPORT_SYMBOL(km_is_alive);
1871
1da177e4
LT
1872int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
1873{
1874 int err;
1875 u8 *data;
1876 struct xfrm_mgr *km;
1877 struct xfrm_policy *pol = NULL;
1878
1879 if (optlen <= 0 || optlen > PAGE_SIZE)
1880 return -EMSGSIZE;
1881
1882 data = kmalloc(optlen, GFP_KERNEL);
1883 if (!data)
1884 return -ENOMEM;
1885
1886 err = -EFAULT;
1887 if (copy_from_user(data, optval, optlen))
1888 goto out;
1889
1890 err = -EINVAL;
85168c00
CW
1891 rcu_read_lock();
1892 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
cb969f07 1893 pol = km->compile_policy(sk, optname, data,
1da177e4
LT
1894 optlen, &err);
1895 if (err >= 0)
1896 break;
1897 }
85168c00 1898 rcu_read_unlock();
1da177e4
LT
1899
1900 if (err >= 0) {
1901 xfrm_sk_policy_insert(sk, err, pol);
1902 xfrm_pol_put(pol);
1903 err = 0;
1904 }
1905
1906out:
1907 kfree(data);
1908 return err;
1909}
1910EXPORT_SYMBOL(xfrm_user_policy);
1911
85168c00
CW
1912static DEFINE_SPINLOCK(xfrm_km_lock);
1913
1da177e4
LT
1914int xfrm_register_km(struct xfrm_mgr *km)
1915{
85168c00
CW
1916 spin_lock_bh(&xfrm_km_lock);
1917 list_add_tail_rcu(&km->list, &xfrm_km_list);
1918 spin_unlock_bh(&xfrm_km_lock);
1da177e4
LT
1919 return 0;
1920}
1921EXPORT_SYMBOL(xfrm_register_km);
1922
1923int xfrm_unregister_km(struct xfrm_mgr *km)
1924{
85168c00
CW
1925 spin_lock_bh(&xfrm_km_lock);
1926 list_del_rcu(&km->list);
1927 spin_unlock_bh(&xfrm_km_lock);
1928 synchronize_rcu();
1da177e4
LT
1929 return 0;
1930}
1931EXPORT_SYMBOL(xfrm_unregister_km);
1932
1933int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
1934{
1935 int err = 0;
1936 if (unlikely(afinfo == NULL))
1937 return -EINVAL;
1938 if (unlikely(afinfo->family >= NPROTO))
1939 return -EAFNOSUPPORT;
44abdc30 1940 spin_lock_bh(&xfrm_state_afinfo_lock);
1da177e4 1941 if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
f31e8d4f 1942 err = -EEXIST;
edcd5821 1943 else
44abdc30
CW
1944 rcu_assign_pointer(xfrm_state_afinfo[afinfo->family], afinfo);
1945 spin_unlock_bh(&xfrm_state_afinfo_lock);
1da177e4
LT
1946 return err;
1947}
1948EXPORT_SYMBOL(xfrm_state_register_afinfo);
1949
1950int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
1951{
1952 int err = 0;
1953 if (unlikely(afinfo == NULL))
1954 return -EINVAL;
1955 if (unlikely(afinfo->family >= NPROTO))
1956 return -EAFNOSUPPORT;
44abdc30 1957 spin_lock_bh(&xfrm_state_afinfo_lock);
1da177e4
LT
1958 if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
1959 if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
1960 err = -EINVAL;
edcd5821 1961 else
44abdc30 1962 RCU_INIT_POINTER(xfrm_state_afinfo[afinfo->family], NULL);
1da177e4 1963 }
44abdc30
CW
1964 spin_unlock_bh(&xfrm_state_afinfo_lock);
1965 synchronize_rcu();
1da177e4
LT
1966 return err;
1967}
1968EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
1969
628e341f 1970struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
1da177e4
LT
1971{
1972 struct xfrm_state_afinfo *afinfo;
1973 if (unlikely(family >= NPROTO))
1974 return NULL;
44abdc30
CW
1975 rcu_read_lock();
1976 afinfo = rcu_dereference(xfrm_state_afinfo[family]);
546be240 1977 if (unlikely(!afinfo))
44abdc30 1978 rcu_read_unlock();
1da177e4
LT
1979 return afinfo;
1980}
1981
628e341f 1982void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
1da177e4 1983{
44abdc30 1984 rcu_read_unlock();
1da177e4
LT
1985}
1986
1987/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
1988void xfrm_state_delete_tunnel(struct xfrm_state *x)
1989{
1990 if (x->tunnel) {
1991 struct xfrm_state *t = x->tunnel;
1992
1993 if (atomic_read(&t->tunnel_users) == 2)
1994 xfrm_state_delete(t);
1995 atomic_dec(&t->tunnel_users);
1996 xfrm_state_put(t);
1997 x->tunnel = NULL;
1998 }
1999}
2000EXPORT_SYMBOL(xfrm_state_delete_tunnel);
2001
2002int xfrm_state_mtu(struct xfrm_state *x, int mtu)
2003{
c5c25238 2004 int res;
1da177e4 2005
c5c25238
PM
2006 spin_lock_bh(&x->lock);
2007 if (x->km.state == XFRM_STATE_VALID &&
2008 x->type && x->type->get_mtu)
2009 res = x->type->get_mtu(x, mtu);
2010 else
28121617 2011 res = mtu - x->props.header_len;
c5c25238 2012 spin_unlock_bh(&x->lock);
1da177e4
LT
2013 return res;
2014}
2015
a454f0cc 2016int __xfrm_init_state(struct xfrm_state *x, bool init_replay)
72cb6962 2017{
d094cd83 2018 struct xfrm_state_afinfo *afinfo;
df9dcb45 2019 struct xfrm_mode *inner_mode;
d094cd83 2020 int family = x->props.family;
72cb6962
HX
2021 int err;
2022
d094cd83
HX
2023 err = -EAFNOSUPPORT;
2024 afinfo = xfrm_state_get_afinfo(family);
2025 if (!afinfo)
2026 goto error;
2027
2028 err = 0;
2029 if (afinfo->init_flags)
2030 err = afinfo->init_flags(x);
2031
2032 xfrm_state_put_afinfo(afinfo);
2033
2034 if (err)
2035 goto error;
2036
2037 err = -EPROTONOSUPPORT;
13996378 2038
df9dcb45
KM
2039 if (x->sel.family != AF_UNSPEC) {
2040 inner_mode = xfrm_get_mode(x->props.mode, x->sel.family);
2041 if (inner_mode == NULL)
2042 goto error;
2043
2044 if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
2045 family != x->sel.family) {
2046 xfrm_put_mode(inner_mode);
2047 goto error;
2048 }
2049
2050 x->inner_mode = inner_mode;
2051 } else {
2052 struct xfrm_mode *inner_mode_iaf;
d81d2285 2053 int iafamily = AF_INET;
df9dcb45 2054
d81d2285 2055 inner_mode = xfrm_get_mode(x->props.mode, x->props.family);
df9dcb45
KM
2056 if (inner_mode == NULL)
2057 goto error;
2058
2059 if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) {
2060 xfrm_put_mode(inner_mode);
2061 goto error;
2062 }
d81d2285 2063 x->inner_mode = inner_mode;
df9dcb45 2064
d81d2285
MW
2065 if (x->props.family == AF_INET)
2066 iafamily = AF_INET6;
df9dcb45 2067
d81d2285
MW
2068 inner_mode_iaf = xfrm_get_mode(x->props.mode, iafamily);
2069 if (inner_mode_iaf) {
2070 if (inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)
2071 x->inner_mode_iaf = inner_mode_iaf;
2072 else
2073 xfrm_put_mode(inner_mode_iaf);
df9dcb45
KM
2074 }
2075 }
13996378 2076
d094cd83 2077 x->type = xfrm_get_type(x->id.proto, family);
72cb6962
HX
2078 if (x->type == NULL)
2079 goto error;
2080
2081 err = x->type->init_state(x);
2082 if (err)
2083 goto error;
2084
13996378 2085 x->outer_mode = xfrm_get_mode(x->props.mode, family);
599901c3
JL
2086 if (x->outer_mode == NULL) {
2087 err = -EPROTONOSUPPORT;
b59f45d0 2088 goto error;
599901c3 2089 }
b59f45d0 2090
a454f0cc
WY
2091 if (init_replay) {
2092 err = xfrm_init_replay(x);
2093 if (err)
2094 goto error;
2095 }
2096
72cb6962
HX
2097 x->km.state = XFRM_STATE_VALID;
2098
2099error:
2100 return err;
2101}
2102
a454f0cc
WY
2103EXPORT_SYMBOL(__xfrm_init_state);
2104
2105int xfrm_init_state(struct xfrm_state *x)
2106{
2107 return __xfrm_init_state(x, true);
2108}
2109
72cb6962 2110EXPORT_SYMBOL(xfrm_init_state);
a716c119 2111
d62ddc21 2112int __net_init xfrm_state_init(struct net *net)
1da177e4 2113{
f034b5d4
DM
2114 unsigned int sz;
2115
9d4139c7
AD
2116 INIT_LIST_HEAD(&net->xfrm.state_all);
2117
f034b5d4
DM
2118 sz = sizeof(struct hlist_head) * 8;
2119
73d189dc
AD
2120 net->xfrm.state_bydst = xfrm_hash_alloc(sz);
2121 if (!net->xfrm.state_bydst)
2122 goto out_bydst;
d320bbb3
AD
2123 net->xfrm.state_bysrc = xfrm_hash_alloc(sz);
2124 if (!net->xfrm.state_bysrc)
2125 goto out_bysrc;
b754a4fd
AD
2126 net->xfrm.state_byspi = xfrm_hash_alloc(sz);
2127 if (!net->xfrm.state_byspi)
2128 goto out_byspi;
529983ec 2129 net->xfrm.state_hmask = ((sz / sizeof(struct hlist_head)) - 1);
1da177e4 2130
0bf7c5b0 2131 net->xfrm.state_num = 0;
63082733 2132 INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize);
b8a0ae20 2133 INIT_HLIST_HEAD(&net->xfrm.state_gc_list);
c7837144 2134 INIT_WORK(&net->xfrm.state_gc_work, xfrm_state_gc_task);
283bc9f3 2135 spin_lock_init(&net->xfrm.xfrm_state_lock);
d62ddc21 2136 return 0;
73d189dc 2137
b754a4fd
AD
2138out_byspi:
2139 xfrm_hash_free(net->xfrm.state_bysrc, sz);
d320bbb3
AD
2140out_bysrc:
2141 xfrm_hash_free(net->xfrm.state_bydst, sz);
73d189dc
AD
2142out_bydst:
2143 return -ENOMEM;
d62ddc21
AD
2144}
2145
2146void xfrm_state_fini(struct net *net)
2147{
73d189dc
AD
2148 unsigned int sz;
2149
7c2776ee 2150 flush_work(&net->xfrm.state_hash_work);
2e71029e 2151 xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
7c2776ee
AD
2152 flush_work(&net->xfrm.state_gc_work);
2153
9d4139c7 2154 WARN_ON(!list_empty(&net->xfrm.state_all));
73d189dc 2155
529983ec 2156 sz = (net->xfrm.state_hmask + 1) * sizeof(struct hlist_head);
b754a4fd
AD
2157 WARN_ON(!hlist_empty(net->xfrm.state_byspi));
2158 xfrm_hash_free(net->xfrm.state_byspi, sz);
d320bbb3
AD
2159 WARN_ON(!hlist_empty(net->xfrm.state_bysrc));
2160 xfrm_hash_free(net->xfrm.state_bysrc, sz);
73d189dc
AD
2161 WARN_ON(!hlist_empty(net->xfrm.state_bydst));
2162 xfrm_hash_free(net->xfrm.state_bydst, sz);
1da177e4
LT
2163}
2164
ab5f5e8b 2165#ifdef CONFIG_AUDITSYSCALL
cf35f43e
IJ
2166static void xfrm_audit_helper_sainfo(struct xfrm_state *x,
2167 struct audit_buffer *audit_buf)
ab5f5e8b 2168{
68277acc
PM
2169 struct xfrm_sec_ctx *ctx = x->security;
2170 u32 spi = ntohl(x->id.spi);
2171
2172 if (ctx)
ab5f5e8b 2173 audit_log_format(audit_buf, " sec_alg=%u sec_doi=%u sec_obj=%s",
68277acc 2174 ctx->ctx_alg, ctx->ctx_doi, ctx->ctx_str);
ab5f5e8b 2175
9b7a787d 2176 switch (x->props.family) {
ab5f5e8b 2177 case AF_INET:
21454aaa
HH
2178 audit_log_format(audit_buf, " src=%pI4 dst=%pI4",
2179 &x->props.saddr.a4, &x->id.daddr.a4);
ab5f5e8b
JL
2180 break;
2181 case AF_INET6:
5b095d98 2182 audit_log_format(audit_buf, " src=%pI6 dst=%pI6",
fdb46ee7 2183 x->props.saddr.a6, x->id.daddr.a6);
ab5f5e8b
JL
2184 break;
2185 }
68277acc
PM
2186
2187 audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
ab5f5e8b
JL
2188}
2189
cf35f43e
IJ
2190static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family,
2191 struct audit_buffer *audit_buf)
afeb14b4 2192{
b71d1d42
ED
2193 const struct iphdr *iph4;
2194 const struct ipv6hdr *iph6;
afeb14b4
PM
2195
2196 switch (family) {
2197 case AF_INET:
2198 iph4 = ip_hdr(skb);
21454aaa
HH
2199 audit_log_format(audit_buf, " src=%pI4 dst=%pI4",
2200 &iph4->saddr, &iph4->daddr);
afeb14b4
PM
2201 break;
2202 case AF_INET6:
2203 iph6 = ipv6_hdr(skb);
2204 audit_log_format(audit_buf,
5b095d98 2205 " src=%pI6 dst=%pI6 flowlbl=0x%x%02x%02x",
9b7a787d 2206 &iph6->saddr, &iph6->daddr,
afeb14b4
PM
2207 iph6->flow_lbl[0] & 0x0f,
2208 iph6->flow_lbl[1],
2209 iph6->flow_lbl[2]);
2210 break;
2211 }
2212}
2213
2e71029e 2214void xfrm_audit_state_add(struct xfrm_state *x, int result, bool task_valid)
ab5f5e8b
JL
2215{
2216 struct audit_buffer *audit_buf;
ab5f5e8b 2217
afeb14b4 2218 audit_buf = xfrm_audit_start("SAD-add");
ab5f5e8b
JL
2219 if (audit_buf == NULL)
2220 return;
2e71029e 2221 xfrm_audit_helper_usrinfo(task_valid, audit_buf);
afeb14b4
PM
2222 xfrm_audit_helper_sainfo(x, audit_buf);
2223 audit_log_format(audit_buf, " res=%u", result);
ab5f5e8b
JL
2224 audit_log_end(audit_buf);
2225}
2226EXPORT_SYMBOL_GPL(xfrm_audit_state_add);
2227
2e71029e 2228void xfrm_audit_state_delete(struct xfrm_state *x, int result, bool task_valid)
ab5f5e8b
JL
2229{
2230 struct audit_buffer *audit_buf;
ab5f5e8b 2231
afeb14b4 2232 audit_buf = xfrm_audit_start("SAD-delete");
ab5f5e8b
JL
2233 if (audit_buf == NULL)
2234 return;
2e71029e 2235 xfrm_audit_helper_usrinfo(task_valid, audit_buf);
afeb14b4
PM
2236 xfrm_audit_helper_sainfo(x, audit_buf);
2237 audit_log_format(audit_buf, " res=%u", result);
ab5f5e8b
JL
2238 audit_log_end(audit_buf);
2239}
2240EXPORT_SYMBOL_GPL(xfrm_audit_state_delete);
afeb14b4
PM
2241
2242void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
2243 struct sk_buff *skb)
2244{
2245 struct audit_buffer *audit_buf;
2246 u32 spi;
2247
2248 audit_buf = xfrm_audit_start("SA-replay-overflow");
2249 if (audit_buf == NULL)
2250 return;
2251 xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
2252 /* don't record the sequence number because it's inherent in this kind
2253 * of audit message */
2254 spi = ntohl(x->id.spi);
2255 audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
2256 audit_log_end(audit_buf);
2257}
2258EXPORT_SYMBOL_GPL(xfrm_audit_state_replay_overflow);
2259
9fdc4883 2260void xfrm_audit_state_replay(struct xfrm_state *x,
afeb14b4
PM
2261 struct sk_buff *skb, __be32 net_seq)
2262{
2263 struct audit_buffer *audit_buf;
2264 u32 spi;
2265
2266 audit_buf = xfrm_audit_start("SA-replayed-pkt");
2267 if (audit_buf == NULL)
2268 return;
2269 xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
2270 spi = ntohl(x->id.spi);
2271 audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
2272 spi, spi, ntohl(net_seq));
2273 audit_log_end(audit_buf);
2274}
9fdc4883 2275EXPORT_SYMBOL_GPL(xfrm_audit_state_replay);
afeb14b4
PM
2276
2277void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family)
2278{
2279 struct audit_buffer *audit_buf;
2280
2281 audit_buf = xfrm_audit_start("SA-notfound");
2282 if (audit_buf == NULL)
2283 return;
2284 xfrm_audit_helper_pktinfo(skb, family, audit_buf);
2285 audit_log_end(audit_buf);
2286}
2287EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound_simple);
2288
2289void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
2290 __be32 net_spi, __be32 net_seq)
2291{
2292 struct audit_buffer *audit_buf;
2293 u32 spi;
2294
2295 audit_buf = xfrm_audit_start("SA-notfound");
2296 if (audit_buf == NULL)
2297 return;
2298 xfrm_audit_helper_pktinfo(skb, family, audit_buf);
2299 spi = ntohl(net_spi);
2300 audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
2301 spi, spi, ntohl(net_seq));
2302 audit_log_end(audit_buf);
2303}
2304EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound);
2305
2306void xfrm_audit_state_icvfail(struct xfrm_state *x,
2307 struct sk_buff *skb, u8 proto)
2308{
2309 struct audit_buffer *audit_buf;
2310 __be32 net_spi;
2311 __be32 net_seq;
2312
2313 audit_buf = xfrm_audit_start("SA-icv-failure");
2314 if (audit_buf == NULL)
2315 return;
2316 xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
2317 if (xfrm_parse_spi(skb, proto, &net_spi, &net_seq) == 0) {
2318 u32 spi = ntohl(net_spi);
2319 audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
2320 spi, spi, ntohl(net_seq));
2321 }
2322 audit_log_end(audit_buf);
2323}
2324EXPORT_SYMBOL_GPL(xfrm_audit_state_icvfail);
ab5f5e8b 2325#endif /* CONFIG_AUDITSYSCALL */