diff options
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r-- | net/xfrm/xfrm_state.c | 381 |
1 files changed, 202 insertions, 179 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 508337f97249..2fd57f8f77c1 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -24,17 +24,6 @@ | |||
24 | 24 | ||
25 | #include "xfrm_hash.h" | 25 | #include "xfrm_hash.h" |
26 | 26 | ||
27 | struct sock *xfrm_nl; | ||
28 | EXPORT_SYMBOL(xfrm_nl); | ||
29 | |||
30 | u32 sysctl_xfrm_aevent_etime __read_mostly = XFRM_AE_ETIME; | ||
31 | EXPORT_SYMBOL(sysctl_xfrm_aevent_etime); | ||
32 | |||
33 | u32 sysctl_xfrm_aevent_rseqth __read_mostly = XFRM_AE_SEQT_SIZE; | ||
34 | EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth); | ||
35 | |||
36 | u32 sysctl_xfrm_acq_expires __read_mostly = 30; | ||
37 | |||
38 | /* Each xfrm_state may be linked to two tables: | 27 | /* Each xfrm_state may be linked to two tables: |
39 | 28 | ||
40 | 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl) | 29 | 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl) |
@@ -44,19 +33,7 @@ u32 sysctl_xfrm_acq_expires __read_mostly = 30; | |||
44 | 33 | ||
45 | static DEFINE_SPINLOCK(xfrm_state_lock); | 34 | static DEFINE_SPINLOCK(xfrm_state_lock); |
46 | 35 | ||
47 | /* Hash table to find appropriate SA towards given target (endpoint | ||
48 | * of tunnel or destination of transport mode) allowed by selector. | ||
49 | * | ||
50 | * Main use is finding SA after policy selected tunnel or transport mode. | ||
51 | * Also, it can be used by ah/esp icmp error handler to find offending SA. | ||
52 | */ | ||
53 | static LIST_HEAD(xfrm_state_all); | ||
54 | static struct hlist_head *xfrm_state_bydst __read_mostly; | ||
55 | static struct hlist_head *xfrm_state_bysrc __read_mostly; | ||
56 | static struct hlist_head *xfrm_state_byspi __read_mostly; | ||
57 | static unsigned int xfrm_state_hmask __read_mostly; | ||
58 | static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; | 36 | static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; |
59 | static unsigned int xfrm_state_num; | ||
60 | static unsigned int xfrm_state_genid; | 37 | static unsigned int xfrm_state_genid; |
61 | 38 | ||
62 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); | 39 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); |
@@ -69,25 +46,27 @@ static void xfrm_audit_state_replay(struct xfrm_state *x, | |||
69 | #define xfrm_audit_state_replay(x, s, sq) do { ; } while (0) | 46 | #define xfrm_audit_state_replay(x, s, sq) do { ; } while (0) |
70 | #endif /* CONFIG_AUDITSYSCALL */ | 47 | #endif /* CONFIG_AUDITSYSCALL */ |
71 | 48 | ||
72 | static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, | 49 | static inline unsigned int xfrm_dst_hash(struct net *net, |
50 | xfrm_address_t *daddr, | ||
73 | xfrm_address_t *saddr, | 51 | xfrm_address_t *saddr, |
74 | u32 reqid, | 52 | u32 reqid, |
75 | unsigned short family) | 53 | unsigned short family) |
76 | { | 54 | { |
77 | return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); | 55 | return __xfrm_dst_hash(daddr, saddr, reqid, family, net->xfrm.state_hmask); |
78 | } | 56 | } |
79 | 57 | ||
80 | static inline unsigned int xfrm_src_hash(xfrm_address_t *daddr, | 58 | static inline unsigned int xfrm_src_hash(struct net *net, |
59 | xfrm_address_t *daddr, | ||
81 | xfrm_address_t *saddr, | 60 | xfrm_address_t *saddr, |
82 | unsigned short family) | 61 | unsigned short family) |
83 | { | 62 | { |
84 | return __xfrm_src_hash(daddr, saddr, family, xfrm_state_hmask); | 63 | return __xfrm_src_hash(daddr, saddr, family, net->xfrm.state_hmask); |
85 | } | 64 | } |
86 | 65 | ||
87 | static inline unsigned int | 66 | static inline unsigned int |
88 | xfrm_spi_hash(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) | 67 | xfrm_spi_hash(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) |
89 | { | 68 | { |
90 | return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask); | 69 | return __xfrm_spi_hash(daddr, spi, proto, family, net->xfrm.state_hmask); |
91 | } | 70 | } |
92 | 71 | ||
93 | static void xfrm_hash_transfer(struct hlist_head *list, | 72 | static void xfrm_hash_transfer(struct hlist_head *list, |
@@ -121,16 +100,16 @@ static void xfrm_hash_transfer(struct hlist_head *list, | |||
121 | } | 100 | } |
122 | } | 101 | } |
123 | 102 | ||
124 | static unsigned long xfrm_hash_new_size(void) | 103 | static unsigned long xfrm_hash_new_size(unsigned int state_hmask) |
125 | { | 104 | { |
126 | return ((xfrm_state_hmask + 1) << 1) * | 105 | return ((state_hmask + 1) << 1) * sizeof(struct hlist_head); |
127 | sizeof(struct hlist_head); | ||
128 | } | 106 | } |
129 | 107 | ||
130 | static DEFINE_MUTEX(hash_resize_mutex); | 108 | static DEFINE_MUTEX(hash_resize_mutex); |
131 | 109 | ||
132 | static void xfrm_hash_resize(struct work_struct *__unused) | 110 | static void xfrm_hash_resize(struct work_struct *work) |
133 | { | 111 | { |
112 | struct net *net = container_of(work, struct net, xfrm.state_hash_work); | ||
134 | struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi; | 113 | struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi; |
135 | unsigned long nsize, osize; | 114 | unsigned long nsize, osize; |
136 | unsigned int nhashmask, ohashmask; | 115 | unsigned int nhashmask, ohashmask; |
@@ -138,7 +117,7 @@ static void xfrm_hash_resize(struct work_struct *__unused) | |||
138 | 117 | ||
139 | mutex_lock(&hash_resize_mutex); | 118 | mutex_lock(&hash_resize_mutex); |
140 | 119 | ||
141 | nsize = xfrm_hash_new_size(); | 120 | nsize = xfrm_hash_new_size(net->xfrm.state_hmask); |
142 | ndst = xfrm_hash_alloc(nsize); | 121 | ndst = xfrm_hash_alloc(nsize); |
143 | if (!ndst) | 122 | if (!ndst) |
144 | goto out_unlock; | 123 | goto out_unlock; |
@@ -157,19 +136,19 @@ static void xfrm_hash_resize(struct work_struct *__unused) | |||
157 | spin_lock_bh(&xfrm_state_lock); | 136 | spin_lock_bh(&xfrm_state_lock); |
158 | 137 | ||
159 | nhashmask = (nsize / sizeof(struct hlist_head)) - 1U; | 138 | nhashmask = (nsize / sizeof(struct hlist_head)) - 1U; |
160 | for (i = xfrm_state_hmask; i >= 0; i--) | 139 | for (i = net->xfrm.state_hmask; i >= 0; i--) |
161 | xfrm_hash_transfer(xfrm_state_bydst+i, ndst, nsrc, nspi, | 140 | xfrm_hash_transfer(net->xfrm.state_bydst+i, ndst, nsrc, nspi, |
162 | nhashmask); | 141 | nhashmask); |
163 | 142 | ||
164 | odst = xfrm_state_bydst; | 143 | odst = net->xfrm.state_bydst; |
165 | osrc = xfrm_state_bysrc; | 144 | osrc = net->xfrm.state_bysrc; |
166 | ospi = xfrm_state_byspi; | 145 | ospi = net->xfrm.state_byspi; |
167 | ohashmask = xfrm_state_hmask; | 146 | ohashmask = net->xfrm.state_hmask; |
168 | 147 | ||
169 | xfrm_state_bydst = ndst; | 148 | net->xfrm.state_bydst = ndst; |
170 | xfrm_state_bysrc = nsrc; | 149 | net->xfrm.state_bysrc = nsrc; |
171 | xfrm_state_byspi = nspi; | 150 | net->xfrm.state_byspi = nspi; |
172 | xfrm_state_hmask = nhashmask; | 151 | net->xfrm.state_hmask = nhashmask; |
173 | 152 | ||
174 | spin_unlock_bh(&xfrm_state_lock); | 153 | spin_unlock_bh(&xfrm_state_lock); |
175 | 154 | ||
@@ -182,16 +161,9 @@ out_unlock: | |||
182 | mutex_unlock(&hash_resize_mutex); | 161 | mutex_unlock(&hash_resize_mutex); |
183 | } | 162 | } |
184 | 163 | ||
185 | static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize); | ||
186 | |||
187 | DECLARE_WAIT_QUEUE_HEAD(km_waitq); | ||
188 | EXPORT_SYMBOL(km_waitq); | ||
189 | |||
190 | static DEFINE_RWLOCK(xfrm_state_afinfo_lock); | 164 | static DEFINE_RWLOCK(xfrm_state_afinfo_lock); |
191 | static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; | 165 | static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; |
192 | 166 | ||
193 | static struct work_struct xfrm_state_gc_work; | ||
194 | static HLIST_HEAD(xfrm_state_gc_list); | ||
195 | static DEFINE_SPINLOCK(xfrm_state_gc_lock); | 167 | static DEFINE_SPINLOCK(xfrm_state_gc_lock); |
196 | 168 | ||
197 | int __xfrm_state_delete(struct xfrm_state *x); | 169 | int __xfrm_state_delete(struct xfrm_state *x); |
@@ -401,20 +373,21 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
401 | kfree(x); | 373 | kfree(x); |
402 | } | 374 | } |
403 | 375 | ||
404 | static void xfrm_state_gc_task(struct work_struct *data) | 376 | static void xfrm_state_gc_task(struct work_struct *work) |
405 | { | 377 | { |
378 | struct net *net = container_of(work, struct net, xfrm.state_gc_work); | ||
406 | struct xfrm_state *x; | 379 | struct xfrm_state *x; |
407 | struct hlist_node *entry, *tmp; | 380 | struct hlist_node *entry, *tmp; |
408 | struct hlist_head gc_list; | 381 | struct hlist_head gc_list; |
409 | 382 | ||
410 | spin_lock_bh(&xfrm_state_gc_lock); | 383 | spin_lock_bh(&xfrm_state_gc_lock); |
411 | hlist_move_list(&xfrm_state_gc_list, &gc_list); | 384 | hlist_move_list(&net->xfrm.state_gc_list, &gc_list); |
412 | spin_unlock_bh(&xfrm_state_gc_lock); | 385 | spin_unlock_bh(&xfrm_state_gc_lock); |
413 | 386 | ||
414 | hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist) | 387 | hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist) |
415 | xfrm_state_gc_destroy(x); | 388 | xfrm_state_gc_destroy(x); |
416 | 389 | ||
417 | wake_up(&km_waitq); | 390 | wake_up(&net->xfrm.km_waitq); |
418 | } | 391 | } |
419 | 392 | ||
420 | static inline unsigned long make_jiffies(long secs) | 393 | static inline unsigned long make_jiffies(long secs) |
@@ -428,6 +401,7 @@ static inline unsigned long make_jiffies(long secs) | |||
428 | static void xfrm_timer_handler(unsigned long data) | 401 | static void xfrm_timer_handler(unsigned long data) |
429 | { | 402 | { |
430 | struct xfrm_state *x = (struct xfrm_state*)data; | 403 | struct xfrm_state *x = (struct xfrm_state*)data; |
404 | struct net *net = xs_net(x); | ||
431 | unsigned long now = get_seconds(); | 405 | unsigned long now = get_seconds(); |
432 | long next = LONG_MAX; | 406 | long next = LONG_MAX; |
433 | int warn = 0; | 407 | int warn = 0; |
@@ -485,7 +459,7 @@ resched: | |||
485 | expired: | 459 | expired: |
486 | if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0) { | 460 | if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0) { |
487 | x->km.state = XFRM_STATE_EXPIRED; | 461 | x->km.state = XFRM_STATE_EXPIRED; |
488 | wake_up(&km_waitq); | 462 | wake_up(&net->xfrm.km_waitq); |
489 | next = 2; | 463 | next = 2; |
490 | goto resched; | 464 | goto resched; |
491 | } | 465 | } |
@@ -504,13 +478,14 @@ out: | |||
504 | 478 | ||
505 | static void xfrm_replay_timer_handler(unsigned long data); | 479 | static void xfrm_replay_timer_handler(unsigned long data); |
506 | 480 | ||
507 | struct xfrm_state *xfrm_state_alloc(void) | 481 | struct xfrm_state *xfrm_state_alloc(struct net *net) |
508 | { | 482 | { |
509 | struct xfrm_state *x; | 483 | struct xfrm_state *x; |
510 | 484 | ||
511 | x = kzalloc(sizeof(struct xfrm_state), GFP_ATOMIC); | 485 | x = kzalloc(sizeof(struct xfrm_state), GFP_ATOMIC); |
512 | 486 | ||
513 | if (x) { | 487 | if (x) { |
488 | write_pnet(&x->xs_net, net); | ||
514 | atomic_set(&x->refcnt, 1); | 489 | atomic_set(&x->refcnt, 1); |
515 | atomic_set(&x->tunnel_users, 0); | 490 | atomic_set(&x->tunnel_users, 0); |
516 | INIT_LIST_HEAD(&x->km.all); | 491 | INIT_LIST_HEAD(&x->km.all); |
@@ -537,17 +512,20 @@ EXPORT_SYMBOL(xfrm_state_alloc); | |||
537 | 512 | ||
538 | void __xfrm_state_destroy(struct xfrm_state *x) | 513 | void __xfrm_state_destroy(struct xfrm_state *x) |
539 | { | 514 | { |
515 | struct net *net = xs_net(x); | ||
516 | |||
540 | WARN_ON(x->km.state != XFRM_STATE_DEAD); | 517 | WARN_ON(x->km.state != XFRM_STATE_DEAD); |
541 | 518 | ||
542 | spin_lock_bh(&xfrm_state_gc_lock); | 519 | spin_lock_bh(&xfrm_state_gc_lock); |
543 | hlist_add_head(&x->gclist, &xfrm_state_gc_list); | 520 | hlist_add_head(&x->gclist, &net->xfrm.state_gc_list); |
544 | spin_unlock_bh(&xfrm_state_gc_lock); | 521 | spin_unlock_bh(&xfrm_state_gc_lock); |
545 | schedule_work(&xfrm_state_gc_work); | 522 | schedule_work(&net->xfrm.state_gc_work); |
546 | } | 523 | } |
547 | EXPORT_SYMBOL(__xfrm_state_destroy); | 524 | EXPORT_SYMBOL(__xfrm_state_destroy); |
548 | 525 | ||
549 | int __xfrm_state_delete(struct xfrm_state *x) | 526 | int __xfrm_state_delete(struct xfrm_state *x) |
550 | { | 527 | { |
528 | struct net *net = xs_net(x); | ||
551 | int err = -ESRCH; | 529 | int err = -ESRCH; |
552 | 530 | ||
553 | if (x->km.state != XFRM_STATE_DEAD) { | 531 | if (x->km.state != XFRM_STATE_DEAD) { |
@@ -558,7 +536,7 @@ int __xfrm_state_delete(struct xfrm_state *x) | |||
558 | hlist_del(&x->bysrc); | 536 | hlist_del(&x->bysrc); |
559 | if (x->id.spi) | 537 | if (x->id.spi) |
560 | hlist_del(&x->byspi); | 538 | hlist_del(&x->byspi); |
561 | xfrm_state_num--; | 539 | net->xfrm.state_num--; |
562 | spin_unlock(&xfrm_state_lock); | 540 | spin_unlock(&xfrm_state_lock); |
563 | 541 | ||
564 | /* All xfrm_state objects are created by xfrm_state_alloc. | 542 | /* All xfrm_state objects are created by xfrm_state_alloc. |
@@ -587,15 +565,15 @@ EXPORT_SYMBOL(xfrm_state_delete); | |||
587 | 565 | ||
588 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 566 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
589 | static inline int | 567 | static inline int |
590 | xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info) | 568 | xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audit_info) |
591 | { | 569 | { |
592 | int i, err = 0; | 570 | int i, err = 0; |
593 | 571 | ||
594 | for (i = 0; i <= xfrm_state_hmask; i++) { | 572 | for (i = 0; i <= net->xfrm.state_hmask; i++) { |
595 | struct hlist_node *entry; | 573 | struct hlist_node *entry; |
596 | struct xfrm_state *x; | 574 | struct xfrm_state *x; |
597 | 575 | ||
598 | hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) { | 576 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { |
599 | if (xfrm_id_proto_match(x->id.proto, proto) && | 577 | if (xfrm_id_proto_match(x->id.proto, proto) && |
600 | (err = security_xfrm_state_delete(x)) != 0) { | 578 | (err = security_xfrm_state_delete(x)) != 0) { |
601 | xfrm_audit_state_delete(x, 0, | 579 | xfrm_audit_state_delete(x, 0, |
@@ -611,26 +589,26 @@ xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info) | |||
611 | } | 589 | } |
612 | #else | 590 | #else |
613 | static inline int | 591 | static inline int |
614 | xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info) | 592 | xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audit_info) |
615 | { | 593 | { |
616 | return 0; | 594 | return 0; |
617 | } | 595 | } |
618 | #endif | 596 | #endif |
619 | 597 | ||
620 | int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info) | 598 | int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info) |
621 | { | 599 | { |
622 | int i, err = 0; | 600 | int i, err = 0; |
623 | 601 | ||
624 | spin_lock_bh(&xfrm_state_lock); | 602 | spin_lock_bh(&xfrm_state_lock); |
625 | err = xfrm_state_flush_secctx_check(proto, audit_info); | 603 | err = xfrm_state_flush_secctx_check(net, proto, audit_info); |
626 | if (err) | 604 | if (err) |
627 | goto out; | 605 | goto out; |
628 | 606 | ||
629 | for (i = 0; i <= xfrm_state_hmask; i++) { | 607 | for (i = 0; i <= net->xfrm.state_hmask; i++) { |
630 | struct hlist_node *entry; | 608 | struct hlist_node *entry; |
631 | struct xfrm_state *x; | 609 | struct xfrm_state *x; |
632 | restart: | 610 | restart: |
633 | hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) { | 611 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { |
634 | if (!xfrm_state_kern(x) && | 612 | if (!xfrm_state_kern(x) && |
635 | xfrm_id_proto_match(x->id.proto, proto)) { | 613 | xfrm_id_proto_match(x->id.proto, proto)) { |
636 | xfrm_state_hold(x); | 614 | xfrm_state_hold(x); |
@@ -652,7 +630,7 @@ restart: | |||
652 | 630 | ||
653 | out: | 631 | out: |
654 | spin_unlock_bh(&xfrm_state_lock); | 632 | spin_unlock_bh(&xfrm_state_lock); |
655 | wake_up(&km_waitq); | 633 | wake_up(&net->xfrm.km_waitq); |
656 | return err; | 634 | return err; |
657 | } | 635 | } |
658 | EXPORT_SYMBOL(xfrm_state_flush); | 636 | EXPORT_SYMBOL(xfrm_state_flush); |
@@ -660,8 +638,8 @@ EXPORT_SYMBOL(xfrm_state_flush); | |||
660 | void xfrm_sad_getinfo(struct xfrmk_sadinfo *si) | 638 | void xfrm_sad_getinfo(struct xfrmk_sadinfo *si) |
661 | { | 639 | { |
662 | spin_lock_bh(&xfrm_state_lock); | 640 | spin_lock_bh(&xfrm_state_lock); |
663 | si->sadcnt = xfrm_state_num; | 641 | si->sadcnt = init_net.xfrm.state_num; |
664 | si->sadhcnt = xfrm_state_hmask; | 642 | si->sadhcnt = init_net.xfrm.state_hmask; |
665 | si->sadhmcnt = xfrm_state_hashmax; | 643 | si->sadhmcnt = xfrm_state_hashmax; |
666 | spin_unlock_bh(&xfrm_state_lock); | 644 | spin_unlock_bh(&xfrm_state_lock); |
667 | } | 645 | } |
@@ -681,13 +659,13 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
681 | return 0; | 659 | return 0; |
682 | } | 660 | } |
683 | 661 | ||
684 | static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) | 662 | static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) |
685 | { | 663 | { |
686 | unsigned int h = xfrm_spi_hash(daddr, spi, proto, family); | 664 | unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family); |
687 | struct xfrm_state *x; | 665 | struct xfrm_state *x; |
688 | struct hlist_node *entry; | 666 | struct hlist_node *entry; |
689 | 667 | ||
690 | hlist_for_each_entry(x, entry, xfrm_state_byspi+h, byspi) { | 668 | hlist_for_each_entry(x, entry, net->xfrm.state_byspi+h, byspi) { |
691 | if (x->props.family != family || | 669 | if (x->props.family != family || |
692 | x->id.spi != spi || | 670 | x->id.spi != spi || |
693 | x->id.proto != proto) | 671 | x->id.proto != proto) |
@@ -713,13 +691,13 @@ static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, | |||
713 | return NULL; | 691 | return NULL; |
714 | } | 692 | } |
715 | 693 | ||
716 | static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) | 694 | static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) |
717 | { | 695 | { |
718 | unsigned int h = xfrm_src_hash(daddr, saddr, family); | 696 | unsigned int h = xfrm_src_hash(net, daddr, saddr, family); |
719 | struct xfrm_state *x; | 697 | struct xfrm_state *x; |
720 | struct hlist_node *entry; | 698 | struct hlist_node *entry; |
721 | 699 | ||
722 | hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) { | 700 | hlist_for_each_entry(x, entry, net->xfrm.state_bysrc+h, bysrc) { |
723 | if (x->props.family != family || | 701 | if (x->props.family != family || |
724 | x->id.proto != proto) | 702 | x->id.proto != proto) |
725 | continue; | 703 | continue; |
@@ -751,21 +729,23 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm | |||
751 | static inline struct xfrm_state * | 729 | static inline struct xfrm_state * |
752 | __xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) | 730 | __xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) |
753 | { | 731 | { |
732 | struct net *net = xs_net(x); | ||
733 | |||
754 | if (use_spi) | 734 | if (use_spi) |
755 | return __xfrm_state_lookup(&x->id.daddr, x->id.spi, | 735 | return __xfrm_state_lookup(net, &x->id.daddr, x->id.spi, |
756 | x->id.proto, family); | 736 | x->id.proto, family); |
757 | else | 737 | else |
758 | return __xfrm_state_lookup_byaddr(&x->id.daddr, | 738 | return __xfrm_state_lookup_byaddr(net, &x->id.daddr, |
759 | &x->props.saddr, | 739 | &x->props.saddr, |
760 | x->id.proto, family); | 740 | x->id.proto, family); |
761 | } | 741 | } |
762 | 742 | ||
763 | static void xfrm_hash_grow_check(int have_hash_collision) | 743 | static void xfrm_hash_grow_check(struct net *net, int have_hash_collision) |
764 | { | 744 | { |
765 | if (have_hash_collision && | 745 | if (have_hash_collision && |
766 | (xfrm_state_hmask + 1) < xfrm_state_hashmax && | 746 | (net->xfrm.state_hmask + 1) < xfrm_state_hashmax && |
767 | xfrm_state_num > xfrm_state_hmask) | 747 | net->xfrm.state_num > net->xfrm.state_hmask) |
768 | schedule_work(&xfrm_hash_work); | 748 | schedule_work(&net->xfrm.state_hash_work); |
769 | } | 749 | } |
770 | 750 | ||
771 | struct xfrm_state * | 751 | struct xfrm_state * |
@@ -774,6 +754,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
774 | struct xfrm_policy *pol, int *err, | 754 | struct xfrm_policy *pol, int *err, |
775 | unsigned short family) | 755 | unsigned short family) |
776 | { | 756 | { |
757 | struct net *net = xp_net(pol); | ||
777 | unsigned int h; | 758 | unsigned int h; |
778 | struct hlist_node *entry; | 759 | struct hlist_node *entry; |
779 | struct xfrm_state *x, *x0, *to_put; | 760 | struct xfrm_state *x, *x0, *to_put; |
@@ -784,8 +765,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
784 | to_put = NULL; | 765 | to_put = NULL; |
785 | 766 | ||
786 | spin_lock_bh(&xfrm_state_lock); | 767 | spin_lock_bh(&xfrm_state_lock); |
787 | h = xfrm_dst_hash(daddr, saddr, tmpl->reqid, family); | 768 | h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, family); |
788 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 769 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
789 | if (x->props.family == family && | 770 | if (x->props.family == family && |
790 | x->props.reqid == tmpl->reqid && | 771 | x->props.reqid == tmpl->reqid && |
791 | !(x->props.flags & XFRM_STATE_WILDRECV) && | 772 | !(x->props.flags & XFRM_STATE_WILDRECV) && |
@@ -829,13 +810,13 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
829 | x = best; | 810 | x = best; |
830 | if (!x && !error && !acquire_in_progress) { | 811 | if (!x && !error && !acquire_in_progress) { |
831 | if (tmpl->id.spi && | 812 | if (tmpl->id.spi && |
832 | (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi, | 813 | (x0 = __xfrm_state_lookup(net, daddr, tmpl->id.spi, |
833 | tmpl->id.proto, family)) != NULL) { | 814 | tmpl->id.proto, family)) != NULL) { |
834 | to_put = x0; | 815 | to_put = x0; |
835 | error = -EEXIST; | 816 | error = -EEXIST; |
836 | goto out; | 817 | goto out; |
837 | } | 818 | } |
838 | x = xfrm_state_alloc(); | 819 | x = xfrm_state_alloc(net); |
839 | if (x == NULL) { | 820 | if (x == NULL) { |
840 | error = -ENOMEM; | 821 | error = -ENOMEM; |
841 | goto out; | 822 | goto out; |
@@ -854,19 +835,19 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
854 | 835 | ||
855 | if (km_query(x, tmpl, pol) == 0) { | 836 | if (km_query(x, tmpl, pol) == 0) { |
856 | x->km.state = XFRM_STATE_ACQ; | 837 | x->km.state = XFRM_STATE_ACQ; |
857 | list_add(&x->km.all, &xfrm_state_all); | 838 | list_add(&x->km.all, &net->xfrm.state_all); |
858 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 839 | hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); |
859 | h = xfrm_src_hash(daddr, saddr, family); | 840 | h = xfrm_src_hash(net, daddr, saddr, family); |
860 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 841 | hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); |
861 | if (x->id.spi) { | 842 | if (x->id.spi) { |
862 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); | 843 | h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, family); |
863 | hlist_add_head(&x->byspi, xfrm_state_byspi+h); | 844 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); |
864 | } | 845 | } |
865 | x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires; | 846 | x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; |
866 | x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; | 847 | x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; |
867 | add_timer(&x->timer); | 848 | add_timer(&x->timer); |
868 | xfrm_state_num++; | 849 | net->xfrm.state_num++; |
869 | xfrm_hash_grow_check(x->bydst.next != NULL); | 850 | xfrm_hash_grow_check(net, x->bydst.next != NULL); |
870 | } else { | 851 | } else { |
871 | x->km.state = XFRM_STATE_DEAD; | 852 | x->km.state = XFRM_STATE_DEAD; |
872 | to_put = x; | 853 | to_put = x; |
@@ -886,7 +867,8 @@ out: | |||
886 | } | 867 | } |
887 | 868 | ||
888 | struct xfrm_state * | 869 | struct xfrm_state * |
889 | xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | 870 | xfrm_stateonly_find(struct net *net, |
871 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
890 | unsigned short family, u8 mode, u8 proto, u32 reqid) | 872 | unsigned short family, u8 mode, u8 proto, u32 reqid) |
891 | { | 873 | { |
892 | unsigned int h; | 874 | unsigned int h; |
@@ -894,8 +876,8 @@ xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
894 | struct hlist_node *entry; | 876 | struct hlist_node *entry; |
895 | 877 | ||
896 | spin_lock(&xfrm_state_lock); | 878 | spin_lock(&xfrm_state_lock); |
897 | h = xfrm_dst_hash(daddr, saddr, reqid, family); | 879 | h = xfrm_dst_hash(net, daddr, saddr, reqid, family); |
898 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 880 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
899 | if (x->props.family == family && | 881 | if (x->props.family == family && |
900 | x->props.reqid == reqid && | 882 | x->props.reqid == reqid && |
901 | !(x->props.flags & XFRM_STATE_WILDRECV) && | 883 | !(x->props.flags & XFRM_STATE_WILDRECV) && |
@@ -919,48 +901,50 @@ EXPORT_SYMBOL(xfrm_stateonly_find); | |||
919 | 901 | ||
920 | static void __xfrm_state_insert(struct xfrm_state *x) | 902 | static void __xfrm_state_insert(struct xfrm_state *x) |
921 | { | 903 | { |
904 | struct net *net = xs_net(x); | ||
922 | unsigned int h; | 905 | unsigned int h; |
923 | 906 | ||
924 | x->genid = ++xfrm_state_genid; | 907 | x->genid = ++xfrm_state_genid; |
925 | 908 | ||
926 | list_add(&x->km.all, &xfrm_state_all); | 909 | list_add(&x->km.all, &net->xfrm.state_all); |
927 | 910 | ||
928 | h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr, | 911 | h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr, |
929 | x->props.reqid, x->props.family); | 912 | x->props.reqid, x->props.family); |
930 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 913 | hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); |
931 | 914 | ||
932 | h = xfrm_src_hash(&x->id.daddr, &x->props.saddr, x->props.family); | 915 | h = xfrm_src_hash(net, &x->id.daddr, &x->props.saddr, x->props.family); |
933 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 916 | hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); |
934 | 917 | ||
935 | if (x->id.spi) { | 918 | if (x->id.spi) { |
936 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, | 919 | h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, |
937 | x->props.family); | 920 | x->props.family); |
938 | 921 | ||
939 | hlist_add_head(&x->byspi, xfrm_state_byspi+h); | 922 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); |
940 | } | 923 | } |
941 | 924 | ||
942 | mod_timer(&x->timer, jiffies + HZ); | 925 | mod_timer(&x->timer, jiffies + HZ); |
943 | if (x->replay_maxage) | 926 | if (x->replay_maxage) |
944 | mod_timer(&x->rtimer, jiffies + x->replay_maxage); | 927 | mod_timer(&x->rtimer, jiffies + x->replay_maxage); |
945 | 928 | ||
946 | wake_up(&km_waitq); | 929 | wake_up(&net->xfrm.km_waitq); |
947 | 930 | ||
948 | xfrm_state_num++; | 931 | net->xfrm.state_num++; |
949 | 932 | ||
950 | xfrm_hash_grow_check(x->bydst.next != NULL); | 933 | xfrm_hash_grow_check(net, x->bydst.next != NULL); |
951 | } | 934 | } |
952 | 935 | ||
953 | /* xfrm_state_lock is held */ | 936 | /* xfrm_state_lock is held */ |
954 | static void __xfrm_state_bump_genids(struct xfrm_state *xnew) | 937 | static void __xfrm_state_bump_genids(struct xfrm_state *xnew) |
955 | { | 938 | { |
939 | struct net *net = xs_net(xnew); | ||
956 | unsigned short family = xnew->props.family; | 940 | unsigned short family = xnew->props.family; |
957 | u32 reqid = xnew->props.reqid; | 941 | u32 reqid = xnew->props.reqid; |
958 | struct xfrm_state *x; | 942 | struct xfrm_state *x; |
959 | struct hlist_node *entry; | 943 | struct hlist_node *entry; |
960 | unsigned int h; | 944 | unsigned int h; |
961 | 945 | ||
962 | h = xfrm_dst_hash(&xnew->id.daddr, &xnew->props.saddr, reqid, family); | 946 | h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family); |
963 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 947 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
964 | if (x->props.family == family && | 948 | if (x->props.family == family && |
965 | x->props.reqid == reqid && | 949 | x->props.reqid == reqid && |
966 | !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && | 950 | !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && |
@@ -979,13 +963,13 @@ void xfrm_state_insert(struct xfrm_state *x) | |||
979 | EXPORT_SYMBOL(xfrm_state_insert); | 963 | EXPORT_SYMBOL(xfrm_state_insert); |
980 | 964 | ||
981 | /* xfrm_state_lock is held */ | 965 | /* xfrm_state_lock is held */ |
982 | static 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) | 966 | static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) |
983 | { | 967 | { |
984 | unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family); | 968 | unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family); |
985 | struct hlist_node *entry; | 969 | struct hlist_node *entry; |
986 | struct xfrm_state *x; | 970 | struct xfrm_state *x; |
987 | 971 | ||
988 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 972 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
989 | if (x->props.reqid != reqid || | 973 | if (x->props.reqid != reqid || |
990 | x->props.mode != mode || | 974 | x->props.mode != mode || |
991 | x->props.family != family || | 975 | x->props.family != family || |
@@ -1017,7 +1001,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re | |||
1017 | if (!create) | 1001 | if (!create) |
1018 | return NULL; | 1002 | return NULL; |
1019 | 1003 | ||
1020 | x = xfrm_state_alloc(); | 1004 | x = xfrm_state_alloc(net); |
1021 | if (likely(x)) { | 1005 | if (likely(x)) { |
1022 | switch (family) { | 1006 | switch (family) { |
1023 | case AF_INET: | 1007 | case AF_INET: |
@@ -1048,27 +1032,28 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re | |||
1048 | x->props.family = family; | 1032 | x->props.family = family; |
1049 | x->props.mode = mode; | 1033 | x->props.mode = mode; |
1050 | x->props.reqid = reqid; | 1034 | x->props.reqid = reqid; |
1051 | x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires; | 1035 | x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; |
1052 | xfrm_state_hold(x); | 1036 | xfrm_state_hold(x); |
1053 | x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; | 1037 | x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; |
1054 | add_timer(&x->timer); | 1038 | add_timer(&x->timer); |
1055 | list_add(&x->km.all, &xfrm_state_all); | 1039 | list_add(&x->km.all, &net->xfrm.state_all); |
1056 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 1040 | hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); |
1057 | h = xfrm_src_hash(daddr, saddr, family); | 1041 | h = xfrm_src_hash(net, daddr, saddr, family); |
1058 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 1042 | hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); |
1059 | 1043 | ||
1060 | xfrm_state_num++; | 1044 | net->xfrm.state_num++; |
1061 | 1045 | ||
1062 | xfrm_hash_grow_check(x->bydst.next != NULL); | 1046 | xfrm_hash_grow_check(net, x->bydst.next != NULL); |
1063 | } | 1047 | } |
1064 | 1048 | ||
1065 | return x; | 1049 | return x; |
1066 | } | 1050 | } |
1067 | 1051 | ||
1068 | static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); | 1052 | static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq); |
1069 | 1053 | ||
1070 | int xfrm_state_add(struct xfrm_state *x) | 1054 | int xfrm_state_add(struct xfrm_state *x) |
1071 | { | 1055 | { |
1056 | struct net *net = xs_net(x); | ||
1072 | struct xfrm_state *x1, *to_put; | 1057 | struct xfrm_state *x1, *to_put; |
1073 | int family; | 1058 | int family; |
1074 | int err; | 1059 | int err; |
@@ -1089,7 +1074,7 @@ int xfrm_state_add(struct xfrm_state *x) | |||
1089 | } | 1074 | } |
1090 | 1075 | ||
1091 | if (use_spi && x->km.seq) { | 1076 | if (use_spi && x->km.seq) { |
1092 | x1 = __xfrm_find_acq_byseq(x->km.seq); | 1077 | x1 = __xfrm_find_acq_byseq(net, x->km.seq); |
1093 | if (x1 && ((x1->id.proto != x->id.proto) || | 1078 | if (x1 && ((x1->id.proto != x->id.proto) || |
1094 | xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { | 1079 | xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { |
1095 | to_put = x1; | 1080 | to_put = x1; |
@@ -1098,7 +1083,7 @@ int xfrm_state_add(struct xfrm_state *x) | |||
1098 | } | 1083 | } |
1099 | 1084 | ||
1100 | if (use_spi && !x1) | 1085 | if (use_spi && !x1) |
1101 | x1 = __find_acq_core(family, x->props.mode, x->props.reqid, | 1086 | x1 = __find_acq_core(net, family, x->props.mode, x->props.reqid, |
1102 | x->id.proto, | 1087 | x->id.proto, |
1103 | &x->id.daddr, &x->props.saddr, 0); | 1088 | &x->id.daddr, &x->props.saddr, 0); |
1104 | 1089 | ||
@@ -1124,8 +1109,9 @@ EXPORT_SYMBOL(xfrm_state_add); | |||
1124 | #ifdef CONFIG_XFRM_MIGRATE | 1109 | #ifdef CONFIG_XFRM_MIGRATE |
1125 | static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | 1110 | static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) |
1126 | { | 1111 | { |
1112 | struct net *net = xs_net(orig); | ||
1127 | int err = -ENOMEM; | 1113 | int err = -ENOMEM; |
1128 | struct xfrm_state *x = xfrm_state_alloc(); | 1114 | struct xfrm_state *x = xfrm_state_alloc(net); |
1129 | if (!x) | 1115 | if (!x) |
1130 | goto error; | 1116 | goto error; |
1131 | 1117 | ||
@@ -1206,9 +1192,9 @@ struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m) | |||
1206 | struct hlist_node *entry; | 1192 | struct hlist_node *entry; |
1207 | 1193 | ||
1208 | if (m->reqid) { | 1194 | if (m->reqid) { |
1209 | h = xfrm_dst_hash(&m->old_daddr, &m->old_saddr, | 1195 | h = xfrm_dst_hash(&init_net, &m->old_daddr, &m->old_saddr, |
1210 | m->reqid, m->old_family); | 1196 | m->reqid, m->old_family); |
1211 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 1197 | hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+h, bydst) { |
1212 | if (x->props.mode != m->mode || | 1198 | if (x->props.mode != m->mode || |
1213 | x->id.proto != m->proto) | 1199 | x->id.proto != m->proto) |
1214 | continue; | 1200 | continue; |
@@ -1223,9 +1209,9 @@ struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m) | |||
1223 | return x; | 1209 | return x; |
1224 | } | 1210 | } |
1225 | } else { | 1211 | } else { |
1226 | h = xfrm_src_hash(&m->old_daddr, &m->old_saddr, | 1212 | h = xfrm_src_hash(&init_net, &m->old_daddr, &m->old_saddr, |
1227 | m->old_family); | 1213 | m->old_family); |
1228 | hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) { | 1214 | hlist_for_each_entry(x, entry, init_net.xfrm.state_bysrc+h, bysrc) { |
1229 | if (x->props.mode != m->mode || | 1215 | if (x->props.mode != m->mode || |
1230 | x->id.proto != m->proto) | 1216 | x->id.proto != m->proto) |
1231 | continue; | 1217 | continue; |
@@ -1369,40 +1355,41 @@ int xfrm_state_check_expire(struct xfrm_state *x) | |||
1369 | EXPORT_SYMBOL(xfrm_state_check_expire); | 1355 | EXPORT_SYMBOL(xfrm_state_check_expire); |
1370 | 1356 | ||
1371 | struct xfrm_state * | 1357 | struct xfrm_state * |
1372 | xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, | 1358 | xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, |
1373 | unsigned short family) | 1359 | unsigned short family) |
1374 | { | 1360 | { |
1375 | struct xfrm_state *x; | 1361 | struct xfrm_state *x; |
1376 | 1362 | ||
1377 | spin_lock_bh(&xfrm_state_lock); | 1363 | spin_lock_bh(&xfrm_state_lock); |
1378 | x = __xfrm_state_lookup(daddr, spi, proto, family); | 1364 | x = __xfrm_state_lookup(net, daddr, spi, proto, family); |
1379 | spin_unlock_bh(&xfrm_state_lock); | 1365 | spin_unlock_bh(&xfrm_state_lock); |
1380 | return x; | 1366 | return x; |
1381 | } | 1367 | } |
1382 | EXPORT_SYMBOL(xfrm_state_lookup); | 1368 | EXPORT_SYMBOL(xfrm_state_lookup); |
1383 | 1369 | ||
1384 | struct xfrm_state * | 1370 | struct xfrm_state * |
1385 | xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, | 1371 | xfrm_state_lookup_byaddr(struct net *net, |
1372 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
1386 | u8 proto, unsigned short family) | 1373 | u8 proto, unsigned short family) |
1387 | { | 1374 | { |
1388 | struct xfrm_state *x; | 1375 | struct xfrm_state *x; |
1389 | 1376 | ||
1390 | spin_lock_bh(&xfrm_state_lock); | 1377 | spin_lock_bh(&xfrm_state_lock); |
1391 | x = __xfrm_state_lookup_byaddr(daddr, saddr, proto, family); | 1378 | x = __xfrm_state_lookup_byaddr(net, daddr, saddr, proto, family); |
1392 | spin_unlock_bh(&xfrm_state_lock); | 1379 | spin_unlock_bh(&xfrm_state_lock); |
1393 | return x; | 1380 | return x; |
1394 | } | 1381 | } |
1395 | EXPORT_SYMBOL(xfrm_state_lookup_byaddr); | 1382 | EXPORT_SYMBOL(xfrm_state_lookup_byaddr); |
1396 | 1383 | ||
1397 | struct xfrm_state * | 1384 | struct xfrm_state * |
1398 | xfrm_find_acq(u8 mode, u32 reqid, u8 proto, | 1385 | xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, |
1399 | xfrm_address_t *daddr, xfrm_address_t *saddr, | 1386 | xfrm_address_t *daddr, xfrm_address_t *saddr, |
1400 | int create, unsigned short family) | 1387 | int create, unsigned short family) |
1401 | { | 1388 | { |
1402 | struct xfrm_state *x; | 1389 | struct xfrm_state *x; |
1403 | 1390 | ||
1404 | spin_lock_bh(&xfrm_state_lock); | 1391 | spin_lock_bh(&xfrm_state_lock); |
1405 | x = __find_acq_core(family, mode, reqid, proto, daddr, saddr, create); | 1392 | x = __find_acq_core(net, family, mode, reqid, proto, daddr, saddr, create); |
1406 | spin_unlock_bh(&xfrm_state_lock); | 1393 | spin_unlock_bh(&xfrm_state_lock); |
1407 | 1394 | ||
1408 | return x; | 1395 | return x; |
@@ -1449,15 +1436,15 @@ EXPORT_SYMBOL(xfrm_state_sort); | |||
1449 | 1436 | ||
1450 | /* Silly enough, but I'm lazy to build resolution list */ | 1437 | /* Silly enough, but I'm lazy to build resolution list */ |
1451 | 1438 | ||
1452 | static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) | 1439 | static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq) |
1453 | { | 1440 | { |
1454 | int i; | 1441 | int i; |
1455 | 1442 | ||
1456 | for (i = 0; i <= xfrm_state_hmask; i++) { | 1443 | for (i = 0; i <= net->xfrm.state_hmask; i++) { |
1457 | struct hlist_node *entry; | 1444 | struct hlist_node *entry; |
1458 | struct xfrm_state *x; | 1445 | struct xfrm_state *x; |
1459 | 1446 | ||
1460 | hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) { | 1447 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { |
1461 | if (x->km.seq == seq && | 1448 | if (x->km.seq == seq && |
1462 | x->km.state == XFRM_STATE_ACQ) { | 1449 | x->km.state == XFRM_STATE_ACQ) { |
1463 | xfrm_state_hold(x); | 1450 | xfrm_state_hold(x); |
@@ -1468,12 +1455,12 @@ static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) | |||
1468 | return NULL; | 1455 | return NULL; |
1469 | } | 1456 | } |
1470 | 1457 | ||
1471 | struct xfrm_state *xfrm_find_acq_byseq(u32 seq) | 1458 | struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq) |
1472 | { | 1459 | { |
1473 | struct xfrm_state *x; | 1460 | struct xfrm_state *x; |
1474 | 1461 | ||
1475 | spin_lock_bh(&xfrm_state_lock); | 1462 | spin_lock_bh(&xfrm_state_lock); |
1476 | x = __xfrm_find_acq_byseq(seq); | 1463 | x = __xfrm_find_acq_byseq(net, seq); |
1477 | spin_unlock_bh(&xfrm_state_lock); | 1464 | spin_unlock_bh(&xfrm_state_lock); |
1478 | return x; | 1465 | return x; |
1479 | } | 1466 | } |
@@ -1494,6 +1481,7 @@ EXPORT_SYMBOL(xfrm_get_acqseq); | |||
1494 | 1481 | ||
1495 | int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) | 1482 | int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) |
1496 | { | 1483 | { |
1484 | struct net *net = xs_net(x); | ||
1497 | unsigned int h; | 1485 | unsigned int h; |
1498 | struct xfrm_state *x0; | 1486 | struct xfrm_state *x0; |
1499 | int err = -ENOENT; | 1487 | int err = -ENOENT; |
@@ -1511,7 +1499,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) | |||
1511 | err = -ENOENT; | 1499 | err = -ENOENT; |
1512 | 1500 | ||
1513 | if (minspi == maxspi) { | 1501 | if (minspi == maxspi) { |
1514 | x0 = xfrm_state_lookup(&x->id.daddr, minspi, x->id.proto, x->props.family); | 1502 | x0 = xfrm_state_lookup(net, &x->id.daddr, minspi, x->id.proto, x->props.family); |
1515 | if (x0) { | 1503 | if (x0) { |
1516 | xfrm_state_put(x0); | 1504 | xfrm_state_put(x0); |
1517 | goto unlock; | 1505 | goto unlock; |
@@ -1521,7 +1509,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) | |||
1521 | u32 spi = 0; | 1509 | u32 spi = 0; |
1522 | for (h=0; h<high-low+1; h++) { | 1510 | for (h=0; h<high-low+1; h++) { |
1523 | spi = low + net_random()%(high-low+1); | 1511 | spi = low + net_random()%(high-low+1); |
1524 | x0 = xfrm_state_lookup(&x->id.daddr, htonl(spi), x->id.proto, x->props.family); | 1512 | x0 = xfrm_state_lookup(net, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); |
1525 | if (x0 == NULL) { | 1513 | if (x0 == NULL) { |
1526 | x->id.spi = htonl(spi); | 1514 | x->id.spi = htonl(spi); |
1527 | break; | 1515 | break; |
@@ -1531,8 +1519,8 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) | |||
1531 | } | 1519 | } |
1532 | if (x->id.spi) { | 1520 | if (x->id.spi) { |
1533 | spin_lock_bh(&xfrm_state_lock); | 1521 | spin_lock_bh(&xfrm_state_lock); |
1534 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family); | 1522 | h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family); |
1535 | hlist_add_head(&x->byspi, xfrm_state_byspi+h); | 1523 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); |
1536 | spin_unlock_bh(&xfrm_state_lock); | 1524 | spin_unlock_bh(&xfrm_state_lock); |
1537 | 1525 | ||
1538 | err = 0; | 1526 | err = 0; |
@@ -1545,7 +1533,7 @@ unlock: | |||
1545 | } | 1533 | } |
1546 | EXPORT_SYMBOL(xfrm_alloc_spi); | 1534 | EXPORT_SYMBOL(xfrm_alloc_spi); |
1547 | 1535 | ||
1548 | int xfrm_state_walk(struct xfrm_state_walk *walk, | 1536 | int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, |
1549 | int (*func)(struct xfrm_state *, int, void*), | 1537 | int (*func)(struct xfrm_state *, int, void*), |
1550 | void *data) | 1538 | void *data) |
1551 | { | 1539 | { |
@@ -1558,10 +1546,10 @@ int xfrm_state_walk(struct xfrm_state_walk *walk, | |||
1558 | 1546 | ||
1559 | spin_lock_bh(&xfrm_state_lock); | 1547 | spin_lock_bh(&xfrm_state_lock); |
1560 | if (list_empty(&walk->all)) | 1548 | if (list_empty(&walk->all)) |
1561 | x = list_first_entry(&xfrm_state_all, struct xfrm_state_walk, all); | 1549 | x = list_first_entry(&net->xfrm.state_all, struct xfrm_state_walk, all); |
1562 | else | 1550 | else |
1563 | x = list_entry(&walk->all, struct xfrm_state_walk, all); | 1551 | x = list_entry(&walk->all, struct xfrm_state_walk, all); |
1564 | list_for_each_entry_from(x, &xfrm_state_all, all) { | 1552 | list_for_each_entry_from(x, &net->xfrm.state_all, all) { |
1565 | if (x->state == XFRM_STATE_DEAD) | 1553 | if (x->state == XFRM_STATE_DEAD) |
1566 | continue; | 1554 | continue; |
1567 | state = container_of(x, struct xfrm_state, km); | 1555 | state = container_of(x, struct xfrm_state, km); |
@@ -1660,7 +1648,7 @@ static void xfrm_replay_timer_handler(unsigned long data) | |||
1660 | spin_lock(&x->lock); | 1648 | spin_lock(&x->lock); |
1661 | 1649 | ||
1662 | if (x->km.state == XFRM_STATE_VALID) { | 1650 | if (x->km.state == XFRM_STATE_VALID) { |
1663 | if (xfrm_aevent_is_on()) | 1651 | if (xfrm_aevent_is_on(xs_net(x))) |
1664 | xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT); | 1652 | xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT); |
1665 | else | 1653 | else |
1666 | x->xflags |= XFRM_TIME_DEFER; | 1654 | x->xflags |= XFRM_TIME_DEFER; |
@@ -1716,7 +1704,7 @@ void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq) | |||
1716 | x->replay.bitmap |= (1U << diff); | 1704 | x->replay.bitmap |= (1U << diff); |
1717 | } | 1705 | } |
1718 | 1706 | ||
1719 | if (xfrm_aevent_is_on()) | 1707 | if (xfrm_aevent_is_on(xs_net(x))) |
1720 | xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); | 1708 | xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); |
1721 | } | 1709 | } |
1722 | 1710 | ||
@@ -1749,6 +1737,7 @@ EXPORT_SYMBOL(km_state_notify); | |||
1749 | 1737 | ||
1750 | void km_state_expired(struct xfrm_state *x, int hard, u32 pid) | 1738 | void km_state_expired(struct xfrm_state *x, int hard, u32 pid) |
1751 | { | 1739 | { |
1740 | struct net *net = xs_net(x); | ||
1752 | struct km_event c; | 1741 | struct km_event c; |
1753 | 1742 | ||
1754 | c.data.hard = hard; | 1743 | c.data.hard = hard; |
@@ -1757,7 +1746,7 @@ void km_state_expired(struct xfrm_state *x, int hard, u32 pid) | |||
1757 | km_state_notify(x, &c); | 1746 | km_state_notify(x, &c); |
1758 | 1747 | ||
1759 | if (hard) | 1748 | if (hard) |
1760 | wake_up(&km_waitq); | 1749 | wake_up(&net->xfrm.km_waitq); |
1761 | } | 1750 | } |
1762 | 1751 | ||
1763 | EXPORT_SYMBOL(km_state_expired); | 1752 | EXPORT_SYMBOL(km_state_expired); |
@@ -1800,6 +1789,7 @@ EXPORT_SYMBOL(km_new_mapping); | |||
1800 | 1789 | ||
1801 | void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid) | 1790 | void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid) |
1802 | { | 1791 | { |
1792 | struct net *net = xp_net(pol); | ||
1803 | struct km_event c; | 1793 | struct km_event c; |
1804 | 1794 | ||
1805 | c.data.hard = hard; | 1795 | c.data.hard = hard; |
@@ -1808,7 +1798,7 @@ void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid) | |||
1808 | km_policy_notify(pol, dir, &c); | 1798 | km_policy_notify(pol, dir, &c); |
1809 | 1799 | ||
1810 | if (hard) | 1800 | if (hard) |
1811 | wake_up(&km_waitq); | 1801 | wake_up(&net->xfrm.km_waitq); |
1812 | } | 1802 | } |
1813 | EXPORT_SYMBOL(km_policy_expired); | 1803 | EXPORT_SYMBOL(km_policy_expired); |
1814 | 1804 | ||
@@ -1835,7 +1825,7 @@ int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
1835 | EXPORT_SYMBOL(km_migrate); | 1825 | EXPORT_SYMBOL(km_migrate); |
1836 | #endif | 1826 | #endif |
1837 | 1827 | ||
1838 | int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) | 1828 | int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) |
1839 | { | 1829 | { |
1840 | int err = -EINVAL; | 1830 | int err = -EINVAL; |
1841 | int ret; | 1831 | int ret; |
@@ -1844,7 +1834,7 @@ int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) | |||
1844 | read_lock(&xfrm_km_lock); | 1834 | read_lock(&xfrm_km_lock); |
1845 | list_for_each_entry(km, &xfrm_km_list, list) { | 1835 | list_for_each_entry(km, &xfrm_km_list, list) { |
1846 | if (km->report) { | 1836 | if (km->report) { |
1847 | ret = km->report(proto, sel, addr); | 1837 | ret = km->report(net, proto, sel, addr); |
1848 | if (!ret) | 1838 | if (!ret) |
1849 | err = ret; | 1839 | err = ret; |
1850 | } | 1840 | } |
@@ -2080,20 +2070,61 @@ error: | |||
2080 | 2070 | ||
2081 | EXPORT_SYMBOL(xfrm_init_state); | 2071 | EXPORT_SYMBOL(xfrm_init_state); |
2082 | 2072 | ||
2083 | void __init xfrm_state_init(void) | 2073 | int __net_init xfrm_state_init(struct net *net) |
2084 | { | 2074 | { |
2085 | unsigned int sz; | 2075 | unsigned int sz; |
2086 | 2076 | ||
2077 | INIT_LIST_HEAD(&net->xfrm.state_all); | ||
2078 | |||
2087 | sz = sizeof(struct hlist_head) * 8; | 2079 | sz = sizeof(struct hlist_head) * 8; |
2088 | 2080 | ||
2089 | xfrm_state_bydst = xfrm_hash_alloc(sz); | 2081 | net->xfrm.state_bydst = xfrm_hash_alloc(sz); |
2090 | xfrm_state_bysrc = xfrm_hash_alloc(sz); | 2082 | if (!net->xfrm.state_bydst) |
2091 | xfrm_state_byspi = xfrm_hash_alloc(sz); | 2083 | goto out_bydst; |
2092 | if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi) | 2084 | net->xfrm.state_bysrc = xfrm_hash_alloc(sz); |
2093 | panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes."); | 2085 | if (!net->xfrm.state_bysrc) |
2094 | xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1); | 2086 | goto out_bysrc; |
2087 | net->xfrm.state_byspi = xfrm_hash_alloc(sz); | ||
2088 | if (!net->xfrm.state_byspi) | ||
2089 | goto out_byspi; | ||
2090 | net->xfrm.state_hmask = ((sz / sizeof(struct hlist_head)) - 1); | ||
2091 | |||
2092 | net->xfrm.state_num = 0; | ||
2093 | INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize); | ||
2094 | INIT_HLIST_HEAD(&net->xfrm.state_gc_list); | ||
2095 | INIT_WORK(&net->xfrm.state_gc_work, xfrm_state_gc_task); | ||
2096 | init_waitqueue_head(&net->xfrm.km_waitq); | ||
2097 | return 0; | ||
2095 | 2098 | ||
2096 | INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task); | 2099 | out_byspi: |
2100 | xfrm_hash_free(net->xfrm.state_bysrc, sz); | ||
2101 | out_bysrc: | ||
2102 | xfrm_hash_free(net->xfrm.state_bydst, sz); | ||
2103 | out_bydst: | ||
2104 | return -ENOMEM; | ||
2105 | } | ||
2106 | |||
2107 | void xfrm_state_fini(struct net *net) | ||
2108 | { | ||
2109 | struct xfrm_audit audit_info; | ||
2110 | unsigned int sz; | ||
2111 | |||
2112 | flush_work(&net->xfrm.state_hash_work); | ||
2113 | audit_info.loginuid = -1; | ||
2114 | audit_info.sessionid = -1; | ||
2115 | audit_info.secid = 0; | ||
2116 | xfrm_state_flush(net, IPSEC_PROTO_ANY, &audit_info); | ||
2117 | flush_work(&net->xfrm.state_gc_work); | ||
2118 | |||
2119 | WARN_ON(!list_empty(&net->xfrm.state_all)); | ||
2120 | |||
2121 | sz = (net->xfrm.state_hmask + 1) * sizeof(struct hlist_head); | ||
2122 | WARN_ON(!hlist_empty(net->xfrm.state_byspi)); | ||
2123 | xfrm_hash_free(net->xfrm.state_byspi, sz); | ||
2124 | WARN_ON(!hlist_empty(net->xfrm.state_bysrc)); | ||
2125 | xfrm_hash_free(net->xfrm.state_bysrc, sz); | ||
2126 | WARN_ON(!hlist_empty(net->xfrm.state_bydst)); | ||
2127 | xfrm_hash_free(net->xfrm.state_bydst, sz); | ||
2097 | } | 2128 | } |
2098 | 2129 | ||
2099 | #ifdef CONFIG_AUDITSYSCALL | 2130 | #ifdef CONFIG_AUDITSYSCALL |
@@ -2109,16 +2140,12 @@ static void xfrm_audit_helper_sainfo(struct xfrm_state *x, | |||
2109 | 2140 | ||
2110 | switch(x->props.family) { | 2141 | switch(x->props.family) { |
2111 | case AF_INET: | 2142 | case AF_INET: |
2112 | audit_log_format(audit_buf, | 2143 | audit_log_format(audit_buf, " src=%pI4 dst=%pI4", |
2113 | " src=" NIPQUAD_FMT " dst=" NIPQUAD_FMT, | 2144 | &x->props.saddr.a4, &x->id.daddr.a4); |
2114 | NIPQUAD(x->props.saddr.a4), | ||
2115 | NIPQUAD(x->id.daddr.a4)); | ||
2116 | break; | 2145 | break; |
2117 | case AF_INET6: | 2146 | case AF_INET6: |
2118 | audit_log_format(audit_buf, | 2147 | audit_log_format(audit_buf, " src=%pI6 dst=%pI6", |
2119 | " src=" NIP6_FMT " dst=" NIP6_FMT, | 2148 | x->props.saddr.a6, x->id.daddr.a6); |
2120 | NIP6(*(struct in6_addr *)x->props.saddr.a6), | ||
2121 | NIP6(*(struct in6_addr *)x->id.daddr.a6)); | ||
2122 | break; | 2149 | break; |
2123 | } | 2150 | } |
2124 | 2151 | ||
@@ -2134,18 +2161,14 @@ static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family, | |||
2134 | switch (family) { | 2161 | switch (family) { |
2135 | case AF_INET: | 2162 | case AF_INET: |
2136 | iph4 = ip_hdr(skb); | 2163 | iph4 = ip_hdr(skb); |
2137 | audit_log_format(audit_buf, | 2164 | audit_log_format(audit_buf, " src=%pI4 dst=%pI4", |
2138 | " src=" NIPQUAD_FMT " dst=" NIPQUAD_FMT, | 2165 | &iph4->saddr, &iph4->daddr); |
2139 | NIPQUAD(iph4->saddr), | ||
2140 | NIPQUAD(iph4->daddr)); | ||
2141 | break; | 2166 | break; |
2142 | case AF_INET6: | 2167 | case AF_INET6: |
2143 | iph6 = ipv6_hdr(skb); | 2168 | iph6 = ipv6_hdr(skb); |
2144 | audit_log_format(audit_buf, | 2169 | audit_log_format(audit_buf, |
2145 | " src=" NIP6_FMT " dst=" NIP6_FMT | 2170 | " src=%pI6 dst=%pI6 flowlbl=0x%x%02x%02x", |
2146 | " flowlbl=0x%x%02x%02x", | 2171 | &iph6->saddr,&iph6->daddr, |
2147 | NIP6(iph6->saddr), | ||
2148 | NIP6(iph6->daddr), | ||
2149 | iph6->flow_lbl[0] & 0x0f, | 2172 | iph6->flow_lbl[0] & 0x0f, |
2150 | iph6->flow_lbl[1], | 2173 | iph6->flow_lbl[1], |
2151 | iph6->flow_lbl[2]); | 2174 | iph6->flow_lbl[2]); |