aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
authorJames Bottomley <jejb@sparkweed.localdomain>2006-09-23 22:03:52 -0400
committerJames Bottomley <jejb@sparkweed.localdomain>2006-09-23 22:03:52 -0400
commit1aedf2ccc60fade26c46fae12e28664d0da3f199 (patch)
treed91083e3079f1ddb942a382ac2b5a7525570ad59 /net/xfrm/xfrm_state.c
parentdfdc58ba354adb80d67c99f7be84f95a8e02e466 (diff)
parent1ab9dd0902df4f4ff56fbf672220549090ab28ba (diff)
Merge mulgrave-w:git/linux-2.6
Conflicts: include/linux/blkdev.h Trivial merge to incorporate tag prototypes.
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c640
1 files changed, 491 insertions, 149 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 0021aad5db43..9f63edd39346 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -18,8 +18,11 @@
18#include <linux/pfkeyv2.h> 18#include <linux/pfkeyv2.h>
19#include <linux/ipsec.h> 19#include <linux/ipsec.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/cache.h>
21#include <asm/uaccess.h> 22#include <asm/uaccess.h>
22 23
24#include "xfrm_hash.h"
25
23struct sock *xfrm_nl; 26struct sock *xfrm_nl;
24EXPORT_SYMBOL(xfrm_nl); 27EXPORT_SYMBOL(xfrm_nl);
25 28
@@ -32,7 +35,7 @@ EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);
32/* Each xfrm_state may be linked to two tables: 35/* Each xfrm_state may be linked to two tables:
33 36
34 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl) 37 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
35 2. Hash table by daddr to find what SAs exist for given 38 2. Hash table by (daddr,family,reqid) to find what SAs exist for given
36 destination/tunnel endpoint. (output) 39 destination/tunnel endpoint. (output)
37 */ 40 */
38 41
@@ -44,8 +47,123 @@ static DEFINE_SPINLOCK(xfrm_state_lock);
44 * Main use is finding SA after policy selected tunnel or transport mode. 47 * Main use is finding SA after policy selected tunnel or transport mode.
45 * Also, it can be used by ah/esp icmp error handler to find offending SA. 48 * Also, it can be used by ah/esp icmp error handler to find offending SA.
46 */ 49 */
47static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE]; 50static struct hlist_head *xfrm_state_bydst __read_mostly;
48static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; 51static struct hlist_head *xfrm_state_bysrc __read_mostly;
52static struct hlist_head *xfrm_state_byspi __read_mostly;
53static unsigned int xfrm_state_hmask __read_mostly;
54static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
55static unsigned int xfrm_state_num;
56static unsigned int xfrm_state_genid;
57
58static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
59 xfrm_address_t *saddr,
60 u32 reqid,
61 unsigned short family)
62{
63 return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask);
64}
65
66static inline unsigned int xfrm_src_hash(xfrm_address_t *addr,
67 unsigned short family)
68{
69 return __xfrm_src_hash(addr, family, xfrm_state_hmask);
70}
71
72static inline unsigned int
73xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family)
74{
75 return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask);
76}
77
78static void xfrm_hash_transfer(struct hlist_head *list,
79 struct hlist_head *ndsttable,
80 struct hlist_head *nsrctable,
81 struct hlist_head *nspitable,
82 unsigned int nhashmask)
83{
84 struct hlist_node *entry, *tmp;
85 struct xfrm_state *x;
86
87 hlist_for_each_entry_safe(x, entry, tmp, list, bydst) {
88 unsigned int h;
89
90 h = __xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
91 x->props.reqid, x->props.family,
92 nhashmask);
93 hlist_add_head(&x->bydst, ndsttable+h);
94
95 h = __xfrm_src_hash(&x->props.saddr, x->props.family,
96 nhashmask);
97 hlist_add_head(&x->bysrc, nsrctable+h);
98
99 h = __xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto,
100 x->props.family, nhashmask);
101 hlist_add_head(&x->byspi, nspitable+h);
102 }
103}
104
105static unsigned long xfrm_hash_new_size(void)
106{
107 return ((xfrm_state_hmask + 1) << 1) *
108 sizeof(struct hlist_head);
109}
110
111static DEFINE_MUTEX(hash_resize_mutex);
112
113static void xfrm_hash_resize(void *__unused)
114{
115 struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi;
116 unsigned long nsize, osize;
117 unsigned int nhashmask, ohashmask;
118 int i;
119
120 mutex_lock(&hash_resize_mutex);
121
122 nsize = xfrm_hash_new_size();
123 ndst = xfrm_hash_alloc(nsize);
124 if (!ndst)
125 goto out_unlock;
126 nsrc = xfrm_hash_alloc(nsize);
127 if (!nsrc) {
128 xfrm_hash_free(ndst, nsize);
129 goto out_unlock;
130 }
131 nspi = xfrm_hash_alloc(nsize);
132 if (!nspi) {
133 xfrm_hash_free(ndst, nsize);
134 xfrm_hash_free(nsrc, nsize);
135 goto out_unlock;
136 }
137
138 spin_lock_bh(&xfrm_state_lock);
139
140 nhashmask = (nsize / sizeof(struct hlist_head)) - 1U;
141 for (i = xfrm_state_hmask; i >= 0; i--)
142 xfrm_hash_transfer(xfrm_state_bydst+i, ndst, nsrc, nspi,
143 nhashmask);
144
145 odst = xfrm_state_bydst;
146 osrc = xfrm_state_bysrc;
147 ospi = xfrm_state_byspi;
148 ohashmask = xfrm_state_hmask;
149
150 xfrm_state_bydst = ndst;
151 xfrm_state_bysrc = nsrc;
152 xfrm_state_byspi = nspi;
153 xfrm_state_hmask = nhashmask;
154
155 spin_unlock_bh(&xfrm_state_lock);
156
157 osize = (ohashmask + 1) * sizeof(struct hlist_head);
158 xfrm_hash_free(odst, osize);
159 xfrm_hash_free(osrc, osize);
160 xfrm_hash_free(ospi, osize);
161
162out_unlock:
163 mutex_unlock(&hash_resize_mutex);
164}
165
166static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL);
49 167
50DECLARE_WAIT_QUEUE_HEAD(km_waitq); 168DECLARE_WAIT_QUEUE_HEAD(km_waitq);
51EXPORT_SYMBOL(km_waitq); 169EXPORT_SYMBOL(km_waitq);
@@ -54,11 +172,9 @@ static DEFINE_RWLOCK(xfrm_state_afinfo_lock);
54static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; 172static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
55 173
56static struct work_struct xfrm_state_gc_work; 174static struct work_struct xfrm_state_gc_work;
57static struct list_head xfrm_state_gc_list = LIST_HEAD_INIT(xfrm_state_gc_list); 175static HLIST_HEAD(xfrm_state_gc_list);
58static DEFINE_SPINLOCK(xfrm_state_gc_lock); 176static DEFINE_SPINLOCK(xfrm_state_gc_lock);
59 177
60static int xfrm_state_gc_flush_bundles;
61
62int __xfrm_state_delete(struct xfrm_state *x); 178int __xfrm_state_delete(struct xfrm_state *x);
63 179
64static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); 180static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
@@ -69,14 +185,13 @@ void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
69 185
70static void xfrm_state_gc_destroy(struct xfrm_state *x) 186static void xfrm_state_gc_destroy(struct xfrm_state *x)
71{ 187{
72 if (del_timer(&x->timer)) 188 del_timer_sync(&x->timer);
73 BUG(); 189 del_timer_sync(&x->rtimer);
74 if (del_timer(&x->rtimer))
75 BUG();
76 kfree(x->aalg); 190 kfree(x->aalg);
77 kfree(x->ealg); 191 kfree(x->ealg);
78 kfree(x->calg); 192 kfree(x->calg);
79 kfree(x->encap); 193 kfree(x->encap);
194 kfree(x->coaddr);
80 if (x->mode) 195 if (x->mode)
81 xfrm_put_mode(x->mode); 196 xfrm_put_mode(x->mode);
82 if (x->type) { 197 if (x->type) {
@@ -90,22 +205,17 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
90static void xfrm_state_gc_task(void *data) 205static void xfrm_state_gc_task(void *data)
91{ 206{
92 struct xfrm_state *x; 207 struct xfrm_state *x;
93 struct list_head *entry, *tmp; 208 struct hlist_node *entry, *tmp;
94 struct list_head gc_list = LIST_HEAD_INIT(gc_list); 209 struct hlist_head gc_list;
95
96 if (xfrm_state_gc_flush_bundles) {
97 xfrm_state_gc_flush_bundles = 0;
98 xfrm_flush_bundles();
99 }
100 210
101 spin_lock_bh(&xfrm_state_gc_lock); 211 spin_lock_bh(&xfrm_state_gc_lock);
102 list_splice_init(&xfrm_state_gc_list, &gc_list); 212 gc_list.first = xfrm_state_gc_list.first;
213 INIT_HLIST_HEAD(&xfrm_state_gc_list);
103 spin_unlock_bh(&xfrm_state_gc_lock); 214 spin_unlock_bh(&xfrm_state_gc_lock);
104 215
105 list_for_each_safe(entry, tmp, &gc_list) { 216 hlist_for_each_entry_safe(x, entry, tmp, &gc_list, bydst)
106 x = list_entry(entry, struct xfrm_state, bydst);
107 xfrm_state_gc_destroy(x); 217 xfrm_state_gc_destroy(x);
108 } 218
109 wake_up(&km_waitq); 219 wake_up(&km_waitq);
110} 220}
111 221
@@ -168,9 +278,9 @@ static void xfrm_timer_handler(unsigned long data)
168 if (warn) 278 if (warn)
169 km_state_expired(x, 0, 0); 279 km_state_expired(x, 0, 0);
170resched: 280resched:
171 if (next != LONG_MAX && 281 if (next != LONG_MAX)
172 !mod_timer(&x->timer, jiffies + make_jiffies(next))) 282 mod_timer(&x->timer, jiffies + make_jiffies(next));
173 xfrm_state_hold(x); 283
174 goto out; 284 goto out;
175 285
176expired: 286expired:
@@ -185,7 +295,6 @@ expired:
185 295
186out: 296out:
187 spin_unlock(&x->lock); 297 spin_unlock(&x->lock);
188 xfrm_state_put(x);
189} 298}
190 299
191static void xfrm_replay_timer_handler(unsigned long data); 300static void xfrm_replay_timer_handler(unsigned long data);
@@ -199,8 +308,9 @@ struct xfrm_state *xfrm_state_alloc(void)
199 if (x) { 308 if (x) {
200 atomic_set(&x->refcnt, 1); 309 atomic_set(&x->refcnt, 1);
201 atomic_set(&x->tunnel_users, 0); 310 atomic_set(&x->tunnel_users, 0);
202 INIT_LIST_HEAD(&x->bydst); 311 INIT_HLIST_NODE(&x->bydst);
203 INIT_LIST_HEAD(&x->byspi); 312 INIT_HLIST_NODE(&x->bysrc);
313 INIT_HLIST_NODE(&x->byspi);
204 init_timer(&x->timer); 314 init_timer(&x->timer);
205 x->timer.function = xfrm_timer_handler; 315 x->timer.function = xfrm_timer_handler;
206 x->timer.data = (unsigned long)x; 316 x->timer.data = (unsigned long)x;
@@ -225,7 +335,7 @@ void __xfrm_state_destroy(struct xfrm_state *x)
225 BUG_TRAP(x->km.state == XFRM_STATE_DEAD); 335 BUG_TRAP(x->km.state == XFRM_STATE_DEAD);
226 336
227 spin_lock_bh(&xfrm_state_gc_lock); 337 spin_lock_bh(&xfrm_state_gc_lock);
228 list_add(&x->bydst, &xfrm_state_gc_list); 338 hlist_add_head(&x->bydst, &xfrm_state_gc_list);
229 spin_unlock_bh(&xfrm_state_gc_lock); 339 spin_unlock_bh(&xfrm_state_gc_lock);
230 schedule_work(&xfrm_state_gc_work); 340 schedule_work(&xfrm_state_gc_work);
231} 341}
@@ -238,27 +348,12 @@ int __xfrm_state_delete(struct xfrm_state *x)
238 if (x->km.state != XFRM_STATE_DEAD) { 348 if (x->km.state != XFRM_STATE_DEAD) {
239 x->km.state = XFRM_STATE_DEAD; 349 x->km.state = XFRM_STATE_DEAD;
240 spin_lock(&xfrm_state_lock); 350 spin_lock(&xfrm_state_lock);
241 list_del(&x->bydst); 351 hlist_del(&x->bydst);
242 __xfrm_state_put(x); 352 hlist_del(&x->bysrc);
243 if (x->id.spi) { 353 if (x->id.spi)
244 list_del(&x->byspi); 354 hlist_del(&x->byspi);
245 __xfrm_state_put(x); 355 xfrm_state_num--;
246 }
247 spin_unlock(&xfrm_state_lock); 356 spin_unlock(&xfrm_state_lock);
248 if (del_timer(&x->timer))
249 __xfrm_state_put(x);
250 if (del_timer(&x->rtimer))
251 __xfrm_state_put(x);
252
253 /* The number two in this test is the reference
254 * mentioned in the comment below plus the reference
255 * our caller holds. A larger value means that
256 * there are DSTs attached to this xfrm_state.
257 */
258 if (atomic_read(&x->refcnt) > 2) {
259 xfrm_state_gc_flush_bundles = 1;
260 schedule_work(&xfrm_state_gc_work);
261 }
262 357
263 /* All xfrm_state objects are created by xfrm_state_alloc. 358 /* All xfrm_state objects are created by xfrm_state_alloc.
264 * The xfrm_state_alloc call gives a reference, and that 359 * The xfrm_state_alloc call gives a reference, and that
@@ -287,14 +382,15 @@ EXPORT_SYMBOL(xfrm_state_delete);
287void xfrm_state_flush(u8 proto) 382void xfrm_state_flush(u8 proto)
288{ 383{
289 int i; 384 int i;
290 struct xfrm_state *x;
291 385
292 spin_lock_bh(&xfrm_state_lock); 386 spin_lock_bh(&xfrm_state_lock);
293 for (i = 0; i < XFRM_DST_HSIZE; i++) { 387 for (i = 0; i <= xfrm_state_hmask; i++) {
388 struct hlist_node *entry;
389 struct xfrm_state *x;
294restart: 390restart:
295 list_for_each_entry(x, xfrm_state_bydst+i, bydst) { 391 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
296 if (!xfrm_state_kern(x) && 392 if (!xfrm_state_kern(x) &&
297 (proto == IPSEC_PROTO_ANY || x->id.proto == proto)) { 393 xfrm_id_proto_match(x->id.proto, proto)) {
298 xfrm_state_hold(x); 394 xfrm_state_hold(x);
299 spin_unlock_bh(&xfrm_state_lock); 395 spin_unlock_bh(&xfrm_state_lock);
300 396
@@ -325,29 +421,103 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
325 return 0; 421 return 0;
326} 422}
327 423
424static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family)
425{
426 unsigned int h = xfrm_spi_hash(daddr, spi, proto, family);
427 struct xfrm_state *x;
428 struct hlist_node *entry;
429
430 hlist_for_each_entry(x, entry, xfrm_state_byspi+h, byspi) {
431 if (x->props.family != family ||
432 x->id.spi != spi ||
433 x->id.proto != proto)
434 continue;
435
436 switch (family) {
437 case AF_INET:
438 if (x->id.daddr.a4 != daddr->a4)
439 continue;
440 break;
441 case AF_INET6:
442 if (!ipv6_addr_equal((struct in6_addr *)daddr,
443 (struct in6_addr *)
444 x->id.daddr.a6))
445 continue;
446 break;
447 };
448
449 xfrm_state_hold(x);
450 return x;
451 }
452
453 return NULL;
454}
455
456static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family)
457{
458 unsigned int h = xfrm_src_hash(saddr, family);
459 struct xfrm_state *x;
460 struct hlist_node *entry;
461
462 hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) {
463 if (x->props.family != family ||
464 x->id.proto != proto)
465 continue;
466
467 switch (family) {
468 case AF_INET:
469 if (x->id.daddr.a4 != daddr->a4 ||
470 x->props.saddr.a4 != saddr->a4)
471 continue;
472 break;
473 case AF_INET6:
474 if (!ipv6_addr_equal((struct in6_addr *)daddr,
475 (struct in6_addr *)
476 x->id.daddr.a6) ||
477 !ipv6_addr_equal((struct in6_addr *)saddr,
478 (struct in6_addr *)
479 x->props.saddr.a6))
480 continue;
481 break;
482 };
483
484 xfrm_state_hold(x);
485 return x;
486 }
487
488 return NULL;
489}
490
491static inline struct xfrm_state *
492__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
493{
494 if (use_spi)
495 return __xfrm_state_lookup(&x->id.daddr, x->id.spi,
496 x->id.proto, family);
497 else
498 return __xfrm_state_lookup_byaddr(&x->id.daddr,
499 &x->props.saddr,
500 x->id.proto, family);
501}
502
328struct xfrm_state * 503struct xfrm_state *
329xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, 504xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
330 struct flowi *fl, struct xfrm_tmpl *tmpl, 505 struct flowi *fl, struct xfrm_tmpl *tmpl,
331 struct xfrm_policy *pol, int *err, 506 struct xfrm_policy *pol, int *err,
332 unsigned short family) 507 unsigned short family)
333{ 508{
334 unsigned h = xfrm_dst_hash(daddr, family); 509 unsigned int h = xfrm_dst_hash(daddr, saddr, tmpl->reqid, family);
510 struct hlist_node *entry;
335 struct xfrm_state *x, *x0; 511 struct xfrm_state *x, *x0;
336 int acquire_in_progress = 0; 512 int acquire_in_progress = 0;
337 int error = 0; 513 int error = 0;
338 struct xfrm_state *best = NULL; 514 struct xfrm_state *best = NULL;
339 struct xfrm_state_afinfo *afinfo;
340 515
341 afinfo = xfrm_state_get_afinfo(family);
342 if (afinfo == NULL) {
343 *err = -EAFNOSUPPORT;
344 return NULL;
345 }
346
347 spin_lock_bh(&xfrm_state_lock); 516 spin_lock_bh(&xfrm_state_lock);
348 list_for_each_entry(x, xfrm_state_bydst+h, bydst) { 517 hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
349 if (x->props.family == family && 518 if (x->props.family == family &&
350 x->props.reqid == tmpl->reqid && 519 x->props.reqid == tmpl->reqid &&
520 !(x->props.flags & XFRM_STATE_WILDRECV) &&
351 xfrm_state_addr_check(x, daddr, saddr, family) && 521 xfrm_state_addr_check(x, daddr, saddr, family) &&
352 tmpl->mode == x->props.mode && 522 tmpl->mode == x->props.mode &&
353 tmpl->id.proto == x->id.proto && 523 tmpl->id.proto == x->id.proto &&
@@ -367,7 +537,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
367 */ 537 */
368 if (x->km.state == XFRM_STATE_VALID) { 538 if (x->km.state == XFRM_STATE_VALID) {
369 if (!xfrm_selector_match(&x->sel, fl, family) || 539 if (!xfrm_selector_match(&x->sel, fl, family) ||
370 !xfrm_sec_ctx_match(pol->security, x->security)) 540 !security_xfrm_state_pol_flow_match(x, pol, fl))
371 continue; 541 continue;
372 if (!best || 542 if (!best ||
373 best->km.dying > x->km.dying || 543 best->km.dying > x->km.dying ||
@@ -379,7 +549,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
379 } else if (x->km.state == XFRM_STATE_ERROR || 549 } else if (x->km.state == XFRM_STATE_ERROR ||
380 x->km.state == XFRM_STATE_EXPIRED) { 550 x->km.state == XFRM_STATE_EXPIRED) {
381 if (xfrm_selector_match(&x->sel, fl, family) && 551 if (xfrm_selector_match(&x->sel, fl, family) &&
382 xfrm_sec_ctx_match(pol->security, x->security)) 552 security_xfrm_state_pol_flow_match(x, pol, fl))
383 error = -ESRCH; 553 error = -ESRCH;
384 } 554 }
385 } 555 }
@@ -388,8 +558,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
388 x = best; 558 x = best;
389 if (!x && !error && !acquire_in_progress) { 559 if (!x && !error && !acquire_in_progress) {
390 if (tmpl->id.spi && 560 if (tmpl->id.spi &&
391 (x0 = afinfo->state_lookup(daddr, tmpl->id.spi, 561 (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi,
392 tmpl->id.proto)) != NULL) { 562 tmpl->id.proto, family)) != NULL) {
393 xfrm_state_put(x0); 563 xfrm_state_put(x0);
394 error = -EEXIST; 564 error = -EEXIST;
395 goto out; 565 goto out;
@@ -403,17 +573,24 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
403 * to current session. */ 573 * to current session. */
404 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); 574 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
405 575
576 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
577 if (error) {
578 x->km.state = XFRM_STATE_DEAD;
579 xfrm_state_put(x);
580 x = NULL;
581 goto out;
582 }
583
406 if (km_query(x, tmpl, pol) == 0) { 584 if (km_query(x, tmpl, pol) == 0) {
407 x->km.state = XFRM_STATE_ACQ; 585 x->km.state = XFRM_STATE_ACQ;
408 list_add_tail(&x->bydst, xfrm_state_bydst+h); 586 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
409 xfrm_state_hold(x); 587 h = xfrm_src_hash(saddr, family);
588 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
410 if (x->id.spi) { 589 if (x->id.spi) {
411 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); 590 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family);
412 list_add(&x->byspi, xfrm_state_byspi+h); 591 hlist_add_head(&x->byspi, xfrm_state_byspi+h);
413 xfrm_state_hold(x);
414 } 592 }
415 x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES; 593 x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
416 xfrm_state_hold(x);
417 x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; 594 x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
418 add_timer(&x->timer); 595 add_timer(&x->timer);
419 } else { 596 } else {
@@ -429,59 +606,167 @@ out:
429 else 606 else
430 *err = acquire_in_progress ? -EAGAIN : error; 607 *err = acquire_in_progress ? -EAGAIN : error;
431 spin_unlock_bh(&xfrm_state_lock); 608 spin_unlock_bh(&xfrm_state_lock);
432 xfrm_state_put_afinfo(afinfo);
433 return x; 609 return x;
434} 610}
435 611
436static void __xfrm_state_insert(struct xfrm_state *x) 612static void __xfrm_state_insert(struct xfrm_state *x)
437{ 613{
438 unsigned h = xfrm_dst_hash(&x->id.daddr, x->props.family); 614 unsigned int h;
439 615
440 list_add(&x->bydst, xfrm_state_bydst+h); 616 x->genid = ++xfrm_state_genid;
441 xfrm_state_hold(x);
442 617
443 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family); 618 h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
619 x->props.reqid, x->props.family);
620 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
444 621
445 list_add(&x->byspi, xfrm_state_byspi+h); 622 h = xfrm_src_hash(&x->props.saddr, x->props.family);
446 xfrm_state_hold(x); 623 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
447 624
448 if (!mod_timer(&x->timer, jiffies + HZ)) 625 if (xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY)) {
449 xfrm_state_hold(x); 626 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto,
627 x->props.family);
450 628
451 if (x->replay_maxage && 629 hlist_add_head(&x->byspi, xfrm_state_byspi+h);
452 !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) 630 }
453 xfrm_state_hold(x); 631
632 mod_timer(&x->timer, jiffies + HZ);
633 if (x->replay_maxage)
634 mod_timer(&x->rtimer, jiffies + x->replay_maxage);
454 635
455 wake_up(&km_waitq); 636 wake_up(&km_waitq);
637
638 xfrm_state_num++;
639
640 if (x->bydst.next != NULL &&
641 (xfrm_state_hmask + 1) < xfrm_state_hashmax &&
642 xfrm_state_num > xfrm_state_hmask)
643 schedule_work(&xfrm_hash_work);
644}
645
646/* xfrm_state_lock is held */
647static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
648{
649 unsigned short family = xnew->props.family;
650 u32 reqid = xnew->props.reqid;
651 struct xfrm_state *x;
652 struct hlist_node *entry;
653 unsigned int h;
654
655 h = xfrm_dst_hash(&xnew->id.daddr, &xnew->props.saddr, reqid, family);
656 hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
657 if (x->props.family == family &&
658 x->props.reqid == reqid &&
659 !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) &&
660 !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family))
661 x->genid = xfrm_state_genid;
662 }
456} 663}
457 664
458void xfrm_state_insert(struct xfrm_state *x) 665void xfrm_state_insert(struct xfrm_state *x)
459{ 666{
460 spin_lock_bh(&xfrm_state_lock); 667 spin_lock_bh(&xfrm_state_lock);
668 __xfrm_state_bump_genids(x);
461 __xfrm_state_insert(x); 669 __xfrm_state_insert(x);
462 spin_unlock_bh(&xfrm_state_lock); 670 spin_unlock_bh(&xfrm_state_lock);
463
464 xfrm_flush_all_bundles();
465} 671}
466EXPORT_SYMBOL(xfrm_state_insert); 672EXPORT_SYMBOL(xfrm_state_insert);
467 673
674/* xfrm_state_lock is held */
675static 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)
676{
677 unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family);
678 struct hlist_node *entry;
679 struct xfrm_state *x;
680
681 hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
682 if (x->props.reqid != reqid ||
683 x->props.mode != mode ||
684 x->props.family != family ||
685 x->km.state != XFRM_STATE_ACQ ||
686 x->id.spi != 0)
687 continue;
688
689 switch (family) {
690 case AF_INET:
691 if (x->id.daddr.a4 != daddr->a4 ||
692 x->props.saddr.a4 != saddr->a4)
693 continue;
694 break;
695 case AF_INET6:
696 if (!ipv6_addr_equal((struct in6_addr *)x->id.daddr.a6,
697 (struct in6_addr *)daddr) ||
698 !ipv6_addr_equal((struct in6_addr *)
699 x->props.saddr.a6,
700 (struct in6_addr *)saddr))
701 continue;
702 break;
703 };
704
705 xfrm_state_hold(x);
706 return x;
707 }
708
709 if (!create)
710 return NULL;
711
712 x = xfrm_state_alloc();
713 if (likely(x)) {
714 switch (family) {
715 case AF_INET:
716 x->sel.daddr.a4 = daddr->a4;
717 x->sel.saddr.a4 = saddr->a4;
718 x->sel.prefixlen_d = 32;
719 x->sel.prefixlen_s = 32;
720 x->props.saddr.a4 = saddr->a4;
721 x->id.daddr.a4 = daddr->a4;
722 break;
723
724 case AF_INET6:
725 ipv6_addr_copy((struct in6_addr *)x->sel.daddr.a6,
726 (struct in6_addr *)daddr);
727 ipv6_addr_copy((struct in6_addr *)x->sel.saddr.a6,
728 (struct in6_addr *)saddr);
729 x->sel.prefixlen_d = 128;
730 x->sel.prefixlen_s = 128;
731 ipv6_addr_copy((struct in6_addr *)x->props.saddr.a6,
732 (struct in6_addr *)saddr);
733 ipv6_addr_copy((struct in6_addr *)x->id.daddr.a6,
734 (struct in6_addr *)daddr);
735 break;
736 };
737
738 x->km.state = XFRM_STATE_ACQ;
739 x->id.proto = proto;
740 x->props.family = family;
741 x->props.mode = mode;
742 x->props.reqid = reqid;
743 x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
744 xfrm_state_hold(x);
745 x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
746 add_timer(&x->timer);
747 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
748 h = xfrm_src_hash(saddr, family);
749 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
750 wake_up(&km_waitq);
751 }
752
753 return x;
754}
755
468static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); 756static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq);
469 757
470int xfrm_state_add(struct xfrm_state *x) 758int xfrm_state_add(struct xfrm_state *x)
471{ 759{
472 struct xfrm_state_afinfo *afinfo;
473 struct xfrm_state *x1; 760 struct xfrm_state *x1;
474 int family; 761 int family;
475 int err; 762 int err;
763 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
476 764
477 family = x->props.family; 765 family = x->props.family;
478 afinfo = xfrm_state_get_afinfo(family);
479 if (unlikely(afinfo == NULL))
480 return -EAFNOSUPPORT;
481 766
482 spin_lock_bh(&xfrm_state_lock); 767 spin_lock_bh(&xfrm_state_lock);
483 768
484 x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto); 769 x1 = __xfrm_state_locate(x, use_spi, family);
485 if (x1) { 770 if (x1) {
486 xfrm_state_put(x1); 771 xfrm_state_put(x1);
487 x1 = NULL; 772 x1 = NULL;
@@ -489,7 +774,7 @@ int xfrm_state_add(struct xfrm_state *x)
489 goto out; 774 goto out;
490 } 775 }
491 776
492 if (x->km.seq) { 777 if (use_spi && x->km.seq) {
493 x1 = __xfrm_find_acq_byseq(x->km.seq); 778 x1 = __xfrm_find_acq_byseq(x->km.seq);
494 if (x1 && xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family)) { 779 if (x1 && xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family)) {
495 xfrm_state_put(x1); 780 xfrm_state_put(x1);
@@ -497,20 +782,17 @@ int xfrm_state_add(struct xfrm_state *x)
497 } 782 }
498 } 783 }
499 784
500 if (!x1) 785 if (use_spi && !x1)
501 x1 = afinfo->find_acq( 786 x1 = __find_acq_core(family, x->props.mode, x->props.reqid,
502 x->props.mode, x->props.reqid, x->id.proto, 787 x->id.proto,
503 &x->id.daddr, &x->props.saddr, 0); 788 &x->id.daddr, &x->props.saddr, 0);
504 789
790 __xfrm_state_bump_genids(x);
505 __xfrm_state_insert(x); 791 __xfrm_state_insert(x);
506 err = 0; 792 err = 0;
507 793
508out: 794out:
509 spin_unlock_bh(&xfrm_state_lock); 795 spin_unlock_bh(&xfrm_state_lock);
510 xfrm_state_put_afinfo(afinfo);
511
512 if (!err)
513 xfrm_flush_all_bundles();
514 796
515 if (x1) { 797 if (x1) {
516 xfrm_state_delete(x1); 798 xfrm_state_delete(x1);
@@ -523,16 +805,12 @@ EXPORT_SYMBOL(xfrm_state_add);
523 805
524int xfrm_state_update(struct xfrm_state *x) 806int xfrm_state_update(struct xfrm_state *x)
525{ 807{
526 struct xfrm_state_afinfo *afinfo;
527 struct xfrm_state *x1; 808 struct xfrm_state *x1;
528 int err; 809 int err;
529 810 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
530 afinfo = xfrm_state_get_afinfo(x->props.family);
531 if (unlikely(afinfo == NULL))
532 return -EAFNOSUPPORT;
533 811
534 spin_lock_bh(&xfrm_state_lock); 812 spin_lock_bh(&xfrm_state_lock);
535 x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto); 813 x1 = __xfrm_state_locate(x, use_spi, x->props.family);
536 814
537 err = -ESRCH; 815 err = -ESRCH;
538 if (!x1) 816 if (!x1)
@@ -552,7 +830,6 @@ int xfrm_state_update(struct xfrm_state *x)
552 830
553out: 831out:
554 spin_unlock_bh(&xfrm_state_lock); 832 spin_unlock_bh(&xfrm_state_lock);
555 xfrm_state_put_afinfo(afinfo);
556 833
557 if (err) 834 if (err)
558 return err; 835 return err;
@@ -568,11 +845,15 @@ out:
568 if (likely(x1->km.state == XFRM_STATE_VALID)) { 845 if (likely(x1->km.state == XFRM_STATE_VALID)) {
569 if (x->encap && x1->encap) 846 if (x->encap && x1->encap)
570 memcpy(x1->encap, x->encap, sizeof(*x1->encap)); 847 memcpy(x1->encap, x->encap, sizeof(*x1->encap));
848 if (x->coaddr && x1->coaddr) {
849 memcpy(x1->coaddr, x->coaddr, sizeof(*x1->coaddr));
850 }
851 if (!use_spi && memcmp(&x1->sel, &x->sel, sizeof(x1->sel)))
852 memcpy(&x1->sel, &x->sel, sizeof(x1->sel));
571 memcpy(&x1->lft, &x->lft, sizeof(x1->lft)); 853 memcpy(&x1->lft, &x->lft, sizeof(x1->lft));
572 x1->km.dying = 0; 854 x1->km.dying = 0;
573 855
574 if (!mod_timer(&x1->timer, jiffies + HZ)) 856 mod_timer(&x1->timer, jiffies + HZ);
575 xfrm_state_hold(x1);
576 if (x1->curlft.use_time) 857 if (x1->curlft.use_time)
577 xfrm_state_check_expire(x1); 858 xfrm_state_check_expire(x1);
578 859
@@ -597,8 +878,7 @@ int xfrm_state_check_expire(struct xfrm_state *x)
597 if (x->curlft.bytes >= x->lft.hard_byte_limit || 878 if (x->curlft.bytes >= x->lft.hard_byte_limit ||
598 x->curlft.packets >= x->lft.hard_packet_limit) { 879 x->curlft.packets >= x->lft.hard_packet_limit) {
599 x->km.state = XFRM_STATE_EXPIRED; 880 x->km.state = XFRM_STATE_EXPIRED;
600 if (!mod_timer(&x->timer, jiffies)) 881 mod_timer(&x->timer, jiffies);
601 xfrm_state_hold(x);
602 return -EINVAL; 882 return -EINVAL;
603 } 883 }
604 884
@@ -640,46 +920,93 @@ xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,
640 unsigned short family) 920 unsigned short family)
641{ 921{
642 struct xfrm_state *x; 922 struct xfrm_state *x;
643 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
644 if (!afinfo)
645 return NULL;
646 923
647 spin_lock_bh(&xfrm_state_lock); 924 spin_lock_bh(&xfrm_state_lock);
648 x = afinfo->state_lookup(daddr, spi, proto); 925 x = __xfrm_state_lookup(daddr, spi, proto, family);
649 spin_unlock_bh(&xfrm_state_lock); 926 spin_unlock_bh(&xfrm_state_lock);
650 xfrm_state_put_afinfo(afinfo);
651 return x; 927 return x;
652} 928}
653EXPORT_SYMBOL(xfrm_state_lookup); 929EXPORT_SYMBOL(xfrm_state_lookup);
654 930
655struct xfrm_state * 931struct xfrm_state *
932xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr,
933 u8 proto, unsigned short family)
934{
935 struct xfrm_state *x;
936
937 spin_lock_bh(&xfrm_state_lock);
938 x = __xfrm_state_lookup_byaddr(daddr, saddr, proto, family);
939 spin_unlock_bh(&xfrm_state_lock);
940 return x;
941}
942EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
943
944struct xfrm_state *
656xfrm_find_acq(u8 mode, u32 reqid, u8 proto, 945xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
657 xfrm_address_t *daddr, xfrm_address_t *saddr, 946 xfrm_address_t *daddr, xfrm_address_t *saddr,
658 int create, unsigned short family) 947 int create, unsigned short family)
659{ 948{
660 struct xfrm_state *x; 949 struct xfrm_state *x;
950
951 spin_lock_bh(&xfrm_state_lock);
952 x = __find_acq_core(family, mode, reqid, proto, daddr, saddr, create);
953 spin_unlock_bh(&xfrm_state_lock);
954
955 return x;
956}
957EXPORT_SYMBOL(xfrm_find_acq);
958
959#ifdef CONFIG_XFRM_SUB_POLICY
960int
961xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
962 unsigned short family)
963{
964 int err = 0;
661 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); 965 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
662 if (!afinfo) 966 if (!afinfo)
663 return NULL; 967 return -EAFNOSUPPORT;
664 968
665 spin_lock_bh(&xfrm_state_lock); 969 spin_lock_bh(&xfrm_state_lock);
666 x = afinfo->find_acq(mode, reqid, proto, daddr, saddr, create); 970 if (afinfo->tmpl_sort)
971 err = afinfo->tmpl_sort(dst, src, n);
667 spin_unlock_bh(&xfrm_state_lock); 972 spin_unlock_bh(&xfrm_state_lock);
668 xfrm_state_put_afinfo(afinfo); 973 xfrm_state_put_afinfo(afinfo);
669 return x; 974 return err;
670} 975}
671EXPORT_SYMBOL(xfrm_find_acq); 976EXPORT_SYMBOL(xfrm_tmpl_sort);
977
978int
979xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
980 unsigned short family)
981{
982 int err = 0;
983 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
984 if (!afinfo)
985 return -EAFNOSUPPORT;
986
987 spin_lock_bh(&xfrm_state_lock);
988 if (afinfo->state_sort)
989 err = afinfo->state_sort(dst, src, n);
990 spin_unlock_bh(&xfrm_state_lock);
991 xfrm_state_put_afinfo(afinfo);
992 return err;
993}
994EXPORT_SYMBOL(xfrm_state_sort);
995#endif
672 996
673/* Silly enough, but I'm lazy to build resolution list */ 997/* Silly enough, but I'm lazy to build resolution list */
674 998
675static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) 999static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq)
676{ 1000{
677 int i; 1001 int i;
678 struct xfrm_state *x;
679 1002
680 for (i = 0; i < XFRM_DST_HSIZE; i++) { 1003 for (i = 0; i <= xfrm_state_hmask; i++) {
681 list_for_each_entry(x, xfrm_state_bydst+i, bydst) { 1004 struct hlist_node *entry;
682 if (x->km.seq == seq && x->km.state == XFRM_STATE_ACQ) { 1005 struct xfrm_state *x;
1006
1007 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
1008 if (x->km.seq == seq &&
1009 x->km.state == XFRM_STATE_ACQ) {
683 xfrm_state_hold(x); 1010 xfrm_state_hold(x);
684 return x; 1011 return x;
685 } 1012 }
@@ -715,7 +1042,7 @@ EXPORT_SYMBOL(xfrm_get_acqseq);
715void 1042void
716xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi) 1043xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
717{ 1044{
718 u32 h; 1045 unsigned int h;
719 struct xfrm_state *x0; 1046 struct xfrm_state *x0;
720 1047
721 if (x->id.spi) 1048 if (x->id.spi)
@@ -745,8 +1072,7 @@ xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
745 if (x->id.spi) { 1072 if (x->id.spi) {
746 spin_lock_bh(&xfrm_state_lock); 1073 spin_lock_bh(&xfrm_state_lock);
747 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family); 1074 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family);
748 list_add(&x->byspi, xfrm_state_byspi+h); 1075 hlist_add_head(&x->byspi, xfrm_state_byspi+h);
749 xfrm_state_hold(x);
750 spin_unlock_bh(&xfrm_state_lock); 1076 spin_unlock_bh(&xfrm_state_lock);
751 wake_up(&km_waitq); 1077 wake_up(&km_waitq);
752 } 1078 }
@@ -758,13 +1084,14 @@ int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
758{ 1084{
759 int i; 1085 int i;
760 struct xfrm_state *x; 1086 struct xfrm_state *x;
1087 struct hlist_node *entry;
761 int count = 0; 1088 int count = 0;
762 int err = 0; 1089 int err = 0;
763 1090
764 spin_lock_bh(&xfrm_state_lock); 1091 spin_lock_bh(&xfrm_state_lock);
765 for (i = 0; i < XFRM_DST_HSIZE; i++) { 1092 for (i = 0; i <= xfrm_state_hmask; i++) {
766 list_for_each_entry(x, xfrm_state_bydst+i, bydst) { 1093 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
767 if (proto == IPSEC_PROTO_ANY || x->id.proto == proto) 1094 if (xfrm_id_proto_match(x->id.proto, proto))
768 count++; 1095 count++;
769 } 1096 }
770 } 1097 }
@@ -773,9 +1100,9 @@ int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
773 goto out; 1100 goto out;
774 } 1101 }
775 1102
776 for (i = 0; i < XFRM_DST_HSIZE; i++) { 1103 for (i = 0; i <= xfrm_state_hmask; i++) {
777 list_for_each_entry(x, xfrm_state_bydst+i, bydst) { 1104 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
778 if (proto != IPSEC_PROTO_ANY && x->id.proto != proto) 1105 if (!xfrm_id_proto_match(x->id.proto, proto))
779 continue; 1106 continue;
780 err = func(x, --count, data); 1107 err = func(x, --count, data);
781 if (err) 1108 if (err)
@@ -832,10 +1159,8 @@ void xfrm_replay_notify(struct xfrm_state *x, int event)
832 km_state_notify(x, &c); 1159 km_state_notify(x, &c);
833 1160
834 if (x->replay_maxage && 1161 if (x->replay_maxage &&
835 !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) { 1162 !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
836 xfrm_state_hold(x);
837 x->xflags &= ~XFRM_TIME_DEFER; 1163 x->xflags &= ~XFRM_TIME_DEFER;
838 }
839} 1164}
840EXPORT_SYMBOL(xfrm_replay_notify); 1165EXPORT_SYMBOL(xfrm_replay_notify);
841 1166
@@ -853,7 +1178,6 @@ static void xfrm_replay_timer_handler(unsigned long data)
853 } 1178 }
854 1179
855 spin_unlock(&x->lock); 1180 spin_unlock(&x->lock);
856 xfrm_state_put(x);
857} 1181}
858 1182
859int xfrm_replay_check(struct xfrm_state *x, u32 seq) 1183int xfrm_replay_check(struct xfrm_state *x, u32 seq)
@@ -997,6 +1321,25 @@ void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid)
997} 1321}
998EXPORT_SYMBOL(km_policy_expired); 1322EXPORT_SYMBOL(km_policy_expired);
999 1323
1324int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr)
1325{
1326 int err = -EINVAL;
1327 int ret;
1328 struct xfrm_mgr *km;
1329
1330 read_lock(&xfrm_km_lock);
1331 list_for_each_entry(km, &xfrm_km_list, list) {
1332 if (km->report) {
1333 ret = km->report(proto, sel, addr);
1334 if (!ret)
1335 err = ret;
1336 }
1337 }
1338 read_unlock(&xfrm_km_lock);
1339 return err;
1340}
1341EXPORT_SYMBOL(km_report);
1342
1000int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen) 1343int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
1001{ 1344{
1002 int err; 1345 int err;
@@ -1018,7 +1361,7 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
1018 err = -EINVAL; 1361 err = -EINVAL;
1019 read_lock(&xfrm_km_lock); 1362 read_lock(&xfrm_km_lock);
1020 list_for_each_entry(km, &xfrm_km_list, list) { 1363 list_for_each_entry(km, &xfrm_km_list, list) {
1021 pol = km->compile_policy(sk->sk_family, optname, data, 1364 pol = km->compile_policy(sk, optname, data,
1022 optlen, &err); 1365 optlen, &err);
1023 if (err >= 0) 1366 if (err >= 0)
1024 break; 1367 break;
@@ -1065,11 +1408,8 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
1065 write_lock_bh(&xfrm_state_afinfo_lock); 1408 write_lock_bh(&xfrm_state_afinfo_lock);
1066 if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) 1409 if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
1067 err = -ENOBUFS; 1410 err = -ENOBUFS;
1068 else { 1411 else
1069 afinfo->state_bydst = xfrm_state_bydst;
1070 afinfo->state_byspi = xfrm_state_byspi;
1071 xfrm_state_afinfo[afinfo->family] = afinfo; 1412 xfrm_state_afinfo[afinfo->family] = afinfo;
1072 }
1073 write_unlock_bh(&xfrm_state_afinfo_lock); 1413 write_unlock_bh(&xfrm_state_afinfo_lock);
1074 return err; 1414 return err;
1075} 1415}
@@ -1086,11 +1426,8 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
1086 if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { 1426 if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
1087 if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) 1427 if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
1088 err = -EINVAL; 1428 err = -EINVAL;
1089 else { 1429 else
1090 xfrm_state_afinfo[afinfo->family] = NULL; 1430 xfrm_state_afinfo[afinfo->family] = NULL;
1091 afinfo->state_byspi = NULL;
1092 afinfo->state_bydst = NULL;
1093 }
1094 } 1431 }
1095 write_unlock_bh(&xfrm_state_afinfo_lock); 1432 write_unlock_bh(&xfrm_state_afinfo_lock);
1096 return err; 1433 return err;
@@ -1206,12 +1543,17 @@ EXPORT_SYMBOL(xfrm_init_state);
1206 1543
1207void __init xfrm_state_init(void) 1544void __init xfrm_state_init(void)
1208{ 1545{
1209 int i; 1546 unsigned int sz;
1547
1548 sz = sizeof(struct hlist_head) * 8;
1549
1550 xfrm_state_bydst = xfrm_hash_alloc(sz);
1551 xfrm_state_bysrc = xfrm_hash_alloc(sz);
1552 xfrm_state_byspi = xfrm_hash_alloc(sz);
1553 if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi)
1554 panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes.");
1555 xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1);
1210 1556
1211 for (i=0; i<XFRM_DST_HSIZE; i++) {
1212 INIT_LIST_HEAD(&xfrm_state_bydst[i]);
1213 INIT_LIST_HEAD(&xfrm_state_byspi[i]);
1214 }
1215 INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL); 1557 INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL);
1216} 1558}
1217 1559