diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-28 15:49:40 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-28 15:49:40 -0500 |
commit | 0191b625ca5a46206d2fb862bb08f36f2fcb3b31 (patch) | |
tree | 454d1842b1833d976da62abcbd5c47521ebe9bd7 /net/xfrm/xfrm_policy.c | |
parent | 54a696bd07c14d3b1192d03ce7269bc59b45209a (diff) | |
parent | eb56092fc168bf5af199d47af50c0d84a96db898 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1429 commits)
net: Allow dependancies of FDDI & Tokenring to be modular.
igb: Fix build warning when DCA is disabled.
net: Fix warning fallout from recent NAPI interface changes.
gro: Fix potential use after free
sfc: If AN is enabled, always read speed/duplex from the AN advertising bits
sfc: When disabling the NIC, close the device rather than unregistering it
sfc: SFT9001: Add cable diagnostics
sfc: Add support for multiple PHY self-tests
sfc: Merge top-level functions for self-tests
sfc: Clean up PHY mode management in loopback self-test
sfc: Fix unreliable link detection in some loopback modes
sfc: Generate unique names for per-NIC workqueues
802.3ad: use standard ethhdr instead of ad_header
802.3ad: generalize out mac address initializer
802.3ad: initialize ports LACPDU from const initializer
802.3ad: remove typedef around ad_system
802.3ad: turn ports is_individual into a bool
802.3ad: turn ports is_enabled into a bool
802.3ad: make ntt bool
ixgbe: Fix set_ringparam in ixgbe to use the same memory pools.
...
Fixed trivial IPv4/6 address printing conflicts in fs/cifs/connect.c due
to the conversion to %pI (in this networking merge) and the addition of
doing IPv6 addresses (from the earlier merge of CIFS).
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 511 |
1 files changed, 292 insertions, 219 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index fb216c9adf86..9c068ab3a834 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -34,28 +34,16 @@ | |||
34 | 34 | ||
35 | #include "xfrm_hash.h" | 35 | #include "xfrm_hash.h" |
36 | 36 | ||
37 | int sysctl_xfrm_larval_drop __read_mostly = 1; | ||
38 | |||
39 | #ifdef CONFIG_XFRM_STATISTICS | ||
40 | DEFINE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics) __read_mostly; | ||
41 | EXPORT_SYMBOL(xfrm_statistics); | ||
42 | #endif | ||
43 | |||
44 | DEFINE_MUTEX(xfrm_cfg_mutex); | 37 | DEFINE_MUTEX(xfrm_cfg_mutex); |
45 | EXPORT_SYMBOL(xfrm_cfg_mutex); | 38 | EXPORT_SYMBOL(xfrm_cfg_mutex); |
46 | 39 | ||
47 | static DEFINE_RWLOCK(xfrm_policy_lock); | 40 | static DEFINE_RWLOCK(xfrm_policy_lock); |
48 | 41 | ||
49 | static struct list_head xfrm_policy_all; | ||
50 | unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2]; | ||
51 | EXPORT_SYMBOL(xfrm_policy_count); | ||
52 | |||
53 | static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); | 42 | static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); |
54 | static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; | 43 | static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; |
55 | 44 | ||
56 | static struct kmem_cache *xfrm_dst_cache __read_mostly; | 45 | static struct kmem_cache *xfrm_dst_cache __read_mostly; |
57 | 46 | ||
58 | static struct work_struct xfrm_policy_gc_work; | ||
59 | static HLIST_HEAD(xfrm_policy_gc_list); | 47 | static HLIST_HEAD(xfrm_policy_gc_list); |
60 | static DEFINE_SPINLOCK(xfrm_policy_gc_lock); | 48 | static DEFINE_SPINLOCK(xfrm_policy_gc_lock); |
61 | 49 | ||
@@ -63,6 +51,9 @@ static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); | |||
63 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); | 51 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); |
64 | static void xfrm_init_pmtu(struct dst_entry *dst); | 52 | static void xfrm_init_pmtu(struct dst_entry *dst); |
65 | 53 | ||
54 | static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, | ||
55 | int dir); | ||
56 | |||
66 | static inline int | 57 | static inline int |
67 | __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) | 58 | __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) |
68 | { | 59 | { |
@@ -97,7 +88,7 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, | |||
97 | return 0; | 88 | return 0; |
98 | } | 89 | } |
99 | 90 | ||
100 | static inline struct dst_entry *__xfrm_dst_lookup(int tos, | 91 | static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, |
101 | xfrm_address_t *saddr, | 92 | xfrm_address_t *saddr, |
102 | xfrm_address_t *daddr, | 93 | xfrm_address_t *daddr, |
103 | int family) | 94 | int family) |
@@ -109,7 +100,7 @@ static inline struct dst_entry *__xfrm_dst_lookup(int tos, | |||
109 | if (unlikely(afinfo == NULL)) | 100 | if (unlikely(afinfo == NULL)) |
110 | return ERR_PTR(-EAFNOSUPPORT); | 101 | return ERR_PTR(-EAFNOSUPPORT); |
111 | 102 | ||
112 | dst = afinfo->dst_lookup(tos, saddr, daddr); | 103 | dst = afinfo->dst_lookup(net, tos, saddr, daddr); |
113 | 104 | ||
114 | xfrm_policy_put_afinfo(afinfo); | 105 | xfrm_policy_put_afinfo(afinfo); |
115 | 106 | ||
@@ -121,6 +112,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos, | |||
121 | xfrm_address_t *prev_daddr, | 112 | xfrm_address_t *prev_daddr, |
122 | int family) | 113 | int family) |
123 | { | 114 | { |
115 | struct net *net = xs_net(x); | ||
124 | xfrm_address_t *saddr = &x->props.saddr; | 116 | xfrm_address_t *saddr = &x->props.saddr; |
125 | xfrm_address_t *daddr = &x->id.daddr; | 117 | xfrm_address_t *daddr = &x->id.daddr; |
126 | struct dst_entry *dst; | 118 | struct dst_entry *dst; |
@@ -134,7 +126,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos, | |||
134 | daddr = x->coaddr; | 126 | daddr = x->coaddr; |
135 | } | 127 | } |
136 | 128 | ||
137 | dst = __xfrm_dst_lookup(tos, saddr, daddr, family); | 129 | dst = __xfrm_dst_lookup(net, tos, saddr, daddr, family); |
138 | 130 | ||
139 | if (!IS_ERR(dst)) { | 131 | if (!IS_ERR(dst)) { |
140 | if (prev_saddr != saddr) | 132 | if (prev_saddr != saddr) |
@@ -229,13 +221,14 @@ expired: | |||
229 | * SPD calls. | 221 | * SPD calls. |
230 | */ | 222 | */ |
231 | 223 | ||
232 | struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp) | 224 | struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp) |
233 | { | 225 | { |
234 | struct xfrm_policy *policy; | 226 | struct xfrm_policy *policy; |
235 | 227 | ||
236 | policy = kzalloc(sizeof(struct xfrm_policy), gfp); | 228 | policy = kzalloc(sizeof(struct xfrm_policy), gfp); |
237 | 229 | ||
238 | if (policy) { | 230 | if (policy) { |
231 | write_pnet(&policy->xp_net, net); | ||
239 | INIT_LIST_HEAD(&policy->walk.all); | 232 | INIT_LIST_HEAD(&policy->walk.all); |
240 | INIT_HLIST_NODE(&policy->bydst); | 233 | INIT_HLIST_NODE(&policy->bydst); |
241 | INIT_HLIST_NODE(&policy->byidx); | 234 | INIT_HLIST_NODE(&policy->byidx); |
@@ -296,6 +289,7 @@ static void xfrm_policy_gc_task(struct work_struct *work) | |||
296 | hlist_for_each_entry_safe(policy, entry, tmp, &gc_list, bydst) | 289 | hlist_for_each_entry_safe(policy, entry, tmp, &gc_list, bydst) |
297 | xfrm_policy_gc_kill(policy); | 290 | xfrm_policy_gc_kill(policy); |
298 | } | 291 | } |
292 | static DECLARE_WORK(xfrm_policy_gc_work, xfrm_policy_gc_task); | ||
299 | 293 | ||
300 | /* Rule must be locked. Release descentant resources, announce | 294 | /* Rule must be locked. Release descentant resources, announce |
301 | * entry dead. The rule must be unlinked from lists to the moment. | 295 | * entry dead. The rule must be unlinked from lists to the moment. |
@@ -322,38 +316,29 @@ static void xfrm_policy_kill(struct xfrm_policy *policy) | |||
322 | schedule_work(&xfrm_policy_gc_work); | 316 | schedule_work(&xfrm_policy_gc_work); |
323 | } | 317 | } |
324 | 318 | ||
325 | struct xfrm_policy_hash { | ||
326 | struct hlist_head *table; | ||
327 | unsigned int hmask; | ||
328 | }; | ||
329 | |||
330 | static struct hlist_head xfrm_policy_inexact[XFRM_POLICY_MAX*2]; | ||
331 | static struct xfrm_policy_hash xfrm_policy_bydst[XFRM_POLICY_MAX*2] __read_mostly; | ||
332 | static struct hlist_head *xfrm_policy_byidx __read_mostly; | ||
333 | static unsigned int xfrm_idx_hmask __read_mostly; | ||
334 | static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; | 319 | static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; |
335 | 320 | ||
336 | static inline unsigned int idx_hash(u32 index) | 321 | static inline unsigned int idx_hash(struct net *net, u32 index) |
337 | { | 322 | { |
338 | return __idx_hash(index, xfrm_idx_hmask); | 323 | return __idx_hash(index, net->xfrm.policy_idx_hmask); |
339 | } | 324 | } |
340 | 325 | ||
341 | static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir) | 326 | static struct hlist_head *policy_hash_bysel(struct net *net, struct xfrm_selector *sel, unsigned short family, int dir) |
342 | { | 327 | { |
343 | unsigned int hmask = xfrm_policy_bydst[dir].hmask; | 328 | unsigned int hmask = net->xfrm.policy_bydst[dir].hmask; |
344 | unsigned int hash = __sel_hash(sel, family, hmask); | 329 | unsigned int hash = __sel_hash(sel, family, hmask); |
345 | 330 | ||
346 | return (hash == hmask + 1 ? | 331 | return (hash == hmask + 1 ? |
347 | &xfrm_policy_inexact[dir] : | 332 | &net->xfrm.policy_inexact[dir] : |
348 | xfrm_policy_bydst[dir].table + hash); | 333 | net->xfrm.policy_bydst[dir].table + hash); |
349 | } | 334 | } |
350 | 335 | ||
351 | static struct hlist_head *policy_hash_direct(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, int dir) | 336 | static struct hlist_head *policy_hash_direct(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, int dir) |
352 | { | 337 | { |
353 | unsigned int hmask = xfrm_policy_bydst[dir].hmask; | 338 | unsigned int hmask = net->xfrm.policy_bydst[dir].hmask; |
354 | unsigned int hash = __addr_hash(daddr, saddr, family, hmask); | 339 | unsigned int hash = __addr_hash(daddr, saddr, family, hmask); |
355 | 340 | ||
356 | return xfrm_policy_bydst[dir].table + hash; | 341 | return net->xfrm.policy_bydst[dir].table + hash; |
357 | } | 342 | } |
358 | 343 | ||
359 | static void xfrm_dst_hash_transfer(struct hlist_head *list, | 344 | static void xfrm_dst_hash_transfer(struct hlist_head *list, |
@@ -408,12 +393,12 @@ static unsigned long xfrm_new_hash_mask(unsigned int old_hmask) | |||
408 | return ((old_hmask + 1) << 1) - 1; | 393 | return ((old_hmask + 1) << 1) - 1; |
409 | } | 394 | } |
410 | 395 | ||
411 | static void xfrm_bydst_resize(int dir) | 396 | static void xfrm_bydst_resize(struct net *net, int dir) |
412 | { | 397 | { |
413 | unsigned int hmask = xfrm_policy_bydst[dir].hmask; | 398 | unsigned int hmask = net->xfrm.policy_bydst[dir].hmask; |
414 | unsigned int nhashmask = xfrm_new_hash_mask(hmask); | 399 | unsigned int nhashmask = xfrm_new_hash_mask(hmask); |
415 | unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); | 400 | unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); |
416 | struct hlist_head *odst = xfrm_policy_bydst[dir].table; | 401 | struct hlist_head *odst = net->xfrm.policy_bydst[dir].table; |
417 | struct hlist_head *ndst = xfrm_hash_alloc(nsize); | 402 | struct hlist_head *ndst = xfrm_hash_alloc(nsize); |
418 | int i; | 403 | int i; |
419 | 404 | ||
@@ -425,20 +410,20 @@ static void xfrm_bydst_resize(int dir) | |||
425 | for (i = hmask; i >= 0; i--) | 410 | for (i = hmask; i >= 0; i--) |
426 | xfrm_dst_hash_transfer(odst + i, ndst, nhashmask); | 411 | xfrm_dst_hash_transfer(odst + i, ndst, nhashmask); |
427 | 412 | ||
428 | xfrm_policy_bydst[dir].table = ndst; | 413 | net->xfrm.policy_bydst[dir].table = ndst; |
429 | xfrm_policy_bydst[dir].hmask = nhashmask; | 414 | net->xfrm.policy_bydst[dir].hmask = nhashmask; |
430 | 415 | ||
431 | write_unlock_bh(&xfrm_policy_lock); | 416 | write_unlock_bh(&xfrm_policy_lock); |
432 | 417 | ||
433 | xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); | 418 | xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); |
434 | } | 419 | } |
435 | 420 | ||
436 | static void xfrm_byidx_resize(int total) | 421 | static void xfrm_byidx_resize(struct net *net, int total) |
437 | { | 422 | { |
438 | unsigned int hmask = xfrm_idx_hmask; | 423 | unsigned int hmask = net->xfrm.policy_idx_hmask; |
439 | unsigned int nhashmask = xfrm_new_hash_mask(hmask); | 424 | unsigned int nhashmask = xfrm_new_hash_mask(hmask); |
440 | unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); | 425 | unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); |
441 | struct hlist_head *oidx = xfrm_policy_byidx; | 426 | struct hlist_head *oidx = net->xfrm.policy_byidx; |
442 | struct hlist_head *nidx = xfrm_hash_alloc(nsize); | 427 | struct hlist_head *nidx = xfrm_hash_alloc(nsize); |
443 | int i; | 428 | int i; |
444 | 429 | ||
@@ -450,18 +435,18 @@ static void xfrm_byidx_resize(int total) | |||
450 | for (i = hmask; i >= 0; i--) | 435 | for (i = hmask; i >= 0; i--) |
451 | xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask); | 436 | xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask); |
452 | 437 | ||
453 | xfrm_policy_byidx = nidx; | 438 | net->xfrm.policy_byidx = nidx; |
454 | xfrm_idx_hmask = nhashmask; | 439 | net->xfrm.policy_idx_hmask = nhashmask; |
455 | 440 | ||
456 | write_unlock_bh(&xfrm_policy_lock); | 441 | write_unlock_bh(&xfrm_policy_lock); |
457 | 442 | ||
458 | xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); | 443 | xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); |
459 | } | 444 | } |
460 | 445 | ||
461 | static inline int xfrm_bydst_should_resize(int dir, int *total) | 446 | static inline int xfrm_bydst_should_resize(struct net *net, int dir, int *total) |
462 | { | 447 | { |
463 | unsigned int cnt = xfrm_policy_count[dir]; | 448 | unsigned int cnt = net->xfrm.policy_count[dir]; |
464 | unsigned int hmask = xfrm_policy_bydst[dir].hmask; | 449 | unsigned int hmask = net->xfrm.policy_bydst[dir].hmask; |
465 | 450 | ||
466 | if (total) | 451 | if (total) |
467 | *total += cnt; | 452 | *total += cnt; |
@@ -473,9 +458,9 @@ static inline int xfrm_bydst_should_resize(int dir, int *total) | |||
473 | return 0; | 458 | return 0; |
474 | } | 459 | } |
475 | 460 | ||
476 | static inline int xfrm_byidx_should_resize(int total) | 461 | static inline int xfrm_byidx_should_resize(struct net *net, int total) |
477 | { | 462 | { |
478 | unsigned int hmask = xfrm_idx_hmask; | 463 | unsigned int hmask = net->xfrm.policy_idx_hmask; |
479 | 464 | ||
480 | if ((hmask + 1) < xfrm_policy_hashmax && | 465 | if ((hmask + 1) < xfrm_policy_hashmax && |
481 | total > hmask) | 466 | total > hmask) |
@@ -487,41 +472,40 @@ static inline int xfrm_byidx_should_resize(int total) | |||
487 | void xfrm_spd_getinfo(struct xfrmk_spdinfo *si) | 472 | void xfrm_spd_getinfo(struct xfrmk_spdinfo *si) |
488 | { | 473 | { |
489 | read_lock_bh(&xfrm_policy_lock); | 474 | read_lock_bh(&xfrm_policy_lock); |
490 | si->incnt = xfrm_policy_count[XFRM_POLICY_IN]; | 475 | si->incnt = init_net.xfrm.policy_count[XFRM_POLICY_IN]; |
491 | si->outcnt = xfrm_policy_count[XFRM_POLICY_OUT]; | 476 | si->outcnt = init_net.xfrm.policy_count[XFRM_POLICY_OUT]; |
492 | si->fwdcnt = xfrm_policy_count[XFRM_POLICY_FWD]; | 477 | si->fwdcnt = init_net.xfrm.policy_count[XFRM_POLICY_FWD]; |
493 | si->inscnt = xfrm_policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX]; | 478 | si->inscnt = init_net.xfrm.policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX]; |
494 | si->outscnt = xfrm_policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX]; | 479 | si->outscnt = init_net.xfrm.policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX]; |
495 | si->fwdscnt = xfrm_policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX]; | 480 | si->fwdscnt = init_net.xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX]; |
496 | si->spdhcnt = xfrm_idx_hmask; | 481 | si->spdhcnt = init_net.xfrm.policy_idx_hmask; |
497 | si->spdhmcnt = xfrm_policy_hashmax; | 482 | si->spdhmcnt = xfrm_policy_hashmax; |
498 | read_unlock_bh(&xfrm_policy_lock); | 483 | read_unlock_bh(&xfrm_policy_lock); |
499 | } | 484 | } |
500 | EXPORT_SYMBOL(xfrm_spd_getinfo); | 485 | EXPORT_SYMBOL(xfrm_spd_getinfo); |
501 | 486 | ||
502 | static DEFINE_MUTEX(hash_resize_mutex); | 487 | static DEFINE_MUTEX(hash_resize_mutex); |
503 | static void xfrm_hash_resize(struct work_struct *__unused) | 488 | static void xfrm_hash_resize(struct work_struct *work) |
504 | { | 489 | { |
490 | struct net *net = container_of(work, struct net, xfrm.policy_hash_work); | ||
505 | int dir, total; | 491 | int dir, total; |
506 | 492 | ||
507 | mutex_lock(&hash_resize_mutex); | 493 | mutex_lock(&hash_resize_mutex); |
508 | 494 | ||
509 | total = 0; | 495 | total = 0; |
510 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { | 496 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { |
511 | if (xfrm_bydst_should_resize(dir, &total)) | 497 | if (xfrm_bydst_should_resize(net, dir, &total)) |
512 | xfrm_bydst_resize(dir); | 498 | xfrm_bydst_resize(net, dir); |
513 | } | 499 | } |
514 | if (xfrm_byidx_should_resize(total)) | 500 | if (xfrm_byidx_should_resize(net, total)) |
515 | xfrm_byidx_resize(total); | 501 | xfrm_byidx_resize(net, total); |
516 | 502 | ||
517 | mutex_unlock(&hash_resize_mutex); | 503 | mutex_unlock(&hash_resize_mutex); |
518 | } | 504 | } |
519 | 505 | ||
520 | static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize); | ||
521 | |||
522 | /* Generate new index... KAME seems to generate them ordered by cost | 506 | /* Generate new index... KAME seems to generate them ordered by cost |
523 | * of an absolute inpredictability of ordering of rules. This will not pass. */ | 507 | * of an absolute inpredictability of ordering of rules. This will not pass. */ |
524 | static u32 xfrm_gen_index(u8 type, int dir) | 508 | static u32 xfrm_gen_index(struct net *net, int dir) |
525 | { | 509 | { |
526 | static u32 idx_generator; | 510 | static u32 idx_generator; |
527 | 511 | ||
@@ -536,7 +520,7 @@ static u32 xfrm_gen_index(u8 type, int dir) | |||
536 | idx_generator += 8; | 520 | idx_generator += 8; |
537 | if (idx == 0) | 521 | if (idx == 0) |
538 | idx = 8; | 522 | idx = 8; |
539 | list = xfrm_policy_byidx + idx_hash(idx); | 523 | list = net->xfrm.policy_byidx + idx_hash(net, idx); |
540 | found = 0; | 524 | found = 0; |
541 | hlist_for_each_entry(p, entry, list, byidx) { | 525 | hlist_for_each_entry(p, entry, list, byidx) { |
542 | if (p->index == idx) { | 526 | if (p->index == idx) { |
@@ -566,6 +550,7 @@ static inline int selector_cmp(struct xfrm_selector *s1, struct xfrm_selector *s | |||
566 | 550 | ||
567 | int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | 551 | int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) |
568 | { | 552 | { |
553 | struct net *net = xp_net(policy); | ||
569 | struct xfrm_policy *pol; | 554 | struct xfrm_policy *pol; |
570 | struct xfrm_policy *delpol; | 555 | struct xfrm_policy *delpol; |
571 | struct hlist_head *chain; | 556 | struct hlist_head *chain; |
@@ -573,7 +558,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
573 | struct dst_entry *gc_list; | 558 | struct dst_entry *gc_list; |
574 | 559 | ||
575 | write_lock_bh(&xfrm_policy_lock); | 560 | write_lock_bh(&xfrm_policy_lock); |
576 | chain = policy_hash_bysel(&policy->selector, policy->family, dir); | 561 | chain = policy_hash_bysel(net, &policy->selector, policy->family, dir); |
577 | delpol = NULL; | 562 | delpol = NULL; |
578 | newpos = NULL; | 563 | newpos = NULL; |
579 | hlist_for_each_entry(pol, entry, chain, bydst) { | 564 | hlist_for_each_entry(pol, entry, chain, bydst) { |
@@ -600,27 +585,23 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
600 | else | 585 | else |
601 | hlist_add_head(&policy->bydst, chain); | 586 | hlist_add_head(&policy->bydst, chain); |
602 | xfrm_pol_hold(policy); | 587 | xfrm_pol_hold(policy); |
603 | xfrm_policy_count[dir]++; | 588 | net->xfrm.policy_count[dir]++; |
604 | atomic_inc(&flow_cache_genid); | 589 | atomic_inc(&flow_cache_genid); |
605 | if (delpol) { | 590 | if (delpol) |
606 | hlist_del(&delpol->bydst); | 591 | __xfrm_policy_unlink(delpol, dir); |
607 | hlist_del(&delpol->byidx); | 592 | policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir); |
608 | list_del(&delpol->walk.all); | 593 | hlist_add_head(&policy->byidx, net->xfrm.policy_byidx+idx_hash(net, policy->index)); |
609 | xfrm_policy_count[dir]--; | ||
610 | } | ||
611 | policy->index = delpol ? delpol->index : xfrm_gen_index(policy->type, dir); | ||
612 | hlist_add_head(&policy->byidx, xfrm_policy_byidx+idx_hash(policy->index)); | ||
613 | policy->curlft.add_time = get_seconds(); | 594 | policy->curlft.add_time = get_seconds(); |
614 | policy->curlft.use_time = 0; | 595 | policy->curlft.use_time = 0; |
615 | if (!mod_timer(&policy->timer, jiffies + HZ)) | 596 | if (!mod_timer(&policy->timer, jiffies + HZ)) |
616 | xfrm_pol_hold(policy); | 597 | xfrm_pol_hold(policy); |
617 | list_add(&policy->walk.all, &xfrm_policy_all); | 598 | list_add(&policy->walk.all, &net->xfrm.policy_all); |
618 | write_unlock_bh(&xfrm_policy_lock); | 599 | write_unlock_bh(&xfrm_policy_lock); |
619 | 600 | ||
620 | if (delpol) | 601 | if (delpol) |
621 | xfrm_policy_kill(delpol); | 602 | xfrm_policy_kill(delpol); |
622 | else if (xfrm_bydst_should_resize(dir, NULL)) | 603 | else if (xfrm_bydst_should_resize(net, dir, NULL)) |
623 | schedule_work(&xfrm_hash_work); | 604 | schedule_work(&net->xfrm.policy_hash_work); |
624 | 605 | ||
625 | read_lock_bh(&xfrm_policy_lock); | 606 | read_lock_bh(&xfrm_policy_lock); |
626 | gc_list = NULL; | 607 | gc_list = NULL; |
@@ -654,7 +635,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
654 | } | 635 | } |
655 | EXPORT_SYMBOL(xfrm_policy_insert); | 636 | EXPORT_SYMBOL(xfrm_policy_insert); |
656 | 637 | ||
657 | struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, | 638 | struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, |
658 | struct xfrm_selector *sel, | 639 | struct xfrm_selector *sel, |
659 | struct xfrm_sec_ctx *ctx, int delete, | 640 | struct xfrm_sec_ctx *ctx, int delete, |
660 | int *err) | 641 | int *err) |
@@ -665,7 +646,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, | |||
665 | 646 | ||
666 | *err = 0; | 647 | *err = 0; |
667 | write_lock_bh(&xfrm_policy_lock); | 648 | write_lock_bh(&xfrm_policy_lock); |
668 | chain = policy_hash_bysel(sel, sel->family, dir); | 649 | chain = policy_hash_bysel(net, sel, sel->family, dir); |
669 | ret = NULL; | 650 | ret = NULL; |
670 | hlist_for_each_entry(pol, entry, chain, bydst) { | 651 | hlist_for_each_entry(pol, entry, chain, bydst) { |
671 | if (pol->type == type && | 652 | if (pol->type == type && |
@@ -679,10 +660,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, | |||
679 | write_unlock_bh(&xfrm_policy_lock); | 660 | write_unlock_bh(&xfrm_policy_lock); |
680 | return pol; | 661 | return pol; |
681 | } | 662 | } |
682 | hlist_del(&pol->bydst); | 663 | __xfrm_policy_unlink(pol, dir); |
683 | hlist_del(&pol->byidx); | ||
684 | list_del(&pol->walk.all); | ||
685 | xfrm_policy_count[dir]--; | ||
686 | } | 664 | } |
687 | ret = pol; | 665 | ret = pol; |
688 | break; | 666 | break; |
@@ -698,8 +676,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, | |||
698 | } | 676 | } |
699 | EXPORT_SYMBOL(xfrm_policy_bysel_ctx); | 677 | EXPORT_SYMBOL(xfrm_policy_bysel_ctx); |
700 | 678 | ||
701 | struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, | 679 | struct xfrm_policy *xfrm_policy_byid(struct net *net, u8 type, int dir, u32 id, |
702 | int *err) | 680 | int delete, int *err) |
703 | { | 681 | { |
704 | struct xfrm_policy *pol, *ret; | 682 | struct xfrm_policy *pol, *ret; |
705 | struct hlist_head *chain; | 683 | struct hlist_head *chain; |
@@ -711,7 +689,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, | |||
711 | 689 | ||
712 | *err = 0; | 690 | *err = 0; |
713 | write_lock_bh(&xfrm_policy_lock); | 691 | write_lock_bh(&xfrm_policy_lock); |
714 | chain = xfrm_policy_byidx + idx_hash(id); | 692 | chain = net->xfrm.policy_byidx + idx_hash(net, id); |
715 | ret = NULL; | 693 | ret = NULL; |
716 | hlist_for_each_entry(pol, entry, chain, byidx) { | 694 | hlist_for_each_entry(pol, entry, chain, byidx) { |
717 | if (pol->type == type && pol->index == id) { | 695 | if (pol->type == type && pol->index == id) { |
@@ -723,10 +701,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, | |||
723 | write_unlock_bh(&xfrm_policy_lock); | 701 | write_unlock_bh(&xfrm_policy_lock); |
724 | return pol; | 702 | return pol; |
725 | } | 703 | } |
726 | hlist_del(&pol->bydst); | 704 | __xfrm_policy_unlink(pol, dir); |
727 | hlist_del(&pol->byidx); | ||
728 | list_del(&pol->walk.all); | ||
729 | xfrm_policy_count[dir]--; | ||
730 | } | 705 | } |
731 | ret = pol; | 706 | ret = pol; |
732 | break; | 707 | break; |
@@ -744,7 +719,7 @@ EXPORT_SYMBOL(xfrm_policy_byid); | |||
744 | 719 | ||
745 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 720 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
746 | static inline int | 721 | static inline int |
747 | xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) | 722 | xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audit_info) |
748 | { | 723 | { |
749 | int dir, err = 0; | 724 | int dir, err = 0; |
750 | 725 | ||
@@ -754,7 +729,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) | |||
754 | int i; | 729 | int i; |
755 | 730 | ||
756 | hlist_for_each_entry(pol, entry, | 731 | hlist_for_each_entry(pol, entry, |
757 | &xfrm_policy_inexact[dir], bydst) { | 732 | &net->xfrm.policy_inexact[dir], bydst) { |
758 | if (pol->type != type) | 733 | if (pol->type != type) |
759 | continue; | 734 | continue; |
760 | err = security_xfrm_policy_delete(pol->security); | 735 | err = security_xfrm_policy_delete(pol->security); |
@@ -766,9 +741,9 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) | |||
766 | return err; | 741 | return err; |
767 | } | 742 | } |
768 | } | 743 | } |
769 | for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { | 744 | for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) { |
770 | hlist_for_each_entry(pol, entry, | 745 | hlist_for_each_entry(pol, entry, |
771 | xfrm_policy_bydst[dir].table + i, | 746 | net->xfrm.policy_bydst[dir].table + i, |
772 | bydst) { | 747 | bydst) { |
773 | if (pol->type != type) | 748 | if (pol->type != type) |
774 | continue; | 749 | continue; |
@@ -788,36 +763,33 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) | |||
788 | } | 763 | } |
789 | #else | 764 | #else |
790 | static inline int | 765 | static inline int |
791 | xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) | 766 | xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audit_info) |
792 | { | 767 | { |
793 | return 0; | 768 | return 0; |
794 | } | 769 | } |
795 | #endif | 770 | #endif |
796 | 771 | ||
797 | int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) | 772 | int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) |
798 | { | 773 | { |
799 | int dir, err = 0; | 774 | int dir, err = 0; |
800 | 775 | ||
801 | write_lock_bh(&xfrm_policy_lock); | 776 | write_lock_bh(&xfrm_policy_lock); |
802 | 777 | ||
803 | err = xfrm_policy_flush_secctx_check(type, audit_info); | 778 | err = xfrm_policy_flush_secctx_check(net, type, audit_info); |
804 | if (err) | 779 | if (err) |
805 | goto out; | 780 | goto out; |
806 | 781 | ||
807 | for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { | 782 | for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { |
808 | struct xfrm_policy *pol; | 783 | struct xfrm_policy *pol; |
809 | struct hlist_node *entry; | 784 | struct hlist_node *entry; |
810 | int i, killed; | 785 | int i; |
811 | 786 | ||
812 | killed = 0; | ||
813 | again1: | 787 | again1: |
814 | hlist_for_each_entry(pol, entry, | 788 | hlist_for_each_entry(pol, entry, |
815 | &xfrm_policy_inexact[dir], bydst) { | 789 | &net->xfrm.policy_inexact[dir], bydst) { |
816 | if (pol->type != type) | 790 | if (pol->type != type) |
817 | continue; | 791 | continue; |
818 | hlist_del(&pol->bydst); | 792 | __xfrm_policy_unlink(pol, dir); |
819 | hlist_del(&pol->byidx); | ||
820 | list_del(&pol->walk.all); | ||
821 | write_unlock_bh(&xfrm_policy_lock); | 793 | write_unlock_bh(&xfrm_policy_lock); |
822 | 794 | ||
823 | xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, | 795 | xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, |
@@ -825,22 +797,19 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) | |||
825 | audit_info->secid); | 797 | audit_info->secid); |
826 | 798 | ||
827 | xfrm_policy_kill(pol); | 799 | xfrm_policy_kill(pol); |
828 | killed++; | ||
829 | 800 | ||
830 | write_lock_bh(&xfrm_policy_lock); | 801 | write_lock_bh(&xfrm_policy_lock); |
831 | goto again1; | 802 | goto again1; |
832 | } | 803 | } |
833 | 804 | ||
834 | for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { | 805 | for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) { |
835 | again2: | 806 | again2: |
836 | hlist_for_each_entry(pol, entry, | 807 | hlist_for_each_entry(pol, entry, |
837 | xfrm_policy_bydst[dir].table + i, | 808 | net->xfrm.policy_bydst[dir].table + i, |
838 | bydst) { | 809 | bydst) { |
839 | if (pol->type != type) | 810 | if (pol->type != type) |
840 | continue; | 811 | continue; |
841 | hlist_del(&pol->bydst); | 812 | __xfrm_policy_unlink(pol, dir); |
842 | hlist_del(&pol->byidx); | ||
843 | list_del(&pol->walk.all); | ||
844 | write_unlock_bh(&xfrm_policy_lock); | 813 | write_unlock_bh(&xfrm_policy_lock); |
845 | 814 | ||
846 | xfrm_audit_policy_delete(pol, 1, | 815 | xfrm_audit_policy_delete(pol, 1, |
@@ -848,14 +817,12 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) | |||
848 | audit_info->sessionid, | 817 | audit_info->sessionid, |
849 | audit_info->secid); | 818 | audit_info->secid); |
850 | xfrm_policy_kill(pol); | 819 | xfrm_policy_kill(pol); |
851 | killed++; | ||
852 | 820 | ||
853 | write_lock_bh(&xfrm_policy_lock); | 821 | write_lock_bh(&xfrm_policy_lock); |
854 | goto again2; | 822 | goto again2; |
855 | } | 823 | } |
856 | } | 824 | } |
857 | 825 | ||
858 | xfrm_policy_count[dir] -= killed; | ||
859 | } | 826 | } |
860 | atomic_inc(&flow_cache_genid); | 827 | atomic_inc(&flow_cache_genid); |
861 | out: | 828 | out: |
@@ -864,7 +831,7 @@ out: | |||
864 | } | 831 | } |
865 | EXPORT_SYMBOL(xfrm_policy_flush); | 832 | EXPORT_SYMBOL(xfrm_policy_flush); |
866 | 833 | ||
867 | int xfrm_policy_walk(struct xfrm_policy_walk *walk, | 834 | int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk, |
868 | int (*func)(struct xfrm_policy *, int, int, void*), | 835 | int (*func)(struct xfrm_policy *, int, int, void*), |
869 | void *data) | 836 | void *data) |
870 | { | 837 | { |
@@ -881,10 +848,10 @@ int xfrm_policy_walk(struct xfrm_policy_walk *walk, | |||
881 | 848 | ||
882 | write_lock_bh(&xfrm_policy_lock); | 849 | write_lock_bh(&xfrm_policy_lock); |
883 | if (list_empty(&walk->walk.all)) | 850 | if (list_empty(&walk->walk.all)) |
884 | x = list_first_entry(&xfrm_policy_all, struct xfrm_policy_walk_entry, all); | 851 | x = list_first_entry(&net->xfrm.policy_all, struct xfrm_policy_walk_entry, all); |
885 | else | 852 | else |
886 | x = list_entry(&walk->walk.all, struct xfrm_policy_walk_entry, all); | 853 | x = list_entry(&walk->walk.all, struct xfrm_policy_walk_entry, all); |
887 | list_for_each_entry_from(x, &xfrm_policy_all, all) { | 854 | list_for_each_entry_from(x, &net->xfrm.policy_all, all) { |
888 | if (x->dead) | 855 | if (x->dead) |
889 | continue; | 856 | continue; |
890 | pol = container_of(x, struct xfrm_policy, walk); | 857 | pol = container_of(x, struct xfrm_policy, walk); |
@@ -953,7 +920,8 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl, | |||
953 | return ret; | 920 | return ret; |
954 | } | 921 | } |
955 | 922 | ||
956 | static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, | 923 | static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type, |
924 | struct flowi *fl, | ||
957 | u16 family, u8 dir) | 925 | u16 family, u8 dir) |
958 | { | 926 | { |
959 | int err; | 927 | int err; |
@@ -969,7 +937,7 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, | |||
969 | return NULL; | 937 | return NULL; |
970 | 938 | ||
971 | read_lock_bh(&xfrm_policy_lock); | 939 | read_lock_bh(&xfrm_policy_lock); |
972 | chain = policy_hash_direct(daddr, saddr, family, dir); | 940 | chain = policy_hash_direct(net, daddr, saddr, family, dir); |
973 | ret = NULL; | 941 | ret = NULL; |
974 | hlist_for_each_entry(pol, entry, chain, bydst) { | 942 | hlist_for_each_entry(pol, entry, chain, bydst) { |
975 | err = xfrm_policy_match(pol, fl, type, family, dir); | 943 | err = xfrm_policy_match(pol, fl, type, family, dir); |
@@ -986,7 +954,7 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, | |||
986 | break; | 954 | break; |
987 | } | 955 | } |
988 | } | 956 | } |
989 | chain = &xfrm_policy_inexact[dir]; | 957 | chain = &net->xfrm.policy_inexact[dir]; |
990 | hlist_for_each_entry(pol, entry, chain, bydst) { | 958 | hlist_for_each_entry(pol, entry, chain, bydst) { |
991 | err = xfrm_policy_match(pol, fl, type, family, dir); | 959 | err = xfrm_policy_match(pol, fl, type, family, dir); |
992 | if (err) { | 960 | if (err) { |
@@ -1009,14 +977,14 @@ fail: | |||
1009 | return ret; | 977 | return ret; |
1010 | } | 978 | } |
1011 | 979 | ||
1012 | static int xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, | 980 | static int xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family, |
1013 | void **objp, atomic_t **obj_refp) | 981 | u8 dir, void **objp, atomic_t **obj_refp) |
1014 | { | 982 | { |
1015 | struct xfrm_policy *pol; | 983 | struct xfrm_policy *pol; |
1016 | int err = 0; | 984 | int err = 0; |
1017 | 985 | ||
1018 | #ifdef CONFIG_XFRM_SUB_POLICY | 986 | #ifdef CONFIG_XFRM_SUB_POLICY |
1019 | pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir); | 987 | pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_SUB, fl, family, dir); |
1020 | if (IS_ERR(pol)) { | 988 | if (IS_ERR(pol)) { |
1021 | err = PTR_ERR(pol); | 989 | err = PTR_ERR(pol); |
1022 | pol = NULL; | 990 | pol = NULL; |
@@ -1024,7 +992,7 @@ static int xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, | |||
1024 | if (pol || err) | 992 | if (pol || err) |
1025 | goto end; | 993 | goto end; |
1026 | #endif | 994 | #endif |
1027 | pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir); | 995 | pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, fl, family, dir); |
1028 | if (IS_ERR(pol)) { | 996 | if (IS_ERR(pol)) { |
1029 | err = PTR_ERR(pol); | 997 | err = PTR_ERR(pol); |
1030 | pol = NULL; | 998 | pol = NULL; |
@@ -1083,29 +1051,32 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc | |||
1083 | 1051 | ||
1084 | static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) | 1052 | static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) |
1085 | { | 1053 | { |
1086 | struct hlist_head *chain = policy_hash_bysel(&pol->selector, | 1054 | struct net *net = xp_net(pol); |
1055 | struct hlist_head *chain = policy_hash_bysel(net, &pol->selector, | ||
1087 | pol->family, dir); | 1056 | pol->family, dir); |
1088 | 1057 | ||
1089 | list_add(&pol->walk.all, &xfrm_policy_all); | 1058 | list_add(&pol->walk.all, &net->xfrm.policy_all); |
1090 | hlist_add_head(&pol->bydst, chain); | 1059 | hlist_add_head(&pol->bydst, chain); |
1091 | hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index)); | 1060 | hlist_add_head(&pol->byidx, net->xfrm.policy_byidx+idx_hash(net, pol->index)); |
1092 | xfrm_policy_count[dir]++; | 1061 | net->xfrm.policy_count[dir]++; |
1093 | xfrm_pol_hold(pol); | 1062 | xfrm_pol_hold(pol); |
1094 | 1063 | ||
1095 | if (xfrm_bydst_should_resize(dir, NULL)) | 1064 | if (xfrm_bydst_should_resize(net, dir, NULL)) |
1096 | schedule_work(&xfrm_hash_work); | 1065 | schedule_work(&net->xfrm.policy_hash_work); |
1097 | } | 1066 | } |
1098 | 1067 | ||
1099 | static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, | 1068 | static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, |
1100 | int dir) | 1069 | int dir) |
1101 | { | 1070 | { |
1071 | struct net *net = xp_net(pol); | ||
1072 | |||
1102 | if (hlist_unhashed(&pol->bydst)) | 1073 | if (hlist_unhashed(&pol->bydst)) |
1103 | return NULL; | 1074 | return NULL; |
1104 | 1075 | ||
1105 | hlist_del(&pol->bydst); | 1076 | hlist_del(&pol->bydst); |
1106 | hlist_del(&pol->byidx); | 1077 | hlist_del(&pol->byidx); |
1107 | list_del(&pol->walk.all); | 1078 | list_del(&pol->walk.all); |
1108 | xfrm_policy_count[dir]--; | 1079 | net->xfrm.policy_count[dir]--; |
1109 | 1080 | ||
1110 | return pol; | 1081 | return pol; |
1111 | } | 1082 | } |
@@ -1127,6 +1098,7 @@ EXPORT_SYMBOL(xfrm_policy_delete); | |||
1127 | 1098 | ||
1128 | int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | 1099 | int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) |
1129 | { | 1100 | { |
1101 | struct net *net = xp_net(pol); | ||
1130 | struct xfrm_policy *old_pol; | 1102 | struct xfrm_policy *old_pol; |
1131 | 1103 | ||
1132 | #ifdef CONFIG_XFRM_SUB_POLICY | 1104 | #ifdef CONFIG_XFRM_SUB_POLICY |
@@ -1139,7 +1111,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | |||
1139 | sk->sk_policy[dir] = pol; | 1111 | sk->sk_policy[dir] = pol; |
1140 | if (pol) { | 1112 | if (pol) { |
1141 | pol->curlft.add_time = get_seconds(); | 1113 | pol->curlft.add_time = get_seconds(); |
1142 | pol->index = xfrm_gen_index(pol->type, XFRM_POLICY_MAX+dir); | 1114 | pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir); |
1143 | __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); | 1115 | __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); |
1144 | } | 1116 | } |
1145 | if (old_pol) | 1117 | if (old_pol) |
@@ -1154,7 +1126,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | |||
1154 | 1126 | ||
1155 | static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) | 1127 | static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) |
1156 | { | 1128 | { |
1157 | struct xfrm_policy *newp = xfrm_policy_alloc(GFP_ATOMIC); | 1129 | struct xfrm_policy *newp = xfrm_policy_alloc(xp_net(old), GFP_ATOMIC); |
1158 | 1130 | ||
1159 | if (newp) { | 1131 | if (newp) { |
1160 | newp->selector = old->selector; | 1132 | newp->selector = old->selector; |
@@ -1194,7 +1166,7 @@ int __xfrm_sk_clone_policy(struct sock *sk) | |||
1194 | } | 1166 | } |
1195 | 1167 | ||
1196 | static int | 1168 | static int |
1197 | xfrm_get_saddr(xfrm_address_t *local, xfrm_address_t *remote, | 1169 | xfrm_get_saddr(struct net *net, xfrm_address_t *local, xfrm_address_t *remote, |
1198 | unsigned short family) | 1170 | unsigned short family) |
1199 | { | 1171 | { |
1200 | int err; | 1172 | int err; |
@@ -1202,7 +1174,7 @@ xfrm_get_saddr(xfrm_address_t *local, xfrm_address_t *remote, | |||
1202 | 1174 | ||
1203 | if (unlikely(afinfo == NULL)) | 1175 | if (unlikely(afinfo == NULL)) |
1204 | return -EINVAL; | 1176 | return -EINVAL; |
1205 | err = afinfo->get_saddr(local, remote); | 1177 | err = afinfo->get_saddr(net, local, remote); |
1206 | xfrm_policy_put_afinfo(afinfo); | 1178 | xfrm_policy_put_afinfo(afinfo); |
1207 | return err; | 1179 | return err; |
1208 | } | 1180 | } |
@@ -1214,6 +1186,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl, | |||
1214 | struct xfrm_state **xfrm, | 1186 | struct xfrm_state **xfrm, |
1215 | unsigned short family) | 1187 | unsigned short family) |
1216 | { | 1188 | { |
1189 | struct net *net = xp_net(policy); | ||
1217 | int nx; | 1190 | int nx; |
1218 | int i, error; | 1191 | int i, error; |
1219 | xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family); | 1192 | xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family); |
@@ -1232,7 +1205,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl, | |||
1232 | local = &tmpl->saddr; | 1205 | local = &tmpl->saddr; |
1233 | family = tmpl->encap_family; | 1206 | family = tmpl->encap_family; |
1234 | if (xfrm_addr_any(local, family)) { | 1207 | if (xfrm_addr_any(local, family)) { |
1235 | error = xfrm_get_saddr(&tmp, remote, family); | 1208 | error = xfrm_get_saddr(net, &tmp, remote, family); |
1236 | if (error) | 1209 | if (error) |
1237 | goto fail; | 1210 | goto fail; |
1238 | local = &tmp; | 1211 | local = &tmp; |
@@ -1546,7 +1519,7 @@ static int stale_bundle(struct dst_entry *dst); | |||
1546 | * At the moment we eat a raw IP route. Mostly to speed up lookups | 1519 | * At the moment we eat a raw IP route. Mostly to speed up lookups |
1547 | * on interfaces with disabled IPsec. | 1520 | * on interfaces with disabled IPsec. |
1548 | */ | 1521 | */ |
1549 | int __xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, | 1522 | int __xfrm_lookup(struct net *net, struct dst_entry **dst_p, struct flowi *fl, |
1550 | struct sock *sk, int flags) | 1523 | struct sock *sk, int flags) |
1551 | { | 1524 | { |
1552 | struct xfrm_policy *policy; | 1525 | struct xfrm_policy *policy; |
@@ -1576,7 +1549,7 @@ restart: | |||
1576 | policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); | 1549 | policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); |
1577 | err = PTR_ERR(policy); | 1550 | err = PTR_ERR(policy); |
1578 | if (IS_ERR(policy)) { | 1551 | if (IS_ERR(policy)) { |
1579 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR); | 1552 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); |
1580 | goto dropdst; | 1553 | goto dropdst; |
1581 | } | 1554 | } |
1582 | } | 1555 | } |
@@ -1584,14 +1557,14 @@ restart: | |||
1584 | if (!policy) { | 1557 | if (!policy) { |
1585 | /* To accelerate a bit... */ | 1558 | /* To accelerate a bit... */ |
1586 | if ((dst_orig->flags & DST_NOXFRM) || | 1559 | if ((dst_orig->flags & DST_NOXFRM) || |
1587 | !xfrm_policy_count[XFRM_POLICY_OUT]) | 1560 | !net->xfrm.policy_count[XFRM_POLICY_OUT]) |
1588 | goto nopol; | 1561 | goto nopol; |
1589 | 1562 | ||
1590 | policy = flow_cache_lookup(fl, dst_orig->ops->family, | 1563 | policy = flow_cache_lookup(net, fl, dst_orig->ops->family, |
1591 | dir, xfrm_policy_lookup); | 1564 | dir, xfrm_policy_lookup); |
1592 | err = PTR_ERR(policy); | 1565 | err = PTR_ERR(policy); |
1593 | if (IS_ERR(policy)) { | 1566 | if (IS_ERR(policy)) { |
1594 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR); | 1567 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); |
1595 | goto dropdst; | 1568 | goto dropdst; |
1596 | } | 1569 | } |
1597 | } | 1570 | } |
@@ -1614,7 +1587,7 @@ restart: | |||
1614 | default: | 1587 | default: |
1615 | case XFRM_POLICY_BLOCK: | 1588 | case XFRM_POLICY_BLOCK: |
1616 | /* Prohibit the flow */ | 1589 | /* Prohibit the flow */ |
1617 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK); | 1590 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLBLOCK); |
1618 | err = -EPERM; | 1591 | err = -EPERM; |
1619 | goto error; | 1592 | goto error; |
1620 | 1593 | ||
@@ -1634,7 +1607,7 @@ restart: | |||
1634 | */ | 1607 | */ |
1635 | dst = xfrm_find_bundle(fl, policy, family); | 1608 | dst = xfrm_find_bundle(fl, policy, family); |
1636 | if (IS_ERR(dst)) { | 1609 | if (IS_ERR(dst)) { |
1637 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | 1610 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); |
1638 | err = PTR_ERR(dst); | 1611 | err = PTR_ERR(dst); |
1639 | goto error; | 1612 | goto error; |
1640 | } | 1613 | } |
@@ -1644,17 +1617,18 @@ restart: | |||
1644 | 1617 | ||
1645 | #ifdef CONFIG_XFRM_SUB_POLICY | 1618 | #ifdef CONFIG_XFRM_SUB_POLICY |
1646 | if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { | 1619 | if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { |
1647 | pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, | 1620 | pols[1] = xfrm_policy_lookup_bytype(net, |
1621 | XFRM_POLICY_TYPE_MAIN, | ||
1648 | fl, family, | 1622 | fl, family, |
1649 | XFRM_POLICY_OUT); | 1623 | XFRM_POLICY_OUT); |
1650 | if (pols[1]) { | 1624 | if (pols[1]) { |
1651 | if (IS_ERR(pols[1])) { | 1625 | if (IS_ERR(pols[1])) { |
1652 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR); | 1626 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); |
1653 | err = PTR_ERR(pols[1]); | 1627 | err = PTR_ERR(pols[1]); |
1654 | goto error; | 1628 | goto error; |
1655 | } | 1629 | } |
1656 | if (pols[1]->action == XFRM_POLICY_BLOCK) { | 1630 | if (pols[1]->action == XFRM_POLICY_BLOCK) { |
1657 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK); | 1631 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLBLOCK); |
1658 | err = -EPERM; | 1632 | err = -EPERM; |
1659 | goto error; | 1633 | goto error; |
1660 | } | 1634 | } |
@@ -1681,27 +1655,27 @@ restart: | |||
1681 | 1655 | ||
1682 | if (unlikely(nx<0)) { | 1656 | if (unlikely(nx<0)) { |
1683 | err = nx; | 1657 | err = nx; |
1684 | if (err == -EAGAIN && sysctl_xfrm_larval_drop) { | 1658 | if (err == -EAGAIN && net->xfrm.sysctl_larval_drop) { |
1685 | /* EREMOTE tells the caller to generate | 1659 | /* EREMOTE tells the caller to generate |
1686 | * a one-shot blackhole route. | 1660 | * a one-shot blackhole route. |
1687 | */ | 1661 | */ |
1688 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES); | 1662 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
1689 | xfrm_pol_put(policy); | 1663 | xfrm_pol_put(policy); |
1690 | return -EREMOTE; | 1664 | return -EREMOTE; |
1691 | } | 1665 | } |
1692 | if (err == -EAGAIN && (flags & XFRM_LOOKUP_WAIT)) { | 1666 | if (err == -EAGAIN && (flags & XFRM_LOOKUP_WAIT)) { |
1693 | DECLARE_WAITQUEUE(wait, current); | 1667 | DECLARE_WAITQUEUE(wait, current); |
1694 | 1668 | ||
1695 | add_wait_queue(&km_waitq, &wait); | 1669 | add_wait_queue(&net->xfrm.km_waitq, &wait); |
1696 | set_current_state(TASK_INTERRUPTIBLE); | 1670 | set_current_state(TASK_INTERRUPTIBLE); |
1697 | schedule(); | 1671 | schedule(); |
1698 | set_current_state(TASK_RUNNING); | 1672 | set_current_state(TASK_RUNNING); |
1699 | remove_wait_queue(&km_waitq, &wait); | 1673 | remove_wait_queue(&net->xfrm.km_waitq, &wait); |
1700 | 1674 | ||
1701 | nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); | 1675 | nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); |
1702 | 1676 | ||
1703 | if (nx == -EAGAIN && signal_pending(current)) { | 1677 | if (nx == -EAGAIN && signal_pending(current)) { |
1704 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES); | 1678 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
1705 | err = -ERESTART; | 1679 | err = -ERESTART; |
1706 | goto error; | 1680 | goto error; |
1707 | } | 1681 | } |
@@ -1713,7 +1687,7 @@ restart: | |||
1713 | err = nx; | 1687 | err = nx; |
1714 | } | 1688 | } |
1715 | if (err < 0) { | 1689 | if (err < 0) { |
1716 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES); | 1690 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
1717 | goto error; | 1691 | goto error; |
1718 | } | 1692 | } |
1719 | } | 1693 | } |
@@ -1726,7 +1700,7 @@ restart: | |||
1726 | dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig); | 1700 | dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig); |
1727 | err = PTR_ERR(dst); | 1701 | err = PTR_ERR(dst); |
1728 | if (IS_ERR(dst)) { | 1702 | if (IS_ERR(dst)) { |
1729 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLEGENERROR); | 1703 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLEGENERROR); |
1730 | goto error; | 1704 | goto error; |
1731 | } | 1705 | } |
1732 | 1706 | ||
@@ -1747,9 +1721,9 @@ restart: | |||
1747 | dst_free(dst); | 1721 | dst_free(dst); |
1748 | 1722 | ||
1749 | if (pol_dead) | 1723 | if (pol_dead) |
1750 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLDEAD); | 1724 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLDEAD); |
1751 | else | 1725 | else |
1752 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | 1726 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); |
1753 | err = -EHOSTUNREACH; | 1727 | err = -EHOSTUNREACH; |
1754 | goto error; | 1728 | goto error; |
1755 | } | 1729 | } |
@@ -1761,7 +1735,7 @@ restart: | |||
1761 | if (unlikely(err)) { | 1735 | if (unlikely(err)) { |
1762 | write_unlock_bh(&policy->lock); | 1736 | write_unlock_bh(&policy->lock); |
1763 | dst_free(dst); | 1737 | dst_free(dst); |
1764 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | 1738 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); |
1765 | goto error; | 1739 | goto error; |
1766 | } | 1740 | } |
1767 | 1741 | ||
@@ -1790,10 +1764,10 @@ nopol: | |||
1790 | } | 1764 | } |
1791 | EXPORT_SYMBOL(__xfrm_lookup); | 1765 | EXPORT_SYMBOL(__xfrm_lookup); |
1792 | 1766 | ||
1793 | int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, | 1767 | int xfrm_lookup(struct net *net, struct dst_entry **dst_p, struct flowi *fl, |
1794 | struct sock *sk, int flags) | 1768 | struct sock *sk, int flags) |
1795 | { | 1769 | { |
1796 | int err = __xfrm_lookup(dst_p, fl, sk, flags); | 1770 | int err = __xfrm_lookup(net, dst_p, fl, sk, flags); |
1797 | 1771 | ||
1798 | if (err == -EREMOTE) { | 1772 | if (err == -EREMOTE) { |
1799 | dst_release(*dst_p); | 1773 | dst_release(*dst_p); |
@@ -1901,6 +1875,7 @@ static inline int secpath_has_nontransport(struct sec_path *sp, int k, int *idxp | |||
1901 | int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | 1875 | int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, |
1902 | unsigned short family) | 1876 | unsigned short family) |
1903 | { | 1877 | { |
1878 | struct net *net = dev_net(skb->dev); | ||
1904 | struct xfrm_policy *pol; | 1879 | struct xfrm_policy *pol; |
1905 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; | 1880 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; |
1906 | int npols = 0; | 1881 | int npols = 0; |
@@ -1916,7 +1891,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1916 | fl_dir = policy_to_flow_dir(dir); | 1891 | fl_dir = policy_to_flow_dir(dir); |
1917 | 1892 | ||
1918 | if (__xfrm_decode_session(skb, &fl, family, reverse) < 0) { | 1893 | if (__xfrm_decode_session(skb, &fl, family, reverse) < 0) { |
1919 | XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR); | 1894 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
1920 | return 0; | 1895 | return 0; |
1921 | } | 1896 | } |
1922 | 1897 | ||
@@ -1929,7 +1904,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1929 | for (i=skb->sp->len-1; i>=0; i--) { | 1904 | for (i=skb->sp->len-1; i>=0; i--) { |
1930 | struct xfrm_state *x = skb->sp->xvec[i]; | 1905 | struct xfrm_state *x = skb->sp->xvec[i]; |
1931 | if (!xfrm_selector_match(&x->sel, &fl, family)) { | 1906 | if (!xfrm_selector_match(&x->sel, &fl, family)) { |
1932 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMISMATCH); | 1907 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMISMATCH); |
1933 | return 0; | 1908 | return 0; |
1934 | } | 1909 | } |
1935 | } | 1910 | } |
@@ -1939,24 +1914,24 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1939 | if (sk && sk->sk_policy[dir]) { | 1914 | if (sk && sk->sk_policy[dir]) { |
1940 | pol = xfrm_sk_policy_lookup(sk, dir, &fl); | 1915 | pol = xfrm_sk_policy_lookup(sk, dir, &fl); |
1941 | if (IS_ERR(pol)) { | 1916 | if (IS_ERR(pol)) { |
1942 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR); | 1917 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); |
1943 | return 0; | 1918 | return 0; |
1944 | } | 1919 | } |
1945 | } | 1920 | } |
1946 | 1921 | ||
1947 | if (!pol) | 1922 | if (!pol) |
1948 | pol = flow_cache_lookup(&fl, family, fl_dir, | 1923 | pol = flow_cache_lookup(net, &fl, family, fl_dir, |
1949 | xfrm_policy_lookup); | 1924 | xfrm_policy_lookup); |
1950 | 1925 | ||
1951 | if (IS_ERR(pol)) { | 1926 | if (IS_ERR(pol)) { |
1952 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR); | 1927 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); |
1953 | return 0; | 1928 | return 0; |
1954 | } | 1929 | } |
1955 | 1930 | ||
1956 | if (!pol) { | 1931 | if (!pol) { |
1957 | if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { | 1932 | if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { |
1958 | xfrm_secpath_reject(xerr_idx, skb, &fl); | 1933 | xfrm_secpath_reject(xerr_idx, skb, &fl); |
1959 | XFRM_INC_STATS(LINUX_MIB_XFRMINNOPOLS); | 1934 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS); |
1960 | return 0; | 1935 | return 0; |
1961 | } | 1936 | } |
1962 | return 1; | 1937 | return 1; |
@@ -1968,12 +1943,12 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1968 | npols ++; | 1943 | npols ++; |
1969 | #ifdef CONFIG_XFRM_SUB_POLICY | 1944 | #ifdef CONFIG_XFRM_SUB_POLICY |
1970 | if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { | 1945 | if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { |
1971 | pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, | 1946 | pols[1] = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, |
1972 | &fl, family, | 1947 | &fl, family, |
1973 | XFRM_POLICY_IN); | 1948 | XFRM_POLICY_IN); |
1974 | if (pols[1]) { | 1949 | if (pols[1]) { |
1975 | if (IS_ERR(pols[1])) { | 1950 | if (IS_ERR(pols[1])) { |
1976 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR); | 1951 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); |
1977 | return 0; | 1952 | return 0; |
1978 | } | 1953 | } |
1979 | pols[1]->curlft.use_time = get_seconds(); | 1954 | pols[1]->curlft.use_time = get_seconds(); |
@@ -1997,11 +1972,11 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1997 | for (pi = 0; pi < npols; pi++) { | 1972 | for (pi = 0; pi < npols; pi++) { |
1998 | if (pols[pi] != pol && | 1973 | if (pols[pi] != pol && |
1999 | pols[pi]->action != XFRM_POLICY_ALLOW) { | 1974 | pols[pi]->action != XFRM_POLICY_ALLOW) { |
2000 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK); | 1975 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK); |
2001 | goto reject; | 1976 | goto reject; |
2002 | } | 1977 | } |
2003 | if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) { | 1978 | if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) { |
2004 | XFRM_INC_STATS(LINUX_MIB_XFRMINBUFFERERROR); | 1979 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); |
2005 | goto reject_error; | 1980 | goto reject_error; |
2006 | } | 1981 | } |
2007 | for (i = 0; i < pols[pi]->xfrm_nr; i++) | 1982 | for (i = 0; i < pols[pi]->xfrm_nr; i++) |
@@ -2025,20 +2000,20 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
2025 | if (k < -1) | 2000 | if (k < -1) |
2026 | /* "-2 - errored_index" returned */ | 2001 | /* "-2 - errored_index" returned */ |
2027 | xerr_idx = -(2+k); | 2002 | xerr_idx = -(2+k); |
2028 | XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH); | 2003 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINTMPLMISMATCH); |
2029 | goto reject; | 2004 | goto reject; |
2030 | } | 2005 | } |
2031 | } | 2006 | } |
2032 | 2007 | ||
2033 | if (secpath_has_nontransport(sp, k, &xerr_idx)) { | 2008 | if (secpath_has_nontransport(sp, k, &xerr_idx)) { |
2034 | XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH); | 2009 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINTMPLMISMATCH); |
2035 | goto reject; | 2010 | goto reject; |
2036 | } | 2011 | } |
2037 | 2012 | ||
2038 | xfrm_pols_put(pols, npols); | 2013 | xfrm_pols_put(pols, npols); |
2039 | return 1; | 2014 | return 1; |
2040 | } | 2015 | } |
2041 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK); | 2016 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK); |
2042 | 2017 | ||
2043 | reject: | 2018 | reject: |
2044 | xfrm_secpath_reject(xerr_idx, skb, &fl); | 2019 | xfrm_secpath_reject(xerr_idx, skb, &fl); |
@@ -2050,15 +2025,16 @@ EXPORT_SYMBOL(__xfrm_policy_check); | |||
2050 | 2025 | ||
2051 | int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) | 2026 | int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) |
2052 | { | 2027 | { |
2028 | struct net *net = dev_net(skb->dev); | ||
2053 | struct flowi fl; | 2029 | struct flowi fl; |
2054 | 2030 | ||
2055 | if (xfrm_decode_session(skb, &fl, family) < 0) { | 2031 | if (xfrm_decode_session(skb, &fl, family) < 0) { |
2056 | /* XXX: we should have something like FWDHDRERROR here. */ | 2032 | /* XXX: we should have something like FWDHDRERROR here. */ |
2057 | XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR); | 2033 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
2058 | return 0; | 2034 | return 0; |
2059 | } | 2035 | } |
2060 | 2036 | ||
2061 | return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0; | 2037 | return xfrm_lookup(net, &skb->dst, &fl, NULL, 0) == 0; |
2062 | } | 2038 | } |
2063 | EXPORT_SYMBOL(__xfrm_route_forward); | 2039 | EXPORT_SYMBOL(__xfrm_route_forward); |
2064 | 2040 | ||
@@ -2142,7 +2118,7 @@ static void prune_one_bundle(struct xfrm_policy *pol, int (*func)(struct dst_ent | |||
2142 | write_unlock(&pol->lock); | 2118 | write_unlock(&pol->lock); |
2143 | } | 2119 | } |
2144 | 2120 | ||
2145 | static void xfrm_prune_bundles(int (*func)(struct dst_entry *)) | 2121 | static void xfrm_prune_bundles(struct net *net, int (*func)(struct dst_entry *)) |
2146 | { | 2122 | { |
2147 | struct dst_entry *gc_list = NULL; | 2123 | struct dst_entry *gc_list = NULL; |
2148 | int dir; | 2124 | int dir; |
@@ -2155,11 +2131,11 @@ static void xfrm_prune_bundles(int (*func)(struct dst_entry *)) | |||
2155 | int i; | 2131 | int i; |
2156 | 2132 | ||
2157 | hlist_for_each_entry(pol, entry, | 2133 | hlist_for_each_entry(pol, entry, |
2158 | &xfrm_policy_inexact[dir], bydst) | 2134 | &net->xfrm.policy_inexact[dir], bydst) |
2159 | prune_one_bundle(pol, func, &gc_list); | 2135 | prune_one_bundle(pol, func, &gc_list); |
2160 | 2136 | ||
2161 | table = xfrm_policy_bydst[dir].table; | 2137 | table = net->xfrm.policy_bydst[dir].table; |
2162 | for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { | 2138 | for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) { |
2163 | hlist_for_each_entry(pol, entry, table + i, bydst) | 2139 | hlist_for_each_entry(pol, entry, table + i, bydst) |
2164 | prune_one_bundle(pol, func, &gc_list); | 2140 | prune_one_bundle(pol, func, &gc_list); |
2165 | } | 2141 | } |
@@ -2178,14 +2154,14 @@ static int unused_bundle(struct dst_entry *dst) | |||
2178 | return !atomic_read(&dst->__refcnt); | 2154 | return !atomic_read(&dst->__refcnt); |
2179 | } | 2155 | } |
2180 | 2156 | ||
2181 | static void __xfrm_garbage_collect(void) | 2157 | static void __xfrm_garbage_collect(struct net *net) |
2182 | { | 2158 | { |
2183 | xfrm_prune_bundles(unused_bundle); | 2159 | xfrm_prune_bundles(net, unused_bundle); |
2184 | } | 2160 | } |
2185 | 2161 | ||
2186 | static int xfrm_flush_bundles(void) | 2162 | static int xfrm_flush_bundles(struct net *net) |
2187 | { | 2163 | { |
2188 | xfrm_prune_bundles(stale_bundle); | 2164 | xfrm_prune_bundles(net, stale_bundle); |
2189 | return 0; | 2165 | return 0; |
2190 | } | 2166 | } |
2191 | 2167 | ||
@@ -2371,38 +2347,54 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void | |||
2371 | { | 2347 | { |
2372 | struct net_device *dev = ptr; | 2348 | struct net_device *dev = ptr; |
2373 | 2349 | ||
2374 | if (!net_eq(dev_net(dev), &init_net)) | ||
2375 | return NOTIFY_DONE; | ||
2376 | |||
2377 | switch (event) { | 2350 | switch (event) { |
2378 | case NETDEV_DOWN: | 2351 | case NETDEV_DOWN: |
2379 | xfrm_flush_bundles(); | 2352 | xfrm_flush_bundles(dev_net(dev)); |
2380 | } | 2353 | } |
2381 | return NOTIFY_DONE; | 2354 | return NOTIFY_DONE; |
2382 | } | 2355 | } |
2383 | 2356 | ||
2384 | static struct notifier_block xfrm_dev_notifier = { | 2357 | static struct notifier_block xfrm_dev_notifier = { |
2385 | xfrm_dev_event, | 2358 | .notifier_call = xfrm_dev_event, |
2386 | NULL, | ||
2387 | 0 | ||
2388 | }; | 2359 | }; |
2389 | 2360 | ||
2390 | #ifdef CONFIG_XFRM_STATISTICS | 2361 | #ifdef CONFIG_XFRM_STATISTICS |
2391 | static int __init xfrm_statistics_init(void) | 2362 | static int __net_init xfrm_statistics_init(struct net *net) |
2392 | { | 2363 | { |
2393 | if (snmp_mib_init((void **)xfrm_statistics, | 2364 | int rv; |
2365 | |||
2366 | if (snmp_mib_init((void **)net->mib.xfrm_statistics, | ||
2394 | sizeof(struct linux_xfrm_mib)) < 0) | 2367 | sizeof(struct linux_xfrm_mib)) < 0) |
2395 | return -ENOMEM; | 2368 | return -ENOMEM; |
2369 | rv = xfrm_proc_init(net); | ||
2370 | if (rv < 0) | ||
2371 | snmp_mib_free((void **)net->mib.xfrm_statistics); | ||
2372 | return rv; | ||
2373 | } | ||
2374 | |||
2375 | static void xfrm_statistics_fini(struct net *net) | ||
2376 | { | ||
2377 | xfrm_proc_fini(net); | ||
2378 | snmp_mib_free((void **)net->mib.xfrm_statistics); | ||
2379 | } | ||
2380 | #else | ||
2381 | static int __net_init xfrm_statistics_init(struct net *net) | ||
2382 | { | ||
2396 | return 0; | 2383 | return 0; |
2397 | } | 2384 | } |
2385 | |||
2386 | static void xfrm_statistics_fini(struct net *net) | ||
2387 | { | ||
2388 | } | ||
2398 | #endif | 2389 | #endif |
2399 | 2390 | ||
2400 | static void __init xfrm_policy_init(void) | 2391 | static int __net_init xfrm_policy_init(struct net *net) |
2401 | { | 2392 | { |
2402 | unsigned int hmask, sz; | 2393 | unsigned int hmask, sz; |
2403 | int dir; | 2394 | int dir; |
2404 | 2395 | ||
2405 | xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache", | 2396 | if (net_eq(net, &init_net)) |
2397 | xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache", | ||
2406 | sizeof(struct xfrm_dst), | 2398 | sizeof(struct xfrm_dst), |
2407 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, | 2399 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, |
2408 | NULL); | 2400 | NULL); |
@@ -2410,39 +2402,124 @@ static void __init xfrm_policy_init(void) | |||
2410 | hmask = 8 - 1; | 2402 | hmask = 8 - 1; |
2411 | sz = (hmask+1) * sizeof(struct hlist_head); | 2403 | sz = (hmask+1) * sizeof(struct hlist_head); |
2412 | 2404 | ||
2413 | xfrm_policy_byidx = xfrm_hash_alloc(sz); | 2405 | net->xfrm.policy_byidx = xfrm_hash_alloc(sz); |
2414 | xfrm_idx_hmask = hmask; | 2406 | if (!net->xfrm.policy_byidx) |
2415 | if (!xfrm_policy_byidx) | 2407 | goto out_byidx; |
2416 | panic("XFRM: failed to allocate byidx hash\n"); | 2408 | net->xfrm.policy_idx_hmask = hmask; |
2417 | 2409 | ||
2418 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { | 2410 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { |
2419 | struct xfrm_policy_hash *htab; | 2411 | struct xfrm_policy_hash *htab; |
2420 | 2412 | ||
2421 | INIT_HLIST_HEAD(&xfrm_policy_inexact[dir]); | 2413 | net->xfrm.policy_count[dir] = 0; |
2414 | INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]); | ||
2422 | 2415 | ||
2423 | htab = &xfrm_policy_bydst[dir]; | 2416 | htab = &net->xfrm.policy_bydst[dir]; |
2424 | htab->table = xfrm_hash_alloc(sz); | 2417 | htab->table = xfrm_hash_alloc(sz); |
2425 | htab->hmask = hmask; | ||
2426 | if (!htab->table) | 2418 | if (!htab->table) |
2427 | panic("XFRM: failed to allocate bydst hash\n"); | 2419 | goto out_bydst; |
2420 | htab->hmask = hmask; | ||
2428 | } | 2421 | } |
2429 | 2422 | ||
2430 | INIT_LIST_HEAD(&xfrm_policy_all); | 2423 | INIT_LIST_HEAD(&net->xfrm.policy_all); |
2431 | INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task); | 2424 | INIT_WORK(&net->xfrm.policy_hash_work, xfrm_hash_resize); |
2432 | register_netdevice_notifier(&xfrm_dev_notifier); | 2425 | if (net_eq(net, &init_net)) |
2426 | register_netdevice_notifier(&xfrm_dev_notifier); | ||
2427 | return 0; | ||
2428 | |||
2429 | out_bydst: | ||
2430 | for (dir--; dir >= 0; dir--) { | ||
2431 | struct xfrm_policy_hash *htab; | ||
2432 | |||
2433 | htab = &net->xfrm.policy_bydst[dir]; | ||
2434 | xfrm_hash_free(htab->table, sz); | ||
2435 | } | ||
2436 | xfrm_hash_free(net->xfrm.policy_byidx, sz); | ||
2437 | out_byidx: | ||
2438 | return -ENOMEM; | ||
2433 | } | 2439 | } |
2434 | 2440 | ||
2435 | void __init xfrm_init(void) | 2441 | static void xfrm_policy_fini(struct net *net) |
2436 | { | 2442 | { |
2437 | #ifdef CONFIG_XFRM_STATISTICS | 2443 | struct xfrm_audit audit_info; |
2438 | xfrm_statistics_init(); | 2444 | unsigned int sz; |
2445 | int dir; | ||
2446 | |||
2447 | flush_work(&net->xfrm.policy_hash_work); | ||
2448 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
2449 | audit_info.loginuid = -1; | ||
2450 | audit_info.sessionid = -1; | ||
2451 | audit_info.secid = 0; | ||
2452 | xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, &audit_info); | ||
2439 | #endif | 2453 | #endif |
2440 | xfrm_state_init(); | 2454 | audit_info.loginuid = -1; |
2441 | xfrm_policy_init(); | 2455 | audit_info.sessionid = -1; |
2456 | audit_info.secid = 0; | ||
2457 | xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); | ||
2458 | flush_work(&xfrm_policy_gc_work); | ||
2459 | |||
2460 | WARN_ON(!list_empty(&net->xfrm.policy_all)); | ||
2461 | |||
2462 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { | ||
2463 | struct xfrm_policy_hash *htab; | ||
2464 | |||
2465 | WARN_ON(!hlist_empty(&net->xfrm.policy_inexact[dir])); | ||
2466 | |||
2467 | htab = &net->xfrm.policy_bydst[dir]; | ||
2468 | sz = (htab->hmask + 1); | ||
2469 | WARN_ON(!hlist_empty(htab->table)); | ||
2470 | xfrm_hash_free(htab->table, sz); | ||
2471 | } | ||
2472 | |||
2473 | sz = (net->xfrm.policy_idx_hmask + 1) * sizeof(struct hlist_head); | ||
2474 | WARN_ON(!hlist_empty(net->xfrm.policy_byidx)); | ||
2475 | xfrm_hash_free(net->xfrm.policy_byidx, sz); | ||
2476 | } | ||
2477 | |||
2478 | static int __net_init xfrm_net_init(struct net *net) | ||
2479 | { | ||
2480 | int rv; | ||
2481 | |||
2482 | rv = xfrm_statistics_init(net); | ||
2483 | if (rv < 0) | ||
2484 | goto out_statistics; | ||
2485 | rv = xfrm_state_init(net); | ||
2486 | if (rv < 0) | ||
2487 | goto out_state; | ||
2488 | rv = xfrm_policy_init(net); | ||
2489 | if (rv < 0) | ||
2490 | goto out_policy; | ||
2491 | rv = xfrm_sysctl_init(net); | ||
2492 | if (rv < 0) | ||
2493 | goto out_sysctl; | ||
2494 | return 0; | ||
2495 | |||
2496 | out_sysctl: | ||
2497 | xfrm_policy_fini(net); | ||
2498 | out_policy: | ||
2499 | xfrm_state_fini(net); | ||
2500 | out_state: | ||
2501 | xfrm_statistics_fini(net); | ||
2502 | out_statistics: | ||
2503 | return rv; | ||
2504 | } | ||
2505 | |||
2506 | static void __net_exit xfrm_net_exit(struct net *net) | ||
2507 | { | ||
2508 | xfrm_sysctl_fini(net); | ||
2509 | xfrm_policy_fini(net); | ||
2510 | xfrm_state_fini(net); | ||
2511 | xfrm_statistics_fini(net); | ||
2512 | } | ||
2513 | |||
2514 | static struct pernet_operations __net_initdata xfrm_net_ops = { | ||
2515 | .init = xfrm_net_init, | ||
2516 | .exit = xfrm_net_exit, | ||
2517 | }; | ||
2518 | |||
2519 | void __init xfrm_init(void) | ||
2520 | { | ||
2521 | register_pernet_subsys(&xfrm_net_ops); | ||
2442 | xfrm_input_init(); | 2522 | xfrm_input_init(); |
2443 | #ifdef CONFIG_XFRM_STATISTICS | ||
2444 | xfrm_proc_init(); | ||
2445 | #endif | ||
2446 | } | 2523 | } |
2447 | 2524 | ||
2448 | #ifdef CONFIG_AUDITSYSCALL | 2525 | #ifdef CONFIG_AUDITSYSCALL |
@@ -2458,25 +2535,21 @@ static void xfrm_audit_common_policyinfo(struct xfrm_policy *xp, | |||
2458 | 2535 | ||
2459 | switch(sel->family) { | 2536 | switch(sel->family) { |
2460 | case AF_INET: | 2537 | case AF_INET: |
2461 | audit_log_format(audit_buf, " src=" NIPQUAD_FMT, | 2538 | audit_log_format(audit_buf, " src=%pI4", &sel->saddr.a4); |
2462 | NIPQUAD(sel->saddr.a4)); | ||
2463 | if (sel->prefixlen_s != 32) | 2539 | if (sel->prefixlen_s != 32) |
2464 | audit_log_format(audit_buf, " src_prefixlen=%d", | 2540 | audit_log_format(audit_buf, " src_prefixlen=%d", |
2465 | sel->prefixlen_s); | 2541 | sel->prefixlen_s); |
2466 | audit_log_format(audit_buf, " dst=" NIPQUAD_FMT, | 2542 | audit_log_format(audit_buf, " dst=%pI4", &sel->daddr.a4); |
2467 | NIPQUAD(sel->daddr.a4)); | ||
2468 | if (sel->prefixlen_d != 32) | 2543 | if (sel->prefixlen_d != 32) |
2469 | audit_log_format(audit_buf, " dst_prefixlen=%d", | 2544 | audit_log_format(audit_buf, " dst_prefixlen=%d", |
2470 | sel->prefixlen_d); | 2545 | sel->prefixlen_d); |
2471 | break; | 2546 | break; |
2472 | case AF_INET6: | 2547 | case AF_INET6: |
2473 | audit_log_format(audit_buf, " src=" NIP6_FMT, | 2548 | audit_log_format(audit_buf, " src=%pI6", sel->saddr.a6); |
2474 | NIP6(*(struct in6_addr *)sel->saddr.a6)); | ||
2475 | if (sel->prefixlen_s != 128) | 2549 | if (sel->prefixlen_s != 128) |
2476 | audit_log_format(audit_buf, " src_prefixlen=%d", | 2550 | audit_log_format(audit_buf, " src_prefixlen=%d", |
2477 | sel->prefixlen_s); | 2551 | sel->prefixlen_s); |
2478 | audit_log_format(audit_buf, " dst=" NIP6_FMT, | 2552 | audit_log_format(audit_buf, " dst=%pI6", sel->daddr.a6); |
2479 | NIP6(*(struct in6_addr *)sel->daddr.a6)); | ||
2480 | if (sel->prefixlen_d != 128) | 2553 | if (sel->prefixlen_d != 128) |
2481 | audit_log_format(audit_buf, " dst_prefixlen=%d", | 2554 | audit_log_format(audit_buf, " dst_prefixlen=%d", |
2482 | sel->prefixlen_d); | 2555 | sel->prefixlen_d); |
@@ -2546,7 +2619,7 @@ static struct xfrm_policy * xfrm_migrate_policy_find(struct xfrm_selector *sel, | |||
2546 | u32 priority = ~0U; | 2619 | u32 priority = ~0U; |
2547 | 2620 | ||
2548 | read_lock_bh(&xfrm_policy_lock); | 2621 | read_lock_bh(&xfrm_policy_lock); |
2549 | chain = policy_hash_direct(&sel->daddr, &sel->saddr, sel->family, dir); | 2622 | chain = policy_hash_direct(&init_net, &sel->daddr, &sel->saddr, sel->family, dir); |
2550 | hlist_for_each_entry(pol, entry, chain, bydst) { | 2623 | hlist_for_each_entry(pol, entry, chain, bydst) { |
2551 | if (xfrm_migrate_selector_match(sel, &pol->selector) && | 2624 | if (xfrm_migrate_selector_match(sel, &pol->selector) && |
2552 | pol->type == type) { | 2625 | pol->type == type) { |
@@ -2555,7 +2628,7 @@ static struct xfrm_policy * xfrm_migrate_policy_find(struct xfrm_selector *sel, | |||
2555 | break; | 2628 | break; |
2556 | } | 2629 | } |
2557 | } | 2630 | } |
2558 | chain = &xfrm_policy_inexact[dir]; | 2631 | chain = &init_net.xfrm.policy_inexact[dir]; |
2559 | hlist_for_each_entry(pol, entry, chain, bydst) { | 2632 | hlist_for_each_entry(pol, entry, chain, bydst) { |
2560 | if (xfrm_migrate_selector_match(sel, &pol->selector) && | 2633 | if (xfrm_migrate_selector_match(sel, &pol->selector) && |
2561 | pol->type == type && | 2634 | pol->type == type && |