[XFRM]: xfrm audit calls
[deliverable/linux.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>
b5890d8b 22#include <asm/uaccess.h>
1da177e4 23
44e36b42
DM
24#include "xfrm_hash.h"
25
ee857a7d
DM
26struct sock *xfrm_nl;
27EXPORT_SYMBOL(xfrm_nl);
28
01e67d08 29u32 sysctl_xfrm_aevent_etime __read_mostly = XFRM_AE_ETIME;
a70fcb0b
DM
30EXPORT_SYMBOL(sysctl_xfrm_aevent_etime);
31
01e67d08 32u32 sysctl_xfrm_aevent_rseqth __read_mostly = XFRM_AE_SEQT_SIZE;
a70fcb0b
DM
33EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);
34
01e67d08
DM
35u32 sysctl_xfrm_acq_expires __read_mostly = 30;
36
1da177e4
LT
37/* Each xfrm_state may be linked to two tables:
38
39 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
a624c108 40 2. Hash table by (daddr,family,reqid) to find what SAs exist for given
1da177e4
LT
41 destination/tunnel endpoint. (output)
42 */
43
44static DEFINE_SPINLOCK(xfrm_state_lock);
45
46/* Hash table to find appropriate SA towards given target (endpoint
47 * of tunnel or destination of transport mode) allowed by selector.
48 *
49 * Main use is finding SA after policy selected tunnel or transport mode.
50 * Also, it can be used by ah/esp icmp error handler to find offending SA.
51 */
f034b5d4
DM
52static struct hlist_head *xfrm_state_bydst __read_mostly;
53static struct hlist_head *xfrm_state_bysrc __read_mostly;
54static struct hlist_head *xfrm_state_byspi __read_mostly;
55static unsigned int xfrm_state_hmask __read_mostly;
56static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
57static unsigned int xfrm_state_num;
9d4a706d 58static unsigned int xfrm_state_genid;
f034b5d4 59
c1969f29
DM
60static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
61 xfrm_address_t *saddr,
62 u32 reqid,
a624c108 63 unsigned short family)
f034b5d4 64{
c1969f29 65 return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask);
f034b5d4
DM
66}
67
667bbcb6
MN
68static inline unsigned int xfrm_src_hash(xfrm_address_t *daddr,
69 xfrm_address_t *saddr,
44e36b42 70 unsigned short family)
f034b5d4 71{
667bbcb6 72 return __xfrm_src_hash(daddr, saddr, family, xfrm_state_hmask);
f034b5d4
DM
73}
74
f034b5d4 75static inline unsigned int
8122adf0 76xfrm_spi_hash(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
f034b5d4 77{
c1969f29 78 return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask);
f034b5d4
DM
79}
80
f034b5d4
DM
81static void xfrm_hash_transfer(struct hlist_head *list,
82 struct hlist_head *ndsttable,
83 struct hlist_head *nsrctable,
84 struct hlist_head *nspitable,
85 unsigned int nhashmask)
86{
87 struct hlist_node *entry, *tmp;
88 struct xfrm_state *x;
89
90 hlist_for_each_entry_safe(x, entry, tmp, list, bydst) {
91 unsigned int h;
92
c1969f29
DM
93 h = __xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
94 x->props.reqid, x->props.family,
95 nhashmask);
f034b5d4
DM
96 hlist_add_head(&x->bydst, ndsttable+h);
97
667bbcb6
MN
98 h = __xfrm_src_hash(&x->id.daddr, &x->props.saddr,
99 x->props.family,
f034b5d4
DM
100 nhashmask);
101 hlist_add_head(&x->bysrc, nsrctable+h);
102
7b4dc360
MN
103 if (x->id.spi) {
104 h = __xfrm_spi_hash(&x->id.daddr, x->id.spi,
105 x->id.proto, x->props.family,
106 nhashmask);
107 hlist_add_head(&x->byspi, nspitable+h);
108 }
f034b5d4
DM
109 }
110}
111
112static unsigned long xfrm_hash_new_size(void)
113{
114 return ((xfrm_state_hmask + 1) << 1) *
115 sizeof(struct hlist_head);
116}
117
118static DEFINE_MUTEX(hash_resize_mutex);
119
c4028958 120static void xfrm_hash_resize(struct work_struct *__unused)
f034b5d4
DM
121{
122 struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi;
123 unsigned long nsize, osize;
124 unsigned int nhashmask, ohashmask;
125 int i;
126
127 mutex_lock(&hash_resize_mutex);
128
129 nsize = xfrm_hash_new_size();
44e36b42 130 ndst = xfrm_hash_alloc(nsize);
f034b5d4
DM
131 if (!ndst)
132 goto out_unlock;
44e36b42 133 nsrc = xfrm_hash_alloc(nsize);
f034b5d4 134 if (!nsrc) {
44e36b42 135 xfrm_hash_free(ndst, nsize);
f034b5d4
DM
136 goto out_unlock;
137 }
44e36b42 138 nspi = xfrm_hash_alloc(nsize);
f034b5d4 139 if (!nspi) {
44e36b42
DM
140 xfrm_hash_free(ndst, nsize);
141 xfrm_hash_free(nsrc, nsize);
f034b5d4
DM
142 goto out_unlock;
143 }
144
145 spin_lock_bh(&xfrm_state_lock);
146
147 nhashmask = (nsize / sizeof(struct hlist_head)) - 1U;
148 for (i = xfrm_state_hmask; i >= 0; i--)
149 xfrm_hash_transfer(xfrm_state_bydst+i, ndst, nsrc, nspi,
150 nhashmask);
151
152 odst = xfrm_state_bydst;
153 osrc = xfrm_state_bysrc;
154 ospi = xfrm_state_byspi;
155 ohashmask = xfrm_state_hmask;
156
157 xfrm_state_bydst = ndst;
158 xfrm_state_bysrc = nsrc;
159 xfrm_state_byspi = nspi;
160 xfrm_state_hmask = nhashmask;
161
162 spin_unlock_bh(&xfrm_state_lock);
163
164 osize = (ohashmask + 1) * sizeof(struct hlist_head);
44e36b42
DM
165 xfrm_hash_free(odst, osize);
166 xfrm_hash_free(osrc, osize);
167 xfrm_hash_free(ospi, osize);
f034b5d4
DM
168
169out_unlock:
170 mutex_unlock(&hash_resize_mutex);
171}
172
c4028958 173static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize);
f034b5d4 174
1da177e4
LT
175DECLARE_WAIT_QUEUE_HEAD(km_waitq);
176EXPORT_SYMBOL(km_waitq);
177
178static DEFINE_RWLOCK(xfrm_state_afinfo_lock);
179static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
180
181static struct work_struct xfrm_state_gc_work;
8f126e37 182static HLIST_HEAD(xfrm_state_gc_list);
1da177e4
LT
183static DEFINE_SPINLOCK(xfrm_state_gc_lock);
184
53bc6b4d 185int __xfrm_state_delete(struct xfrm_state *x);
1da177e4 186
980ebd25 187int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
53bc6b4d 188void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
1da177e4
LT
189
190static void xfrm_state_gc_destroy(struct xfrm_state *x)
191{
a47f0ce0
DM
192 del_timer_sync(&x->timer);
193 del_timer_sync(&x->rtimer);
a51482bd
JJ
194 kfree(x->aalg);
195 kfree(x->ealg);
196 kfree(x->calg);
197 kfree(x->encap);
060f02a3 198 kfree(x->coaddr);
b59f45d0
HX
199 if (x->mode)
200 xfrm_put_mode(x->mode);
1da177e4
LT
201 if (x->type) {
202 x->type->destructor(x);
203 xfrm_put_type(x->type);
204 }
df71837d 205 security_xfrm_state_free(x);
1da177e4
LT
206 kfree(x);
207}
208
c4028958 209static void xfrm_state_gc_task(struct work_struct *data)
1da177e4
LT
210{
211 struct xfrm_state *x;
8f126e37
DM
212 struct hlist_node *entry, *tmp;
213 struct hlist_head gc_list;
1da177e4 214
1da177e4 215 spin_lock_bh(&xfrm_state_gc_lock);
8f126e37
DM
216 gc_list.first = xfrm_state_gc_list.first;
217 INIT_HLIST_HEAD(&xfrm_state_gc_list);
1da177e4
LT
218 spin_unlock_bh(&xfrm_state_gc_lock);
219
8f126e37 220 hlist_for_each_entry_safe(x, entry, tmp, &gc_list, bydst)
1da177e4 221 xfrm_state_gc_destroy(x);
8f126e37 222
1da177e4
LT
223 wake_up(&km_waitq);
224}
225
226static inline unsigned long make_jiffies(long secs)
227{
228 if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
229 return MAX_SCHEDULE_TIMEOUT-1;
230 else
a716c119 231 return secs*HZ;
1da177e4
LT
232}
233
234static void xfrm_timer_handler(unsigned long data)
235{
236 struct xfrm_state *x = (struct xfrm_state*)data;
9d729f72 237 unsigned long now = get_seconds();
1da177e4
LT
238 long next = LONG_MAX;
239 int warn = 0;
161a09e7 240 int err = 0;
1da177e4
LT
241
242 spin_lock(&x->lock);
243 if (x->km.state == XFRM_STATE_DEAD)
244 goto out;
245 if (x->km.state == XFRM_STATE_EXPIRED)
246 goto expired;
247 if (x->lft.hard_add_expires_seconds) {
248 long tmo = x->lft.hard_add_expires_seconds +
249 x->curlft.add_time - now;
250 if (tmo <= 0)
251 goto expired;
252 if (tmo < next)
253 next = tmo;
254 }
255 if (x->lft.hard_use_expires_seconds) {
256 long tmo = x->lft.hard_use_expires_seconds +
257 (x->curlft.use_time ? : now) - now;
258 if (tmo <= 0)
259 goto expired;
260 if (tmo < next)
261 next = tmo;
262 }
263 if (x->km.dying)
264 goto resched;
265 if (x->lft.soft_add_expires_seconds) {
266 long tmo = x->lft.soft_add_expires_seconds +
267 x->curlft.add_time - now;
268 if (tmo <= 0)
269 warn = 1;
270 else if (tmo < next)
271 next = tmo;
272 }
273 if (x->lft.soft_use_expires_seconds) {
274 long tmo = x->lft.soft_use_expires_seconds +
275 (x->curlft.use_time ? : now) - now;
276 if (tmo <= 0)
277 warn = 1;
278 else if (tmo < next)
279 next = tmo;
280 }
281
4666faab 282 x->km.dying = warn;
1da177e4 283 if (warn)
53bc6b4d 284 km_state_expired(x, 0, 0);
1da177e4 285resched:
a47f0ce0
DM
286 if (next != LONG_MAX)
287 mod_timer(&x->timer, jiffies + make_jiffies(next));
288
1da177e4
LT
289 goto out;
290
291expired:
292 if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0) {
293 x->km.state = XFRM_STATE_EXPIRED;
294 wake_up(&km_waitq);
295 next = 2;
296 goto resched;
297 }
161a09e7
JL
298
299 err = __xfrm_state_delete(x);
300 if (!err && x->id.spi)
53bc6b4d 301 km_state_expired(x, 1, 0);
1da177e4 302
ab5f5e8b
JL
303 xfrm_audit_state_delete(x, err ? 0 : 1,
304 audit_get_loginuid(current->audit_context), 0);
161a09e7 305
1da177e4
LT
306out:
307 spin_unlock(&x->lock);
1da177e4
LT
308}
309
0ac84752
DM
310static void xfrm_replay_timer_handler(unsigned long data);
311
1da177e4
LT
312struct xfrm_state *xfrm_state_alloc(void)
313{
314 struct xfrm_state *x;
315
0da974f4 316 x = kzalloc(sizeof(struct xfrm_state), GFP_ATOMIC);
1da177e4
LT
317
318 if (x) {
1da177e4
LT
319 atomic_set(&x->refcnt, 1);
320 atomic_set(&x->tunnel_users, 0);
8f126e37
DM
321 INIT_HLIST_NODE(&x->bydst);
322 INIT_HLIST_NODE(&x->bysrc);
323 INIT_HLIST_NODE(&x->byspi);
1da177e4
LT
324 init_timer(&x->timer);
325 x->timer.function = xfrm_timer_handler;
326 x->timer.data = (unsigned long)x;
f8cd5488
JHS
327 init_timer(&x->rtimer);
328 x->rtimer.function = xfrm_replay_timer_handler;
329 x->rtimer.data = (unsigned long)x;
9d729f72 330 x->curlft.add_time = get_seconds();
1da177e4
LT
331 x->lft.soft_byte_limit = XFRM_INF;
332 x->lft.soft_packet_limit = XFRM_INF;
333 x->lft.hard_byte_limit = XFRM_INF;
334 x->lft.hard_packet_limit = XFRM_INF;
f8cd5488
JHS
335 x->replay_maxage = 0;
336 x->replay_maxdiff = 0;
1da177e4
LT
337 spin_lock_init(&x->lock);
338 }
339 return x;
340}
341EXPORT_SYMBOL(xfrm_state_alloc);
342
343void __xfrm_state_destroy(struct xfrm_state *x)
344{
345 BUG_TRAP(x->km.state == XFRM_STATE_DEAD);
346
347 spin_lock_bh(&xfrm_state_gc_lock);
8f126e37 348 hlist_add_head(&x->bydst, &xfrm_state_gc_list);
1da177e4
LT
349 spin_unlock_bh(&xfrm_state_gc_lock);
350 schedule_work(&xfrm_state_gc_work);
351}
352EXPORT_SYMBOL(__xfrm_state_destroy);
353
53bc6b4d 354int __xfrm_state_delete(struct xfrm_state *x)
1da177e4 355{
26b15dad
JHS
356 int err = -ESRCH;
357
1da177e4
LT
358 if (x->km.state != XFRM_STATE_DEAD) {
359 x->km.state = XFRM_STATE_DEAD;
360 spin_lock(&xfrm_state_lock);
8f126e37 361 hlist_del(&x->bydst);
8f126e37 362 hlist_del(&x->bysrc);
a47f0ce0 363 if (x->id.spi)
8f126e37 364 hlist_del(&x->byspi);
f034b5d4 365 xfrm_state_num--;
1da177e4 366 spin_unlock(&xfrm_state_lock);
1da177e4 367
1da177e4
LT
368 /* All xfrm_state objects are created by xfrm_state_alloc.
369 * The xfrm_state_alloc call gives a reference, and that
370 * is what we are dropping here.
371 */
21380b81 372 __xfrm_state_put(x);
26b15dad 373 err = 0;
1da177e4 374 }
26b15dad
JHS
375
376 return err;
1da177e4 377}
53bc6b4d 378EXPORT_SYMBOL(__xfrm_state_delete);
1da177e4 379
26b15dad 380int xfrm_state_delete(struct xfrm_state *x)
1da177e4 381{
26b15dad
JHS
382 int err;
383
1da177e4 384 spin_lock_bh(&x->lock);
26b15dad 385 err = __xfrm_state_delete(x);
1da177e4 386 spin_unlock_bh(&x->lock);
26b15dad
JHS
387
388 return err;
1da177e4
LT
389}
390EXPORT_SYMBOL(xfrm_state_delete);
391
4aa2e62c
JL
392#ifdef CONFIG_SECURITY_NETWORK_XFRM
393static inline int
394xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
1da177e4 395{
4aa2e62c
JL
396 int i, err = 0;
397
398 for (i = 0; i <= xfrm_state_hmask; i++) {
399 struct hlist_node *entry;
400 struct xfrm_state *x;
401
402 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
403 if (xfrm_id_proto_match(x->id.proto, proto) &&
404 (err = security_xfrm_state_delete(x)) != 0) {
ab5f5e8b
JL
405 xfrm_audit_state_delete(x, 0,
406 audit_info->loginuid,
407 audit_info->secid);
4aa2e62c
JL
408 return err;
409 }
410 }
411 }
412
413 return err;
414}
415#else
416static inline int
417xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
418{
419 return 0;
420}
421#endif
422
423int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
424{
425 int i, err = 0;
1da177e4
LT
426
427 spin_lock_bh(&xfrm_state_lock);
4aa2e62c
JL
428 err = xfrm_state_flush_secctx_check(proto, audit_info);
429 if (err)
430 goto out;
431
a9917c06 432 for (i = 0; i <= xfrm_state_hmask; i++) {
8f126e37
DM
433 struct hlist_node *entry;
434 struct xfrm_state *x;
1da177e4 435restart:
8f126e37 436 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
1da177e4 437 if (!xfrm_state_kern(x) &&
5794708f 438 xfrm_id_proto_match(x->id.proto, proto)) {
1da177e4
LT
439 xfrm_state_hold(x);
440 spin_unlock_bh(&xfrm_state_lock);
441
161a09e7 442 err = xfrm_state_delete(x);
ab5f5e8b
JL
443 xfrm_audit_state_delete(x, err ? 0 : 1,
444 audit_info->loginuid,
445 audit_info->secid);
1da177e4
LT
446 xfrm_state_put(x);
447
448 spin_lock_bh(&xfrm_state_lock);
449 goto restart;
450 }
451 }
452 }
4aa2e62c
JL
453 err = 0;
454
455out:
1da177e4
LT
456 spin_unlock_bh(&xfrm_state_lock);
457 wake_up(&km_waitq);
4aa2e62c 458 return err;
1da177e4
LT
459}
460EXPORT_SYMBOL(xfrm_state_flush);
461
af11e316 462void xfrm_sad_getinfo(struct xfrmk_sadinfo *si)
28d8909b
JHS
463{
464 spin_lock_bh(&xfrm_state_lock);
465 si->sadcnt = xfrm_state_num;
466 si->sadhcnt = xfrm_state_hmask;
467 si->sadhmcnt = xfrm_state_hashmax;
468 spin_unlock_bh(&xfrm_state_lock);
469}
470EXPORT_SYMBOL(xfrm_sad_getinfo);
471
1da177e4
LT
472static int
473xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
474 struct xfrm_tmpl *tmpl,
475 xfrm_address_t *daddr, xfrm_address_t *saddr,
476 unsigned short family)
477{
478 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
479 if (!afinfo)
480 return -1;
481 afinfo->init_tempsel(x, fl, tmpl, daddr, saddr);
482 xfrm_state_put_afinfo(afinfo);
483 return 0;
484}
485
a94cfd19 486static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
edcd5821
DM
487{
488 unsigned int h = xfrm_spi_hash(daddr, spi, proto, family);
489 struct xfrm_state *x;
8f126e37 490 struct hlist_node *entry;
edcd5821 491
8f126e37 492 hlist_for_each_entry(x, entry, xfrm_state_byspi+h, byspi) {
edcd5821
DM
493 if (x->props.family != family ||
494 x->id.spi != spi ||
495 x->id.proto != proto)
496 continue;
497
498 switch (family) {
499 case AF_INET:
500 if (x->id.daddr.a4 != daddr->a4)
501 continue;
502 break;
503 case AF_INET6:
504 if (!ipv6_addr_equal((struct in6_addr *)daddr,
505 (struct in6_addr *)
506 x->id.daddr.a6))
507 continue;
508 break;
3ff50b79 509 }
edcd5821
DM
510
511 xfrm_state_hold(x);
512 return x;
513 }
514
515 return NULL;
516}
517
518static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family)
519{
667bbcb6 520 unsigned int h = xfrm_src_hash(daddr, saddr, family);
edcd5821 521 struct xfrm_state *x;
8f126e37 522 struct hlist_node *entry;
edcd5821 523
8f126e37 524 hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) {
edcd5821
DM
525 if (x->props.family != family ||
526 x->id.proto != proto)
527 continue;
528
529 switch (family) {
530 case AF_INET:
531 if (x->id.daddr.a4 != daddr->a4 ||
532 x->props.saddr.a4 != saddr->a4)
533 continue;
534 break;
535 case AF_INET6:
536 if (!ipv6_addr_equal((struct in6_addr *)daddr,
537 (struct in6_addr *)
538 x->id.daddr.a6) ||
539 !ipv6_addr_equal((struct in6_addr *)saddr,
540 (struct in6_addr *)
541 x->props.saddr.a6))
542 continue;
543 break;
3ff50b79 544 }
edcd5821
DM
545
546 xfrm_state_hold(x);
547 return x;
548 }
549
550 return NULL;
551}
552
553static inline struct xfrm_state *
554__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
555{
556 if (use_spi)
557 return __xfrm_state_lookup(&x->id.daddr, x->id.spi,
558 x->id.proto, family);
559 else
560 return __xfrm_state_lookup_byaddr(&x->id.daddr,
561 &x->props.saddr,
562 x->id.proto, family);
563}
564
2fab22f2
PM
565static void xfrm_hash_grow_check(int have_hash_collision)
566{
567 if (have_hash_collision &&
568 (xfrm_state_hmask + 1) < xfrm_state_hashmax &&
569 xfrm_state_num > xfrm_state_hmask)
570 schedule_work(&xfrm_hash_work);
571}
572
1da177e4 573struct xfrm_state *
a716c119 574xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
1da177e4
LT
575 struct flowi *fl, struct xfrm_tmpl *tmpl,
576 struct xfrm_policy *pol, int *err,
577 unsigned short family)
578{
c1969f29 579 unsigned int h = xfrm_dst_hash(daddr, saddr, tmpl->reqid, family);
8f126e37 580 struct hlist_node *entry;
1da177e4
LT
581 struct xfrm_state *x, *x0;
582 int acquire_in_progress = 0;
583 int error = 0;
584 struct xfrm_state *best = NULL;
a716c119 585
1da177e4 586 spin_lock_bh(&xfrm_state_lock);
8f126e37 587 hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
1da177e4
LT
588 if (x->props.family == family &&
589 x->props.reqid == tmpl->reqid &&
fbd9a5b4 590 !(x->props.flags & XFRM_STATE_WILDRECV) &&
1da177e4
LT
591 xfrm_state_addr_check(x, daddr, saddr, family) &&
592 tmpl->mode == x->props.mode &&
593 tmpl->id.proto == x->id.proto &&
594 (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) {
595 /* Resolution logic:
596 1. There is a valid state with matching selector.
597 Done.
598 2. Valid state with inappropriate selector. Skip.
599
600 Entering area of "sysdeps".
601
602 3. If state is not valid, selector is temporary,
603 it selects only session which triggered
604 previous resolution. Key manager will do
605 something to install a state with proper
606 selector.
607 */
608 if (x->km.state == XFRM_STATE_VALID) {
48b8d783 609 if (!xfrm_selector_match(&x->sel, fl, x->sel.family) ||
e0d1caa7 610 !security_xfrm_state_pol_flow_match(x, pol, fl))
1da177e4
LT
611 continue;
612 if (!best ||
613 best->km.dying > x->km.dying ||
614 (best->km.dying == x->km.dying &&
615 best->curlft.add_time < x->curlft.add_time))
616 best = x;
617 } else if (x->km.state == XFRM_STATE_ACQ) {
618 acquire_in_progress = 1;
619 } else if (x->km.state == XFRM_STATE_ERROR ||
620 x->km.state == XFRM_STATE_EXPIRED) {
48b8d783 621 if (xfrm_selector_match(&x->sel, fl, x->sel.family) &&
e0d1caa7 622 security_xfrm_state_pol_flow_match(x, pol, fl))
1da177e4
LT
623 error = -ESRCH;
624 }
625 }
626 }
627
628 x = best;
629 if (!x && !error && !acquire_in_progress) {
5c5d281a 630 if (tmpl->id.spi &&
edcd5821
DM
631 (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi,
632 tmpl->id.proto, family)) != NULL) {
1da177e4
LT
633 xfrm_state_put(x0);
634 error = -EEXIST;
635 goto out;
636 }
637 x = xfrm_state_alloc();
638 if (x == NULL) {
639 error = -ENOMEM;
640 goto out;
641 }
642 /* Initialize temporary selector matching only
643 * to current session. */
644 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
645
e0d1caa7
VY
646 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
647 if (error) {
648 x->km.state = XFRM_STATE_DEAD;
649 xfrm_state_put(x);
650 x = NULL;
651 goto out;
652 }
653
1da177e4
LT
654 if (km_query(x, tmpl, pol) == 0) {
655 x->km.state = XFRM_STATE_ACQ;
8f126e37 656 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
667bbcb6 657 h = xfrm_src_hash(daddr, saddr, family);
8f126e37 658 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
1da177e4
LT
659 if (x->id.spi) {
660 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family);
8f126e37 661 hlist_add_head(&x->byspi, xfrm_state_byspi+h);
1da177e4 662 }
01e67d08
DM
663 x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
664 x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
1da177e4 665 add_timer(&x->timer);
2fab22f2
PM
666 xfrm_state_num++;
667 xfrm_hash_grow_check(x->bydst.next != NULL);
1da177e4
LT
668 } else {
669 x->km.state = XFRM_STATE_DEAD;
670 xfrm_state_put(x);
671 x = NULL;
672 error = -ESRCH;
673 }
674 }
675out:
676 if (x)
677 xfrm_state_hold(x);
678 else
679 *err = acquire_in_progress ? -EAGAIN : error;
680 spin_unlock_bh(&xfrm_state_lock);
1da177e4
LT
681 return x;
682}
683
628529b6
JHS
684struct xfrm_state *
685xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
686 unsigned short family, u8 mode, u8 proto, u32 reqid)
687{
688 unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family);
689 struct xfrm_state *rx = NULL, *x = NULL;
690 struct hlist_node *entry;
691
692 spin_lock(&xfrm_state_lock);
693 hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
694 if (x->props.family == family &&
695 x->props.reqid == reqid &&
696 !(x->props.flags & XFRM_STATE_WILDRECV) &&
697 xfrm_state_addr_check(x, daddr, saddr, family) &&
698 mode == x->props.mode &&
699 proto == x->id.proto &&
700 x->km.state == XFRM_STATE_VALID) {
701 rx = x;
702 break;
703 }
704 }
705
706 if (rx)
707 xfrm_state_hold(rx);
708 spin_unlock(&xfrm_state_lock);
709
710
711 return rx;
712}
713EXPORT_SYMBOL(xfrm_stateonly_find);
714
1da177e4
LT
715static void __xfrm_state_insert(struct xfrm_state *x)
716{
a624c108 717 unsigned int h;
1da177e4 718
9d4a706d
DM
719 x->genid = ++xfrm_state_genid;
720
c1969f29
DM
721 h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
722 x->props.reqid, x->props.family);
8f126e37 723 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
1da177e4 724
667bbcb6 725 h = xfrm_src_hash(&x->id.daddr, &x->props.saddr, x->props.family);
8f126e37 726 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
1da177e4 727
7b4dc360 728 if (x->id.spi) {
6c44e6b7
MN
729 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto,
730 x->props.family);
731
8f126e37 732 hlist_add_head(&x->byspi, xfrm_state_byspi+h);
6c44e6b7
MN
733 }
734
a47f0ce0
DM
735 mod_timer(&x->timer, jiffies + HZ);
736 if (x->replay_maxage)
737 mod_timer(&x->rtimer, jiffies + x->replay_maxage);
f8cd5488 738
1da177e4 739 wake_up(&km_waitq);
f034b5d4
DM
740
741 xfrm_state_num++;
742
918049f0 743 xfrm_hash_grow_check(x->bydst.next != NULL);
1da177e4
LT
744}
745
c7f5ea3a
DM
746/* xfrm_state_lock is held */
747static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
748{
749 unsigned short family = xnew->props.family;
750 u32 reqid = xnew->props.reqid;
751 struct xfrm_state *x;
752 struct hlist_node *entry;
753 unsigned int h;
754
c1969f29 755 h = xfrm_dst_hash(&xnew->id.daddr, &xnew->props.saddr, reqid, family);
c7f5ea3a
DM
756 hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
757 if (x->props.family == family &&
758 x->props.reqid == reqid &&
c1969f29
DM
759 !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) &&
760 !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family))
c7f5ea3a
DM
761 x->genid = xfrm_state_genid;
762 }
763}
764
1da177e4
LT
765void xfrm_state_insert(struct xfrm_state *x)
766{
767 spin_lock_bh(&xfrm_state_lock);
c7f5ea3a 768 __xfrm_state_bump_genids(x);
1da177e4
LT
769 __xfrm_state_insert(x);
770 spin_unlock_bh(&xfrm_state_lock);
771}
772EXPORT_SYMBOL(xfrm_state_insert);
773
2770834c
DM
774/* xfrm_state_lock is held */
775static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create)
776{
c1969f29 777 unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family);
8f126e37 778 struct hlist_node *entry;
2770834c
DM
779 struct xfrm_state *x;
780
8f126e37 781 hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
2770834c
DM
782 if (x->props.reqid != reqid ||
783 x->props.mode != mode ||
784 x->props.family != family ||
785 x->km.state != XFRM_STATE_ACQ ||
75e252d9
JL
786 x->id.spi != 0 ||
787 x->id.proto != proto)
2770834c
DM
788 continue;
789
790 switch (family) {
791 case AF_INET:
792 if (x->id.daddr.a4 != daddr->a4 ||
793 x->props.saddr.a4 != saddr->a4)
794 continue;
795 break;
796 case AF_INET6:
797 if (!ipv6_addr_equal((struct in6_addr *)x->id.daddr.a6,
798 (struct in6_addr *)daddr) ||
799 !ipv6_addr_equal((struct in6_addr *)
800 x->props.saddr.a6,
801 (struct in6_addr *)saddr))
802 continue;
803 break;
3ff50b79 804 }
2770834c
DM
805
806 xfrm_state_hold(x);
807 return x;
808 }
809
810 if (!create)
811 return NULL;
812
813 x = xfrm_state_alloc();
814 if (likely(x)) {
815 switch (family) {
816 case AF_INET:
817 x->sel.daddr.a4 = daddr->a4;
818 x->sel.saddr.a4 = saddr->a4;
819 x->sel.prefixlen_d = 32;
820 x->sel.prefixlen_s = 32;
821 x->props.saddr.a4 = saddr->a4;
822 x->id.daddr.a4 = daddr->a4;
823 break;
824
825 case AF_INET6:
826 ipv6_addr_copy((struct in6_addr *)x->sel.daddr.a6,
827 (struct in6_addr *)daddr);
828 ipv6_addr_copy((struct in6_addr *)x->sel.saddr.a6,
829 (struct in6_addr *)saddr);
830 x->sel.prefixlen_d = 128;
831 x->sel.prefixlen_s = 128;
832 ipv6_addr_copy((struct in6_addr *)x->props.saddr.a6,
833 (struct in6_addr *)saddr);
834 ipv6_addr_copy((struct in6_addr *)x->id.daddr.a6,
835 (struct in6_addr *)daddr);
836 break;
3ff50b79 837 }
2770834c
DM
838
839 x->km.state = XFRM_STATE_ACQ;
840 x->id.proto = proto;
841 x->props.family = family;
842 x->props.mode = mode;
843 x->props.reqid = reqid;
01e67d08 844 x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
2770834c 845 xfrm_state_hold(x);
01e67d08 846 x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
2770834c 847 add_timer(&x->timer);
8f126e37 848 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
667bbcb6 849 h = xfrm_src_hash(daddr, saddr, family);
8f126e37 850 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
2770834c 851 wake_up(&km_waitq);
918049f0
DM
852
853 xfrm_state_num++;
854
855 xfrm_hash_grow_check(x->bydst.next != NULL);
2770834c
DM
856 }
857
858 return x;
859}
860
1da177e4
LT
861static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq);
862
863int xfrm_state_add(struct xfrm_state *x)
864{
1da177e4
LT
865 struct xfrm_state *x1;
866 int family;
867 int err;
eb2971b6 868 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
1da177e4
LT
869
870 family = x->props.family;
1da177e4
LT
871
872 spin_lock_bh(&xfrm_state_lock);
873
edcd5821 874 x1 = __xfrm_state_locate(x, use_spi, family);
1da177e4
LT
875 if (x1) {
876 xfrm_state_put(x1);
877 x1 = NULL;
878 err = -EEXIST;
879 goto out;
880 }
881
eb2971b6 882 if (use_spi && x->km.seq) {
1da177e4 883 x1 = __xfrm_find_acq_byseq(x->km.seq);
75e252d9
JL
884 if (x1 && ((x1->id.proto != x->id.proto) ||
885 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) {
1da177e4
LT
886 xfrm_state_put(x1);
887 x1 = NULL;
888 }
889 }
890
eb2971b6 891 if (use_spi && !x1)
2770834c
DM
892 x1 = __find_acq_core(family, x->props.mode, x->props.reqid,
893 x->id.proto,
894 &x->id.daddr, &x->props.saddr, 0);
1da177e4 895
c7f5ea3a 896 __xfrm_state_bump_genids(x);
1da177e4
LT
897 __xfrm_state_insert(x);
898 err = 0;
899
900out:
901 spin_unlock_bh(&xfrm_state_lock);
1da177e4
LT
902
903 if (x1) {
904 xfrm_state_delete(x1);
905 xfrm_state_put(x1);
906 }
907
908 return err;
909}
910EXPORT_SYMBOL(xfrm_state_add);
911
80c9abaa
SS
912#ifdef CONFIG_XFRM_MIGRATE
913struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
914{
915 int err = -ENOMEM;
916 struct xfrm_state *x = xfrm_state_alloc();
917 if (!x)
918 goto error;
919
920 memcpy(&x->id, &orig->id, sizeof(x->id));
921 memcpy(&x->sel, &orig->sel, sizeof(x->sel));
922 memcpy(&x->lft, &orig->lft, sizeof(x->lft));
923 x->props.mode = orig->props.mode;
924 x->props.replay_window = orig->props.replay_window;
925 x->props.reqid = orig->props.reqid;
926 x->props.family = orig->props.family;
927 x->props.saddr = orig->props.saddr;
928
929 if (orig->aalg) {
930 x->aalg = xfrm_algo_clone(orig->aalg);
931 if (!x->aalg)
932 goto error;
933 }
934 x->props.aalgo = orig->props.aalgo;
935
936 if (orig->ealg) {
937 x->ealg = xfrm_algo_clone(orig->ealg);
938 if (!x->ealg)
939 goto error;
940 }
941 x->props.ealgo = orig->props.ealgo;
942
943 if (orig->calg) {
944 x->calg = xfrm_algo_clone(orig->calg);
945 if (!x->calg)
946 goto error;
947 }
948 x->props.calgo = orig->props.calgo;
949
a716c119 950 if (orig->encap) {
80c9abaa
SS
951 x->encap = kmemdup(orig->encap, sizeof(*x->encap), GFP_KERNEL);
952 if (!x->encap)
953 goto error;
954 }
955
956 if (orig->coaddr) {
957 x->coaddr = kmemdup(orig->coaddr, sizeof(*x->coaddr),
958 GFP_KERNEL);
959 if (!x->coaddr)
960 goto error;
961 }
962
963 err = xfrm_init_state(x);
964 if (err)
965 goto error;
966
967 x->props.flags = orig->props.flags;
968
969 x->curlft.add_time = orig->curlft.add_time;
970 x->km.state = orig->km.state;
971 x->km.seq = orig->km.seq;
972
973 return x;
974
975 error:
976 if (errp)
977 *errp = err;
978 if (x) {
979 kfree(x->aalg);
980 kfree(x->ealg);
981 kfree(x->calg);
982 kfree(x->encap);
983 kfree(x->coaddr);
984 }
985 kfree(x);
986 return NULL;
987}
988EXPORT_SYMBOL(xfrm_state_clone);
989
990/* xfrm_state_lock is held */
991struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m)
992{
993 unsigned int h;
994 struct xfrm_state *x;
995 struct hlist_node *entry;
996
997 if (m->reqid) {
998 h = xfrm_dst_hash(&m->old_daddr, &m->old_saddr,
999 m->reqid, m->old_family);
1000 hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
1001 if (x->props.mode != m->mode ||
1002 x->id.proto != m->proto)
1003 continue;
1004 if (m->reqid && x->props.reqid != m->reqid)
1005 continue;
1006 if (xfrm_addr_cmp(&x->id.daddr, &m->old_daddr,
1007 m->old_family) ||
1008 xfrm_addr_cmp(&x->props.saddr, &m->old_saddr,
1009 m->old_family))
1010 continue;
1011 xfrm_state_hold(x);
1012 return x;
1013 }
1014 } else {
1015 h = xfrm_src_hash(&m->old_daddr, &m->old_saddr,
1016 m->old_family);
1017 hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) {
1018 if (x->props.mode != m->mode ||
1019 x->id.proto != m->proto)
1020 continue;
1021 if (xfrm_addr_cmp(&x->id.daddr, &m->old_daddr,
1022 m->old_family) ||
1023 xfrm_addr_cmp(&x->props.saddr, &m->old_saddr,
1024 m->old_family))
1025 continue;
1026 xfrm_state_hold(x);
1027 return x;
1028 }
1029 }
1030
a716c119 1031 return NULL;
80c9abaa
SS
1032}
1033EXPORT_SYMBOL(xfrm_migrate_state_find);
1034
1035struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
1036 struct xfrm_migrate *m)
1037{
1038 struct xfrm_state *xc;
1039 int err;
1040
1041 xc = xfrm_state_clone(x, &err);
1042 if (!xc)
1043 return NULL;
1044
1045 memcpy(&xc->id.daddr, &m->new_daddr, sizeof(xc->id.daddr));
1046 memcpy(&xc->props.saddr, &m->new_saddr, sizeof(xc->props.saddr));
1047
1048 /* add state */
1049 if (!xfrm_addr_cmp(&x->id.daddr, &m->new_daddr, m->new_family)) {
1050 /* a care is needed when the destination address of the
1051 state is to be updated as it is a part of triplet */
1052 xfrm_state_insert(xc);
1053 } else {
1054 if ((err = xfrm_state_add(xc)) < 0)
1055 goto error;
1056 }
1057
1058 return xc;
1059error:
1060 kfree(xc);
1061 return NULL;
1062}
1063EXPORT_SYMBOL(xfrm_state_migrate);
1064#endif
1065
1da177e4
LT
1066int xfrm_state_update(struct xfrm_state *x)
1067{
1da177e4
LT
1068 struct xfrm_state *x1;
1069 int err;
eb2971b6 1070 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
1da177e4 1071
1da177e4 1072 spin_lock_bh(&xfrm_state_lock);
edcd5821 1073 x1 = __xfrm_state_locate(x, use_spi, x->props.family);
1da177e4
LT
1074
1075 err = -ESRCH;
1076 if (!x1)
1077 goto out;
1078
1079 if (xfrm_state_kern(x1)) {
1080 xfrm_state_put(x1);
1081 err = -EEXIST;
1082 goto out;
1083 }
1084
1085 if (x1->km.state == XFRM_STATE_ACQ) {
1086 __xfrm_state_insert(x);
1087 x = NULL;
1088 }
1089 err = 0;
1090
1091out:
1092 spin_unlock_bh(&xfrm_state_lock);
1da177e4
LT
1093
1094 if (err)
1095 return err;
1096
1097 if (!x) {
1098 xfrm_state_delete(x1);
1099 xfrm_state_put(x1);
1100 return 0;
1101 }
1102
1103 err = -EINVAL;
1104 spin_lock_bh(&x1->lock);
1105 if (likely(x1->km.state == XFRM_STATE_VALID)) {
1106 if (x->encap && x1->encap)
1107 memcpy(x1->encap, x->encap, sizeof(*x1->encap));
060f02a3
NT
1108 if (x->coaddr && x1->coaddr) {
1109 memcpy(x1->coaddr, x->coaddr, sizeof(*x1->coaddr));
1110 }
1111 if (!use_spi && memcmp(&x1->sel, &x->sel, sizeof(x1->sel)))
1112 memcpy(&x1->sel, &x->sel, sizeof(x1->sel));
1da177e4
LT
1113 memcpy(&x1->lft, &x->lft, sizeof(x1->lft));
1114 x1->km.dying = 0;
1115
a47f0ce0 1116 mod_timer(&x1->timer, jiffies + HZ);
1da177e4
LT
1117 if (x1->curlft.use_time)
1118 xfrm_state_check_expire(x1);
1119
1120 err = 0;
1121 }
1122 spin_unlock_bh(&x1->lock);
1123
1124 xfrm_state_put(x1);
1125
1126 return err;
1127}
1128EXPORT_SYMBOL(xfrm_state_update);
1129
1130int xfrm_state_check_expire(struct xfrm_state *x)
1131{
1132 if (!x->curlft.use_time)
9d729f72 1133 x->curlft.use_time = get_seconds();
1da177e4
LT
1134
1135 if (x->km.state != XFRM_STATE_VALID)
1136 return -EINVAL;
1137
1138 if (x->curlft.bytes >= x->lft.hard_byte_limit ||
1139 x->curlft.packets >= x->lft.hard_packet_limit) {
4666faab 1140 x->km.state = XFRM_STATE_EXPIRED;
a47f0ce0 1141 mod_timer(&x->timer, jiffies);
1da177e4
LT
1142 return -EINVAL;
1143 }
1144
1145 if (!x->km.dying &&
1146 (x->curlft.bytes >= x->lft.soft_byte_limit ||
4666faab
HX
1147 x->curlft.packets >= x->lft.soft_packet_limit)) {
1148 x->km.dying = 1;
53bc6b4d 1149 km_state_expired(x, 0, 0);
4666faab 1150 }
1da177e4
LT
1151 return 0;
1152}
1153EXPORT_SYMBOL(xfrm_state_check_expire);
1154
1155static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
1156{
1157 int nhead = x->props.header_len + LL_RESERVED_SPACE(skb->dst->dev)
1158 - skb_headroom(skb);
1159
1160 if (nhead > 0)
1161 return pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
1162
1163 /* Check tail too... */
1164 return 0;
1165}
1166
1167int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb)
1168{
1169 int err = xfrm_state_check_expire(x);
1170 if (err < 0)
1171 goto err;
1172 err = xfrm_state_check_space(x, skb);
1173err:
1174 return err;
1175}
1176EXPORT_SYMBOL(xfrm_state_check);
1177
1178struct xfrm_state *
a94cfd19 1179xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto,
1da177e4
LT
1180 unsigned short family)
1181{
1182 struct xfrm_state *x;
1da177e4
LT
1183
1184 spin_lock_bh(&xfrm_state_lock);
edcd5821 1185 x = __xfrm_state_lookup(daddr, spi, proto, family);
1da177e4 1186 spin_unlock_bh(&xfrm_state_lock);
1da177e4
LT
1187 return x;
1188}
1189EXPORT_SYMBOL(xfrm_state_lookup);
1190
1191struct xfrm_state *
eb2971b6
MN
1192xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr,
1193 u8 proto, unsigned short family)
1194{
1195 struct xfrm_state *x;
eb2971b6
MN
1196
1197 spin_lock_bh(&xfrm_state_lock);
edcd5821 1198 x = __xfrm_state_lookup_byaddr(daddr, saddr, proto, family);
eb2971b6 1199 spin_unlock_bh(&xfrm_state_lock);
eb2971b6
MN
1200 return x;
1201}
1202EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
1203
1204struct xfrm_state *
a716c119
YH
1205xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
1206 xfrm_address_t *daddr, xfrm_address_t *saddr,
1da177e4
LT
1207 int create, unsigned short family)
1208{
1209 struct xfrm_state *x;
1da177e4
LT
1210
1211 spin_lock_bh(&xfrm_state_lock);
2770834c 1212 x = __find_acq_core(family, mode, reqid, proto, daddr, saddr, create);
1da177e4 1213 spin_unlock_bh(&xfrm_state_lock);
2770834c 1214
1da177e4
LT
1215 return x;
1216}
1217EXPORT_SYMBOL(xfrm_find_acq);
1218
41a49cc3
MN
1219#ifdef CONFIG_XFRM_SUB_POLICY
1220int
1221xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
1222 unsigned short family)
1223{
1224 int err = 0;
1225 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
1226 if (!afinfo)
1227 return -EAFNOSUPPORT;
1228
1229 spin_lock_bh(&xfrm_state_lock);
1230 if (afinfo->tmpl_sort)
1231 err = afinfo->tmpl_sort(dst, src, n);
1232 spin_unlock_bh(&xfrm_state_lock);
1233 xfrm_state_put_afinfo(afinfo);
1234 return err;
1235}
1236EXPORT_SYMBOL(xfrm_tmpl_sort);
1237
1238int
1239xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
1240 unsigned short family)
1241{
1242 int err = 0;
1243 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
1244 if (!afinfo)
1245 return -EAFNOSUPPORT;
1246
1247 spin_lock_bh(&xfrm_state_lock);
1248 if (afinfo->state_sort)
1249 err = afinfo->state_sort(dst, src, n);
1250 spin_unlock_bh(&xfrm_state_lock);
1251 xfrm_state_put_afinfo(afinfo);
1252 return err;
1253}
1254EXPORT_SYMBOL(xfrm_state_sort);
1255#endif
1256
1da177e4
LT
1257/* Silly enough, but I'm lazy to build resolution list */
1258
1259static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq)
1260{
1261 int i;
1da177e4 1262
f034b5d4 1263 for (i = 0; i <= xfrm_state_hmask; i++) {
8f126e37
DM
1264 struct hlist_node *entry;
1265 struct xfrm_state *x;
1266
1267 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
1268 if (x->km.seq == seq &&
1269 x->km.state == XFRM_STATE_ACQ) {
1da177e4
LT
1270 xfrm_state_hold(x);
1271 return x;
1272 }
1273 }
1274 }
1275 return NULL;
1276}
1277
1278struct xfrm_state *xfrm_find_acq_byseq(u32 seq)
1279{
1280 struct xfrm_state *x;
1281
1282 spin_lock_bh(&xfrm_state_lock);
1283 x = __xfrm_find_acq_byseq(seq);
1284 spin_unlock_bh(&xfrm_state_lock);
1285 return x;
1286}
1287EXPORT_SYMBOL(xfrm_find_acq_byseq);
1288
1289u32 xfrm_get_acqseq(void)
1290{
1291 u32 res;
1292 static u32 acqseq;
1293 static DEFINE_SPINLOCK(acqseq_lock);
1294
1295 spin_lock_bh(&acqseq_lock);
1296 res = (++acqseq ? : ++acqseq);
1297 spin_unlock_bh(&acqseq_lock);
1298 return res;
1299}
1300EXPORT_SYMBOL(xfrm_get_acqseq);
1301
1302void
26977b4e 1303xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi)
1da177e4 1304{
f034b5d4 1305 unsigned int h;
1da177e4
LT
1306 struct xfrm_state *x0;
1307
1308 if (x->id.spi)
1309 return;
1310
1311 if (minspi == maxspi) {
1312 x0 = xfrm_state_lookup(&x->id.daddr, minspi, x->id.proto, x->props.family);
1313 if (x0) {
1314 xfrm_state_put(x0);
1315 return;
1316 }
1317 x->id.spi = minspi;
1318 } else {
1319 u32 spi = 0;
26977b4e
AV
1320 u32 low = ntohl(minspi);
1321 u32 high = ntohl(maxspi);
1322 for (h=0; h<high-low+1; h++) {
1323 spi = low + net_random()%(high-low+1);
1da177e4
LT
1324 x0 = xfrm_state_lookup(&x->id.daddr, htonl(spi), x->id.proto, x->props.family);
1325 if (x0 == NULL) {
1326 x->id.spi = htonl(spi);
1327 break;
1328 }
1329 xfrm_state_put(x0);
1330 }
1331 }
1332 if (x->id.spi) {
1333 spin_lock_bh(&xfrm_state_lock);
1334 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family);
8f126e37 1335 hlist_add_head(&x->byspi, xfrm_state_byspi+h);
1da177e4
LT
1336 spin_unlock_bh(&xfrm_state_lock);
1337 wake_up(&km_waitq);
1338 }
1339}
1340EXPORT_SYMBOL(xfrm_alloc_spi);
1341
1342int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
1343 void *data)
1344{
1345 int i;
94b9bb54 1346 struct xfrm_state *x, *last = NULL;
8f126e37 1347 struct hlist_node *entry;
1da177e4
LT
1348 int count = 0;
1349 int err = 0;
1350
1351 spin_lock_bh(&xfrm_state_lock);
f034b5d4 1352 for (i = 0; i <= xfrm_state_hmask; i++) {
8f126e37 1353 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
94b9bb54
JHS
1354 if (!xfrm_id_proto_match(x->id.proto, proto))
1355 continue;
1356 if (last) {
1357 err = func(last, count, data);
1358 if (err)
1359 goto out;
1360 }
1361 last = x;
1362 count++;
1da177e4
LT
1363 }
1364 }
1365 if (count == 0) {
1366 err = -ENOENT;
1367 goto out;
1368 }
94b9bb54 1369 err = func(last, 0, data);
1da177e4
LT
1370out:
1371 spin_unlock_bh(&xfrm_state_lock);
1372 return err;
1373}
1374EXPORT_SYMBOL(xfrm_state_walk);
1375
f8cd5488
JHS
1376
1377void xfrm_replay_notify(struct xfrm_state *x, int event)
1378{
1379 struct km_event c;
1380 /* we send notify messages in case
1381 * 1. we updated on of the sequence numbers, and the seqno difference
1382 * is at least x->replay_maxdiff, in this case we also update the
1383 * timeout of our timer function
1384 * 2. if x->replay_maxage has elapsed since last update,
1385 * and there were changes
1386 *
1387 * The state structure must be locked!
1388 */
1389
1390 switch (event) {
1391 case XFRM_REPLAY_UPDATE:
1392 if (x->replay_maxdiff &&
1393 (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
2717096a
JHS
1394 (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
1395 if (x->xflags & XFRM_TIME_DEFER)
1396 event = XFRM_REPLAY_TIMEOUT;
1397 else
1398 return;
1399 }
f8cd5488
JHS
1400
1401 break;
1402
1403 case XFRM_REPLAY_TIMEOUT:
1404 if ((x->replay.seq == x->preplay.seq) &&
1405 (x->replay.bitmap == x->preplay.bitmap) &&
2717096a
JHS
1406 (x->replay.oseq == x->preplay.oseq)) {
1407 x->xflags |= XFRM_TIME_DEFER;
f8cd5488 1408 return;
2717096a 1409 }
f8cd5488
JHS
1410
1411 break;
1412 }
1413
1414 memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
1415 c.event = XFRM_MSG_NEWAE;
1416 c.data.aevent = event;
1417 km_state_notify(x, &c);
1418
f8cd5488 1419 if (x->replay_maxage &&
a47f0ce0 1420 !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
2717096a 1421 x->xflags &= ~XFRM_TIME_DEFER;
f8cd5488 1422}
a70fcb0b 1423EXPORT_SYMBOL(xfrm_replay_notify);
f8cd5488
JHS
1424
1425static void xfrm_replay_timer_handler(unsigned long data)
1426{
1427 struct xfrm_state *x = (struct xfrm_state*)data;
1428
1429 spin_lock(&x->lock);
1430
2717096a
JHS
1431 if (x->km.state == XFRM_STATE_VALID) {
1432 if (xfrm_aevent_is_on())
1433 xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
1434 else
1435 x->xflags |= XFRM_TIME_DEFER;
1436 }
f8cd5488
JHS
1437
1438 spin_unlock(&x->lock);
1439}
1440
a252cc23 1441int xfrm_replay_check(struct xfrm_state *x, __be32 net_seq)
1da177e4
LT
1442{
1443 u32 diff;
a252cc23 1444 u32 seq = ntohl(net_seq);
1da177e4
LT
1445
1446 if (unlikely(seq == 0))
1447 return -EINVAL;
1448
1449 if (likely(seq > x->replay.seq))
1450 return 0;
1451
1452 diff = x->replay.seq - seq;
4c4d51a7
HX
1453 if (diff >= min_t(unsigned int, x->props.replay_window,
1454 sizeof(x->replay.bitmap) * 8)) {
1da177e4
LT
1455 x->stats.replay_window++;
1456 return -EINVAL;
1457 }
1458
1459 if (x->replay.bitmap & (1U << diff)) {
1460 x->stats.replay++;
1461 return -EINVAL;
1462 }
1463 return 0;
1464}
1465EXPORT_SYMBOL(xfrm_replay_check);
1466
61f4627b 1467void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
1da177e4
LT
1468{
1469 u32 diff;
61f4627b 1470 u32 seq = ntohl(net_seq);
1da177e4
LT
1471
1472 if (seq > x->replay.seq) {
1473 diff = seq - x->replay.seq;
1474 if (diff < x->props.replay_window)
1475 x->replay.bitmap = ((x->replay.bitmap) << diff) | 1;
1476 else
1477 x->replay.bitmap = 1;
1478 x->replay.seq = seq;
1479 } else {
1480 diff = x->replay.seq - seq;
1481 x->replay.bitmap |= (1U << diff);
1482 }
f8cd5488
JHS
1483
1484 if (xfrm_aevent_is_on())
1485 xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
1da177e4
LT
1486}
1487EXPORT_SYMBOL(xfrm_replay_advance);
1488
1489static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
1490static DEFINE_RWLOCK(xfrm_km_lock);
1491
26b15dad 1492void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
1da177e4
LT
1493{
1494 struct xfrm_mgr *km;
1495
26b15dad
JHS
1496 read_lock(&xfrm_km_lock);
1497 list_for_each_entry(km, &xfrm_km_list, list)
1498 if (km->notify_policy)
1499 km->notify_policy(xp, dir, c);
1500 read_unlock(&xfrm_km_lock);
1501}
1da177e4 1502
26b15dad
JHS
1503void km_state_notify(struct xfrm_state *x, struct km_event *c)
1504{
1505 struct xfrm_mgr *km;
1da177e4
LT
1506 read_lock(&xfrm_km_lock);
1507 list_for_each_entry(km, &xfrm_km_list, list)
26b15dad
JHS
1508 if (km->notify)
1509 km->notify(x, c);
1da177e4 1510 read_unlock(&xfrm_km_lock);
26b15dad
JHS
1511}
1512
1513EXPORT_SYMBOL(km_policy_notify);
1514EXPORT_SYMBOL(km_state_notify);
1515
53bc6b4d 1516void km_state_expired(struct xfrm_state *x, int hard, u32 pid)
26b15dad
JHS
1517{
1518 struct km_event c;
1519
bf08867f 1520 c.data.hard = hard;
53bc6b4d 1521 c.pid = pid;
f60f6b8f 1522 c.event = XFRM_MSG_EXPIRE;
26b15dad 1523 km_state_notify(x, &c);
1da177e4
LT
1524
1525 if (hard)
1526 wake_up(&km_waitq);
1527}
1528
53bc6b4d 1529EXPORT_SYMBOL(km_state_expired);
26b15dad
JHS
1530/*
1531 * We send to all registered managers regardless of failure
1532 * We are happy with one success
1533*/
980ebd25 1534int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
1da177e4 1535{
26b15dad 1536 int err = -EINVAL, acqret;
1da177e4
LT
1537 struct xfrm_mgr *km;
1538
1539 read_lock(&xfrm_km_lock);
1540 list_for_each_entry(km, &xfrm_km_list, list) {
26b15dad
JHS
1541 acqret = km->acquire(x, t, pol, XFRM_POLICY_OUT);
1542 if (!acqret)
1543 err = acqret;
1da177e4
LT
1544 }
1545 read_unlock(&xfrm_km_lock);
1546 return err;
1547}
980ebd25 1548EXPORT_SYMBOL(km_query);
1da177e4 1549
5d36b180 1550int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
1da177e4
LT
1551{
1552 int err = -EINVAL;
1553 struct xfrm_mgr *km;
1554
1555 read_lock(&xfrm_km_lock);
1556 list_for_each_entry(km, &xfrm_km_list, list) {
1557 if (km->new_mapping)
1558 err = km->new_mapping(x, ipaddr, sport);
1559 if (!err)
1560 break;
1561 }
1562 read_unlock(&xfrm_km_lock);
1563 return err;
1564}
1565EXPORT_SYMBOL(km_new_mapping);
1566
6c5c8ca7 1567void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid)
1da177e4 1568{
26b15dad 1569 struct km_event c;
1da177e4 1570
bf08867f 1571 c.data.hard = hard;
6c5c8ca7 1572 c.pid = pid;
f60f6b8f 1573 c.event = XFRM_MSG_POLEXPIRE;
26b15dad 1574 km_policy_notify(pol, dir, &c);
1da177e4
LT
1575
1576 if (hard)
1577 wake_up(&km_waitq);
1578}
a70fcb0b 1579EXPORT_SYMBOL(km_policy_expired);
1da177e4 1580
80c9abaa
SS
1581int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
1582 struct xfrm_migrate *m, int num_migrate)
1583{
1584 int err = -EINVAL;
1585 int ret;
1586 struct xfrm_mgr *km;
1587
1588 read_lock(&xfrm_km_lock);
1589 list_for_each_entry(km, &xfrm_km_list, list) {
1590 if (km->migrate) {
1591 ret = km->migrate(sel, dir, type, m, num_migrate);
1592 if (!ret)
1593 err = ret;
1594 }
1595 }
1596 read_unlock(&xfrm_km_lock);
1597 return err;
1598}
1599EXPORT_SYMBOL(km_migrate);
1600
97a64b45
MN
1601int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr)
1602{
1603 int err = -EINVAL;
1604 int ret;
1605 struct xfrm_mgr *km;
1606
1607 read_lock(&xfrm_km_lock);
1608 list_for_each_entry(km, &xfrm_km_list, list) {
1609 if (km->report) {
1610 ret = km->report(proto, sel, addr);
1611 if (!ret)
1612 err = ret;
1613 }
1614 }
1615 read_unlock(&xfrm_km_lock);
1616 return err;
1617}
1618EXPORT_SYMBOL(km_report);
1619
1da177e4
LT
1620int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
1621{
1622 int err;
1623 u8 *data;
1624 struct xfrm_mgr *km;
1625 struct xfrm_policy *pol = NULL;
1626
1627 if (optlen <= 0 || optlen > PAGE_SIZE)
1628 return -EMSGSIZE;
1629
1630 data = kmalloc(optlen, GFP_KERNEL);
1631 if (!data)
1632 return -ENOMEM;
1633
1634 err = -EFAULT;
1635 if (copy_from_user(data, optval, optlen))
1636 goto out;
1637
1638 err = -EINVAL;
1639 read_lock(&xfrm_km_lock);
1640 list_for_each_entry(km, &xfrm_km_list, list) {
cb969f07 1641 pol = km->compile_policy(sk, optname, data,
1da177e4
LT
1642 optlen, &err);
1643 if (err >= 0)
1644 break;
1645 }
1646 read_unlock(&xfrm_km_lock);
1647
1648 if (err >= 0) {
1649 xfrm_sk_policy_insert(sk, err, pol);
1650 xfrm_pol_put(pol);
1651 err = 0;
1652 }
1653
1654out:
1655 kfree(data);
1656 return err;
1657}
1658EXPORT_SYMBOL(xfrm_user_policy);
1659
1660int xfrm_register_km(struct xfrm_mgr *km)
1661{
1662 write_lock_bh(&xfrm_km_lock);
1663 list_add_tail(&km->list, &xfrm_km_list);
1664 write_unlock_bh(&xfrm_km_lock);
1665 return 0;
1666}
1667EXPORT_SYMBOL(xfrm_register_km);
1668
1669int xfrm_unregister_km(struct xfrm_mgr *km)
1670{
1671 write_lock_bh(&xfrm_km_lock);
1672 list_del(&km->list);
1673 write_unlock_bh(&xfrm_km_lock);
1674 return 0;
1675}
1676EXPORT_SYMBOL(xfrm_unregister_km);
1677
1678int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
1679{
1680 int err = 0;
1681 if (unlikely(afinfo == NULL))
1682 return -EINVAL;
1683 if (unlikely(afinfo->family >= NPROTO))
1684 return -EAFNOSUPPORT;
f3111502 1685 write_lock_bh(&xfrm_state_afinfo_lock);
1da177e4
LT
1686 if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
1687 err = -ENOBUFS;
edcd5821 1688 else
1da177e4 1689 xfrm_state_afinfo[afinfo->family] = afinfo;
f3111502 1690 write_unlock_bh(&xfrm_state_afinfo_lock);
1da177e4
LT
1691 return err;
1692}
1693EXPORT_SYMBOL(xfrm_state_register_afinfo);
1694
1695int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
1696{
1697 int err = 0;
1698 if (unlikely(afinfo == NULL))
1699 return -EINVAL;
1700 if (unlikely(afinfo->family >= NPROTO))
1701 return -EAFNOSUPPORT;
f3111502 1702 write_lock_bh(&xfrm_state_afinfo_lock);
1da177e4
LT
1703 if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
1704 if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
1705 err = -EINVAL;
edcd5821 1706 else
1da177e4 1707 xfrm_state_afinfo[afinfo->family] = NULL;
1da177e4 1708 }
f3111502 1709 write_unlock_bh(&xfrm_state_afinfo_lock);
1da177e4
LT
1710 return err;
1711}
1712EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
1713
cdca7265 1714struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
1da177e4
LT
1715{
1716 struct xfrm_state_afinfo *afinfo;
1717 if (unlikely(family >= NPROTO))
1718 return NULL;
1719 read_lock(&xfrm_state_afinfo_lock);
1720 afinfo = xfrm_state_afinfo[family];
546be240
HX
1721 if (unlikely(!afinfo))
1722 read_unlock(&xfrm_state_afinfo_lock);
1da177e4
LT
1723 return afinfo;
1724}
1725
cdca7265 1726void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
1da177e4 1727{
546be240 1728 read_unlock(&xfrm_state_afinfo_lock);
1da177e4
LT
1729}
1730
cdca7265
MK
1731EXPORT_SYMBOL(xfrm_state_get_afinfo);
1732EXPORT_SYMBOL(xfrm_state_put_afinfo);
1733
1da177e4
LT
1734/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
1735void xfrm_state_delete_tunnel(struct xfrm_state *x)
1736{
1737 if (x->tunnel) {
1738 struct xfrm_state *t = x->tunnel;
1739
1740 if (atomic_read(&t->tunnel_users) == 2)
1741 xfrm_state_delete(t);
1742 atomic_dec(&t->tunnel_users);
1743 xfrm_state_put(t);
1744 x->tunnel = NULL;
1745 }
1746}
1747EXPORT_SYMBOL(xfrm_state_delete_tunnel);
1748
1749int xfrm_state_mtu(struct xfrm_state *x, int mtu)
1750{
c5c25238 1751 int res;
1da177e4 1752
c5c25238
PM
1753 spin_lock_bh(&x->lock);
1754 if (x->km.state == XFRM_STATE_VALID &&
1755 x->type && x->type->get_mtu)
1756 res = x->type->get_mtu(x, mtu);
1757 else
28121617 1758 res = mtu - x->props.header_len;
c5c25238 1759 spin_unlock_bh(&x->lock);
1da177e4
LT
1760 return res;
1761}
1762
72cb6962
HX
1763int xfrm_init_state(struct xfrm_state *x)
1764{
d094cd83
HX
1765 struct xfrm_state_afinfo *afinfo;
1766 int family = x->props.family;
72cb6962
HX
1767 int err;
1768
d094cd83
HX
1769 err = -EAFNOSUPPORT;
1770 afinfo = xfrm_state_get_afinfo(family);
1771 if (!afinfo)
1772 goto error;
1773
1774 err = 0;
1775 if (afinfo->init_flags)
1776 err = afinfo->init_flags(x);
1777
1778 xfrm_state_put_afinfo(afinfo);
1779
1780 if (err)
1781 goto error;
1782
1783 err = -EPROTONOSUPPORT;
1784 x->type = xfrm_get_type(x->id.proto, family);
72cb6962
HX
1785 if (x->type == NULL)
1786 goto error;
1787
1788 err = x->type->init_state(x);
1789 if (err)
1790 goto error;
1791
b59f45d0
HX
1792 x->mode = xfrm_get_mode(x->props.mode, family);
1793 if (x->mode == NULL)
1794 goto error;
1795
72cb6962
HX
1796 x->km.state = XFRM_STATE_VALID;
1797
1798error:
1799 return err;
1800}
1801
1802EXPORT_SYMBOL(xfrm_init_state);
a716c119 1803
1da177e4
LT
1804void __init xfrm_state_init(void)
1805{
f034b5d4
DM
1806 unsigned int sz;
1807
1808 sz = sizeof(struct hlist_head) * 8;
1809
44e36b42
DM
1810 xfrm_state_bydst = xfrm_hash_alloc(sz);
1811 xfrm_state_bysrc = xfrm_hash_alloc(sz);
1812 xfrm_state_byspi = xfrm_hash_alloc(sz);
f034b5d4
DM
1813 if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi)
1814 panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes.");
1815 xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1);
1da177e4 1816
c4028958 1817 INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task);
1da177e4
LT
1818}
1819
ab5f5e8b
JL
1820#ifdef CONFIG_AUDITSYSCALL
1821static inline void xfrm_audit_common_stateinfo(struct xfrm_state *x,
1822 struct audit_buffer *audit_buf)
1823{
1824 if (x->security)
1825 audit_log_format(audit_buf, " sec_alg=%u sec_doi=%u sec_obj=%s",
1826 x->security->ctx_alg, x->security->ctx_doi,
1827 x->security->ctx_str);
1828
1829 switch(x->props.family) {
1830 case AF_INET:
1831 audit_log_format(audit_buf, " src=%u.%u.%u.%u dst=%u.%u.%u.%u",
1832 NIPQUAD(x->props.saddr.a4),
1833 NIPQUAD(x->id.daddr.a4));
1834 break;
1835 case AF_INET6:
1836 {
1837 struct in6_addr saddr6, daddr6;
1838
1839 memcpy(&saddr6, x->props.saddr.a6,
1840 sizeof(struct in6_addr));
1841 memcpy(&daddr6, x->id.daddr.a6,
1842 sizeof(struct in6_addr));
1843 audit_log_format(audit_buf,
1844 " src=" NIP6_FMT " dst=" NIP6_FMT,
1845 NIP6(saddr6), NIP6(daddr6));
1846 }
1847 break;
1848 }
1849}
1850
1851void
1852xfrm_audit_state_add(struct xfrm_state *x, int result, u32 auid, u32 sid)
1853{
1854 struct audit_buffer *audit_buf;
1855 extern int audit_enabled;
1856
1857 if (audit_enabled == 0)
1858 return;
1859 audit_buf = xfrm_audit_start(sid, auid);
1860 if (audit_buf == NULL)
1861 return;
1862 audit_log_format(audit_buf, " op=SAD-add res=%u",result);
1863 xfrm_audit_common_stateinfo(x, audit_buf);
1864 audit_log_format(audit_buf, " spi=%lu(0x%lx)",
1865 (unsigned long)x->id.spi, (unsigned long)x->id.spi);
1866 audit_log_end(audit_buf);
1867}
1868EXPORT_SYMBOL_GPL(xfrm_audit_state_add);
1869
1870void
1871xfrm_audit_state_delete(struct xfrm_state *x, int result, u32 auid, u32 sid)
1872{
1873 struct audit_buffer *audit_buf;
1874 extern int audit_enabled;
1875
1876 if (audit_enabled == 0)
1877 return;
1878 audit_buf = xfrm_audit_start(sid, auid);
1879 if (audit_buf == NULL)
1880 return;
1881 audit_log_format(audit_buf, " op=SAD-delete res=%u",result);
1882 xfrm_audit_common_stateinfo(x, audit_buf);
1883 audit_log_format(audit_buf, " spi=%lu(0x%lx)",
1884 (unsigned long)x->id.spi, (unsigned long)x->id.spi);
1885 audit_log_end(audit_buf);
1886}
1887EXPORT_SYMBOL_GPL(xfrm_audit_state_delete);
1888#endif /* CONFIG_AUDITSYSCALL */
This page took 0.422931 seconds and 5 git commands to generate.