Commit 1785e8f473082aa60d62c7165856cf6484077b99
Committed by
Jozsef Kadlecsik
1 parent
3fd986b3d9
netfiler: ipset: Add net namespace for ipset
This patch adds netns support for ipset. Major changes were made in ip_set_core.c and ip_set.h. Global variables are moved to per net namespace. Added initialization code and the destruction of the network namespace ipset subsystem. In the prototypes of public functions ip_set_* added parameter "struct net*". The remaining corrections related to the change prototypes of public functions ip_set_*. The patch for git://git.netfilter.org/ipset.git commit 6a4ec96c0b8caac5c35474e40e319704d92ca347 Signed-off-by: Vitaly Lavrov <lve@guap.ru> Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Showing 9 changed files with 245 additions and 148 deletions Side-by-side Diff
- include/linux/netfilter/ipset/ip_set.h
- net/netfilter/ipset/ip_set_bitmap_ip.c
- net/netfilter/ipset/ip_set_bitmap_ipmac.c
- net/netfilter/ipset/ip_set_bitmap_port.c
- net/netfilter/ipset/ip_set_core.c
- net/netfilter/ipset/ip_set_hash_gen.h
- net/netfilter/ipset/ip_set_list_set.c
- net/netfilter/xt_set.c
- net/sched/em_ipset.c
include/linux/netfilter/ipset/ip_set.h
... | ... | @@ -184,7 +184,8 @@ |
184 | 184 | u8 revision_min, revision_max; |
185 | 185 | |
186 | 186 | /* Create set */ |
187 | - int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags); | |
187 | + int (*create)(struct net *net, struct ip_set *set, | |
188 | + struct nlattr *tb[], u32 flags); | |
188 | 189 | |
189 | 190 | /* Attribute policies */ |
190 | 191 | const struct nla_policy create_policy[IPSET_ATTR_CREATE_MAX + 1]; |
... | ... | @@ -316,12 +317,13 @@ |
316 | 317 | } |
317 | 318 | |
318 | 319 | /* register and unregister set references */ |
319 | -extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set); | |
320 | -extern void ip_set_put_byindex(ip_set_id_t index); | |
321 | -extern const char *ip_set_name_byindex(ip_set_id_t index); | |
322 | -extern ip_set_id_t ip_set_nfnl_get(const char *name); | |
323 | -extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index); | |
324 | -extern void ip_set_nfnl_put(ip_set_id_t index); | |
320 | +extern ip_set_id_t ip_set_get_byname(struct net *net, | |
321 | + const char *name, struct ip_set **set); | |
322 | +extern void ip_set_put_byindex(struct net *net, ip_set_id_t index); | |
323 | +extern const char *ip_set_name_byindex(struct net *net, ip_set_id_t index); | |
324 | +extern ip_set_id_t ip_set_nfnl_get(struct net *net, const char *name); | |
325 | +extern ip_set_id_t ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index); | |
326 | +extern void ip_set_nfnl_put(struct net *net, ip_set_id_t index); | |
325 | 327 | |
326 | 328 | /* API for iptables set match, and SET target */ |
327 | 329 |
net/netfilter/ipset/ip_set_bitmap_ip.c
... | ... | @@ -242,7 +242,8 @@ |
242 | 242 | } |
243 | 243 | |
244 | 244 | static int |
245 | -bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |
245 | +bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[], | |
246 | + u32 flags) | |
246 | 247 | { |
247 | 248 | struct bitmap_ip *map; |
248 | 249 | u32 first_ip = 0, last_ip = 0, hosts; |
net/netfilter/ipset/ip_set_bitmap_ipmac.c
net/netfilter/ipset/ip_set_bitmap_port.c
... | ... | @@ -228,7 +228,8 @@ |
228 | 228 | } |
229 | 229 | |
230 | 230 | static int |
231 | -bitmap_port_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |
231 | +bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[], | |
232 | + u32 flags) | |
232 | 233 | { |
233 | 234 | struct bitmap_port *map; |
234 | 235 | u16 first_port, last_port; |
net/netfilter/ipset/ip_set_core.c
... | ... | @@ -17,6 +17,8 @@ |
17 | 17 | #include <linux/spinlock.h> |
18 | 18 | #include <linux/rculist.h> |
19 | 19 | #include <net/netlink.h> |
20 | +#include <net/net_namespace.h> | |
21 | +#include <net/netns/generic.h> | |
20 | 22 | |
21 | 23 | #include <linux/netfilter.h> |
22 | 24 | #include <linux/netfilter/x_tables.h> |
23 | 25 | |
... | ... | @@ -27,9 +29,18 @@ |
27 | 29 | static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */ |
28 | 30 | static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */ |
29 | 31 | |
30 | -static struct ip_set * __rcu *ip_set_list; /* all individual sets */ | |
31 | -static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */ | |
32 | +struct ip_set_net { | |
33 | + struct ip_set * __rcu *ip_set_list; /* all individual sets */ | |
34 | + ip_set_id_t ip_set_max; /* max number of sets */ | |
35 | + int is_deleted; /* deleted by ip_set_net_exit */ | |
36 | +}; | |
37 | +static int ip_set_net_id __read_mostly; | |
32 | 38 | |
39 | +static inline struct ip_set_net *ip_set_pernet(struct net *net) | |
40 | +{ | |
41 | + return net_generic(net, ip_set_net_id); | |
42 | +} | |
43 | + | |
33 | 44 | #define IP_SET_INC 64 |
34 | 45 | #define STREQ(a, b) (strncmp(a, b, IPSET_MAXNAMELEN) == 0) |
35 | 46 | |
... | ... | @@ -45,8 +56,8 @@ |
45 | 56 | /* When the nfnl mutex is held: */ |
46 | 57 | #define nfnl_dereference(p) \ |
47 | 58 | rcu_dereference_protected(p, 1) |
48 | -#define nfnl_set(id) \ | |
49 | - nfnl_dereference(ip_set_list)[id] | |
59 | +#define nfnl_set(inst, id) \ | |
60 | + nfnl_dereference((inst)->ip_set_list)[id] | |
50 | 61 | |
51 | 62 | /* |
52 | 63 | * The set types are implemented in modules and registered set types |
53 | 64 | |
54 | 65 | |
... | ... | @@ -434,13 +445,14 @@ |
434 | 445 | */ |
435 | 446 | |
436 | 447 | static inline struct ip_set * |
437 | -ip_set_rcu_get(ip_set_id_t index) | |
448 | +ip_set_rcu_get(struct net *net, ip_set_id_t index) | |
438 | 449 | { |
439 | 450 | struct ip_set *set; |
451 | + struct ip_set_net *inst = ip_set_pernet(net); | |
440 | 452 | |
441 | 453 | rcu_read_lock(); |
442 | 454 | /* ip_set_list itself needs to be protected */ |
443 | - set = rcu_dereference(ip_set_list)[index]; | |
455 | + set = rcu_dereference(inst->ip_set_list)[index]; | |
444 | 456 | rcu_read_unlock(); |
445 | 457 | |
446 | 458 | return set; |
... | ... | @@ -450,7 +462,8 @@ |
450 | 462 | ip_set_test(ip_set_id_t index, const struct sk_buff *skb, |
451 | 463 | const struct xt_action_param *par, struct ip_set_adt_opt *opt) |
452 | 464 | { |
453 | - struct ip_set *set = ip_set_rcu_get(index); | |
465 | + struct ip_set *set = ip_set_rcu_get( | |
466 | + dev_net(par->in ? par->in : par->out), index); | |
454 | 467 | int ret = 0; |
455 | 468 | |
456 | 469 | BUG_ON(set == NULL); |
... | ... | @@ -488,7 +501,8 @@ |
488 | 501 | ip_set_add(ip_set_id_t index, const struct sk_buff *skb, |
489 | 502 | const struct xt_action_param *par, struct ip_set_adt_opt *opt) |
490 | 503 | { |
491 | - struct ip_set *set = ip_set_rcu_get(index); | |
504 | + struct ip_set *set = ip_set_rcu_get( | |
505 | + dev_net(par->in ? par->in : par->out), index); | |
492 | 506 | int ret; |
493 | 507 | |
494 | 508 | BUG_ON(set == NULL); |
... | ... | @@ -510,7 +524,8 @@ |
510 | 524 | ip_set_del(ip_set_id_t index, const struct sk_buff *skb, |
511 | 525 | const struct xt_action_param *par, struct ip_set_adt_opt *opt) |
512 | 526 | { |
513 | - struct ip_set *set = ip_set_rcu_get(index); | |
527 | + struct ip_set *set = ip_set_rcu_get( | |
528 | + dev_net(par->in ? par->in : par->out), index); | |
514 | 529 | int ret = 0; |
515 | 530 | |
516 | 531 | BUG_ON(set == NULL); |
517 | 532 | |
518 | 533 | |
... | ... | @@ -534,14 +549,15 @@ |
534 | 549 | * |
535 | 550 | */ |
536 | 551 | ip_set_id_t |
537 | -ip_set_get_byname(const char *name, struct ip_set **set) | |
552 | +ip_set_get_byname(struct net *net, const char *name, struct ip_set **set) | |
538 | 553 | { |
539 | 554 | ip_set_id_t i, index = IPSET_INVALID_ID; |
540 | 555 | struct ip_set *s; |
556 | + struct ip_set_net *inst = ip_set_pernet(net); | |
541 | 557 | |
542 | 558 | rcu_read_lock(); |
543 | - for (i = 0; i < ip_set_max; i++) { | |
544 | - s = rcu_dereference(ip_set_list)[i]; | |
559 | + for (i = 0; i < inst->ip_set_max; i++) { | |
560 | + s = rcu_dereference(inst->ip_set_list)[i]; | |
545 | 561 | if (s != NULL && STREQ(s->name, name)) { |
546 | 562 | __ip_set_get(s); |
547 | 563 | index = i; |
548 | 564 | |
549 | 565 | |
... | ... | @@ -561,17 +577,26 @@ |
561 | 577 | * to be valid, after calling this function. |
562 | 578 | * |
563 | 579 | */ |
564 | -void | |
565 | -ip_set_put_byindex(ip_set_id_t index) | |
580 | + | |
581 | +static inline void | |
582 | +__ip_set_put_byindex(struct ip_set_net *inst, ip_set_id_t index) | |
566 | 583 | { |
567 | 584 | struct ip_set *set; |
568 | 585 | |
569 | 586 | rcu_read_lock(); |
570 | - set = rcu_dereference(ip_set_list)[index]; | |
587 | + set = rcu_dereference(inst->ip_set_list)[index]; | |
571 | 588 | if (set != NULL) |
572 | 589 | __ip_set_put(set); |
573 | 590 | rcu_read_unlock(); |
574 | 591 | } |
592 | + | |
593 | +void | |
594 | +ip_set_put_byindex(struct net *net, ip_set_id_t index) | |
595 | +{ | |
596 | + struct ip_set_net *inst = ip_set_pernet(net); | |
597 | + | |
598 | + __ip_set_put_byindex(inst, index); | |
599 | +} | |
575 | 600 | EXPORT_SYMBOL_GPL(ip_set_put_byindex); |
576 | 601 | |
577 | 602 | /* |
578 | 603 | |
... | ... | @@ -582,9 +607,9 @@ |
582 | 607 | * |
583 | 608 | */ |
584 | 609 | const char * |
585 | -ip_set_name_byindex(ip_set_id_t index) | |
610 | +ip_set_name_byindex(struct net *net, ip_set_id_t index) | |
586 | 611 | { |
587 | - const struct ip_set *set = ip_set_rcu_get(index); | |
612 | + const struct ip_set *set = ip_set_rcu_get(net, index); | |
588 | 613 | |
589 | 614 | BUG_ON(set == NULL); |
590 | 615 | BUG_ON(set->ref == 0); |
591 | 616 | |
592 | 617 | |
... | ... | @@ -606,14 +631,15 @@ |
606 | 631 | * The nfnl mutex is used in the function. |
607 | 632 | */ |
608 | 633 | ip_set_id_t |
609 | -ip_set_nfnl_get(const char *name) | |
634 | +ip_set_nfnl_get(struct net *net, const char *name) | |
610 | 635 | { |
611 | 636 | ip_set_id_t i, index = IPSET_INVALID_ID; |
612 | 637 | struct ip_set *s; |
638 | + struct ip_set_net *inst = ip_set_pernet(net); | |
613 | 639 | |
614 | 640 | nfnl_lock(NFNL_SUBSYS_IPSET); |
615 | - for (i = 0; i < ip_set_max; i++) { | |
616 | - s = nfnl_set(i); | |
641 | + for (i = 0; i < inst->ip_set_max; i++) { | |
642 | + s = nfnl_set(inst, i); | |
617 | 643 | if (s != NULL && STREQ(s->name, name)) { |
618 | 644 | __ip_set_get(s); |
619 | 645 | index = i; |
620 | 646 | |
621 | 647 | |
622 | 648 | |
... | ... | @@ -633,15 +659,16 @@ |
633 | 659 | * The nfnl mutex is used in the function. |
634 | 660 | */ |
635 | 661 | ip_set_id_t |
636 | -ip_set_nfnl_get_byindex(ip_set_id_t index) | |
662 | +ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index) | |
637 | 663 | { |
638 | 664 | struct ip_set *set; |
665 | + struct ip_set_net *inst = ip_set_pernet(net); | |
639 | 666 | |
640 | - if (index > ip_set_max) | |
667 | + if (index > inst->ip_set_max) | |
641 | 668 | return IPSET_INVALID_ID; |
642 | 669 | |
643 | 670 | nfnl_lock(NFNL_SUBSYS_IPSET); |
644 | - set = nfnl_set(index); | |
671 | + set = nfnl_set(inst, index); | |
645 | 672 | if (set) |
646 | 673 | __ip_set_get(set); |
647 | 674 | else |
648 | 675 | |
649 | 676 | |
... | ... | @@ -660,13 +687,17 @@ |
660 | 687 | * The nfnl mutex is used in the function. |
661 | 688 | */ |
662 | 689 | void |
663 | -ip_set_nfnl_put(ip_set_id_t index) | |
690 | +ip_set_nfnl_put(struct net *net, ip_set_id_t index) | |
664 | 691 | { |
665 | 692 | struct ip_set *set; |
693 | + struct ip_set_net *inst = ip_set_pernet(net); | |
694 | + | |
666 | 695 | nfnl_lock(NFNL_SUBSYS_IPSET); |
667 | - set = nfnl_set(index); | |
668 | - if (set != NULL) | |
669 | - __ip_set_put(set); | |
696 | + if (!inst->is_deleted) { /* already deleted from ip_set_net_exit() */ | |
697 | + set = nfnl_set(inst, index); | |
698 | + if (set != NULL) | |
699 | + __ip_set_put(set); | |
700 | + } | |
670 | 701 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
671 | 702 | } |
672 | 703 | EXPORT_SYMBOL_GPL(ip_set_nfnl_put); |
673 | 704 | |
... | ... | @@ -724,14 +755,14 @@ |
724 | 755 | }; |
725 | 756 | |
726 | 757 | static struct ip_set * |
727 | -find_set_and_id(const char *name, ip_set_id_t *id) | |
758 | +find_set_and_id(struct ip_set_net *inst, const char *name, ip_set_id_t *id) | |
728 | 759 | { |
729 | 760 | struct ip_set *set = NULL; |
730 | 761 | ip_set_id_t i; |
731 | 762 | |
732 | 763 | *id = IPSET_INVALID_ID; |
733 | - for (i = 0; i < ip_set_max; i++) { | |
734 | - set = nfnl_set(i); | |
764 | + for (i = 0; i < inst->ip_set_max; i++) { | |
765 | + set = nfnl_set(inst, i); | |
735 | 766 | if (set != NULL && STREQ(set->name, name)) { |
736 | 767 | *id = i; |
737 | 768 | break; |
738 | 769 | |
739 | 770 | |
740 | 771 | |
... | ... | @@ -741,22 +772,23 @@ |
741 | 772 | } |
742 | 773 | |
743 | 774 | static inline struct ip_set * |
744 | -find_set(const char *name) | |
775 | +find_set(struct ip_set_net *inst, const char *name) | |
745 | 776 | { |
746 | 777 | ip_set_id_t id; |
747 | 778 | |
748 | - return find_set_and_id(name, &id); | |
779 | + return find_set_and_id(inst, name, &id); | |
749 | 780 | } |
750 | 781 | |
751 | 782 | static int |
752 | -find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set) | |
783 | +find_free_id(struct ip_set_net *inst, const char *name, ip_set_id_t *index, | |
784 | + struct ip_set **set) | |
753 | 785 | { |
754 | 786 | struct ip_set *s; |
755 | 787 | ip_set_id_t i; |
756 | 788 | |
757 | 789 | *index = IPSET_INVALID_ID; |
758 | - for (i = 0; i < ip_set_max; i++) { | |
759 | - s = nfnl_set(i); | |
790 | + for (i = 0; i < inst->ip_set_max; i++) { | |
791 | + s = nfnl_set(inst, i); | |
760 | 792 | if (s == NULL) { |
761 | 793 | if (*index == IPSET_INVALID_ID) |
762 | 794 | *index = i; |
... | ... | @@ -785,6 +817,8 @@ |
785 | 817 | const struct nlmsghdr *nlh, |
786 | 818 | const struct nlattr * const attr[]) |
787 | 819 | { |
820 | + struct net *net = sock_net(ctnl); | |
821 | + struct ip_set_net *inst = ip_set_pernet(net); | |
788 | 822 | struct ip_set *set, *clash = NULL; |
789 | 823 | ip_set_id_t index = IPSET_INVALID_ID; |
790 | 824 | struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1] = {}; |
... | ... | @@ -843,7 +877,7 @@ |
843 | 877 | goto put_out; |
844 | 878 | } |
845 | 879 | |
846 | - ret = set->type->create(set, tb, flags); | |
880 | + ret = set->type->create(net, set, tb, flags); | |
847 | 881 | if (ret != 0) |
848 | 882 | goto put_out; |
849 | 883 | |
... | ... | @@ -854,7 +888,7 @@ |
854 | 888 | * by the nfnl mutex. Find the first free index in ip_set_list |
855 | 889 | * and check clashing. |
856 | 890 | */ |
857 | - ret = find_free_id(set->name, &index, &clash); | |
891 | + ret = find_free_id(inst, set->name, &index, &clash); | |
858 | 892 | if (ret == -EEXIST) { |
859 | 893 | /* If this is the same set and requested, ignore error */ |
860 | 894 | if ((flags & IPSET_FLAG_EXIST) && |
861 | 895 | |
... | ... | @@ -867,9 +901,9 @@ |
867 | 901 | goto cleanup; |
868 | 902 | } else if (ret == -IPSET_ERR_MAX_SETS) { |
869 | 903 | struct ip_set **list, **tmp; |
870 | - ip_set_id_t i = ip_set_max + IP_SET_INC; | |
904 | + ip_set_id_t i = inst->ip_set_max + IP_SET_INC; | |
871 | 905 | |
872 | - if (i < ip_set_max || i == IPSET_INVALID_ID) | |
906 | + if (i < inst->ip_set_max || i == IPSET_INVALID_ID) | |
873 | 907 | /* Wraparound */ |
874 | 908 | goto cleanup; |
875 | 909 | |
876 | 910 | |
... | ... | @@ -877,14 +911,14 @@ |
877 | 911 | if (!list) |
878 | 912 | goto cleanup; |
879 | 913 | /* nfnl mutex is held, both lists are valid */ |
880 | - tmp = nfnl_dereference(ip_set_list); | |
881 | - memcpy(list, tmp, sizeof(struct ip_set *) * ip_set_max); | |
882 | - rcu_assign_pointer(ip_set_list, list); | |
914 | + tmp = nfnl_dereference(inst->ip_set_list); | |
915 | + memcpy(list, tmp, sizeof(struct ip_set *) * inst->ip_set_max); | |
916 | + rcu_assign_pointer(inst->ip_set_list, list); | |
883 | 917 | /* Make sure all current packets have passed through */ |
884 | 918 | synchronize_net(); |
885 | 919 | /* Use new list */ |
886 | - index = ip_set_max; | |
887 | - ip_set_max = i; | |
920 | + index = inst->ip_set_max; | |
921 | + inst->ip_set_max = i; | |
888 | 922 | kfree(tmp); |
889 | 923 | ret = 0; |
890 | 924 | } else if (ret) |
... | ... | @@ -894,7 +928,7 @@ |
894 | 928 | * Finally! Add our shiny new set to the list, and be done. |
895 | 929 | */ |
896 | 930 | pr_debug("create: '%s' created with index %u!\n", set->name, index); |
897 | - nfnl_set(index) = set; | |
931 | + nfnl_set(inst, index) = set; | |
898 | 932 | |
899 | 933 | return ret; |
900 | 934 | |
901 | 935 | |
902 | 936 | |
... | ... | @@ -917,12 +951,12 @@ |
917 | 951 | }; |
918 | 952 | |
919 | 953 | static void |
920 | -ip_set_destroy_set(ip_set_id_t index) | |
954 | +ip_set_destroy_set(struct ip_set_net *inst, ip_set_id_t index) | |
921 | 955 | { |
922 | - struct ip_set *set = nfnl_set(index); | |
956 | + struct ip_set *set = nfnl_set(inst, index); | |
923 | 957 | |
924 | 958 | pr_debug("set: %s\n", set->name); |
925 | - nfnl_set(index) = NULL; | |
959 | + nfnl_set(inst, index) = NULL; | |
926 | 960 | |
927 | 961 | /* Must call it without holding any lock */ |
928 | 962 | set->variant->destroy(set); |
... | ... | @@ -935,6 +969,7 @@ |
935 | 969 | const struct nlmsghdr *nlh, |
936 | 970 | const struct nlattr * const attr[]) |
937 | 971 | { |
972 | + struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | |
938 | 973 | struct ip_set *s; |
939 | 974 | ip_set_id_t i; |
940 | 975 | int ret = 0; |
941 | 976 | |
942 | 977 | |
943 | 978 | |
... | ... | @@ -954,21 +989,22 @@ |
954 | 989 | */ |
955 | 990 | read_lock_bh(&ip_set_ref_lock); |
956 | 991 | if (!attr[IPSET_ATTR_SETNAME]) { |
957 | - for (i = 0; i < ip_set_max; i++) { | |
958 | - s = nfnl_set(i); | |
992 | + for (i = 0; i < inst->ip_set_max; i++) { | |
993 | + s = nfnl_set(inst, i); | |
959 | 994 | if (s != NULL && s->ref) { |
960 | 995 | ret = -IPSET_ERR_BUSY; |
961 | 996 | goto out; |
962 | 997 | } |
963 | 998 | } |
964 | 999 | read_unlock_bh(&ip_set_ref_lock); |
965 | - for (i = 0; i < ip_set_max; i++) { | |
966 | - s = nfnl_set(i); | |
1000 | + for (i = 0; i < inst->ip_set_max; i++) { | |
1001 | + s = nfnl_set(inst, i); | |
967 | 1002 | if (s != NULL) |
968 | - ip_set_destroy_set(i); | |
1003 | + ip_set_destroy_set(inst, i); | |
969 | 1004 | } |
970 | 1005 | } else { |
971 | - s = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME]), &i); | |
1006 | + s = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]), | |
1007 | + &i); | |
972 | 1008 | if (s == NULL) { |
973 | 1009 | ret = -ENOENT; |
974 | 1010 | goto out; |
... | ... | @@ -978,7 +1014,7 @@ |
978 | 1014 | } |
979 | 1015 | read_unlock_bh(&ip_set_ref_lock); |
980 | 1016 | |
981 | - ip_set_destroy_set(i); | |
1017 | + ip_set_destroy_set(inst, i); | |
982 | 1018 | } |
983 | 1019 | return 0; |
984 | 1020 | out: |
... | ... | @@ -1003,6 +1039,7 @@ |
1003 | 1039 | const struct nlmsghdr *nlh, |
1004 | 1040 | const struct nlattr * const attr[]) |
1005 | 1041 | { |
1042 | + struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | |
1006 | 1043 | struct ip_set *s; |
1007 | 1044 | ip_set_id_t i; |
1008 | 1045 | |
1009 | 1046 | |
... | ... | @@ -1010,13 +1047,13 @@ |
1010 | 1047 | return -IPSET_ERR_PROTOCOL; |
1011 | 1048 | |
1012 | 1049 | if (!attr[IPSET_ATTR_SETNAME]) { |
1013 | - for (i = 0; i < ip_set_max; i++) { | |
1014 | - s = nfnl_set(i); | |
1050 | + for (i = 0; i < inst->ip_set_max; i++) { | |
1051 | + s = nfnl_set(inst, i); | |
1015 | 1052 | if (s != NULL) |
1016 | 1053 | ip_set_flush_set(s); |
1017 | 1054 | } |
1018 | 1055 | } else { |
1019 | - s = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); | |
1056 | + s = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME])); | |
1020 | 1057 | if (s == NULL) |
1021 | 1058 | return -ENOENT; |
1022 | 1059 | |
... | ... | @@ -1042,6 +1079,7 @@ |
1042 | 1079 | const struct nlmsghdr *nlh, |
1043 | 1080 | const struct nlattr * const attr[]) |
1044 | 1081 | { |
1082 | + struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | |
1045 | 1083 | struct ip_set *set, *s; |
1046 | 1084 | const char *name2; |
1047 | 1085 | ip_set_id_t i; |
... | ... | @@ -1052,7 +1090,7 @@ |
1052 | 1090 | attr[IPSET_ATTR_SETNAME2] == NULL)) |
1053 | 1091 | return -IPSET_ERR_PROTOCOL; |
1054 | 1092 | |
1055 | - set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); | |
1093 | + set = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME])); | |
1056 | 1094 | if (set == NULL) |
1057 | 1095 | return -ENOENT; |
1058 | 1096 | |
... | ... | @@ -1063,8 +1101,8 @@ |
1063 | 1101 | } |
1064 | 1102 | |
1065 | 1103 | name2 = nla_data(attr[IPSET_ATTR_SETNAME2]); |
1066 | - for (i = 0; i < ip_set_max; i++) { | |
1067 | - s = nfnl_set(i); | |
1104 | + for (i = 0; i < inst->ip_set_max; i++) { | |
1105 | + s = nfnl_set(inst, i); | |
1068 | 1106 | if (s != NULL && STREQ(s->name, name2)) { |
1069 | 1107 | ret = -IPSET_ERR_EXIST_SETNAME2; |
1070 | 1108 | goto out; |
... | ... | @@ -1091,6 +1129,7 @@ |
1091 | 1129 | const struct nlmsghdr *nlh, |
1092 | 1130 | const struct nlattr * const attr[]) |
1093 | 1131 | { |
1132 | + struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | |
1094 | 1133 | struct ip_set *from, *to; |
1095 | 1134 | ip_set_id_t from_id, to_id; |
1096 | 1135 | char from_name[IPSET_MAXNAMELEN]; |
1097 | 1136 | |
... | ... | @@ -1100,11 +1139,13 @@ |
1100 | 1139 | attr[IPSET_ATTR_SETNAME2] == NULL)) |
1101 | 1140 | return -IPSET_ERR_PROTOCOL; |
1102 | 1141 | |
1103 | - from = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME]), &from_id); | |
1142 | + from = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]), | |
1143 | + &from_id); | |
1104 | 1144 | if (from == NULL) |
1105 | 1145 | return -ENOENT; |
1106 | 1146 | |
1107 | - to = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME2]), &to_id); | |
1147 | + to = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME2]), | |
1148 | + &to_id); | |
1108 | 1149 | if (to == NULL) |
1109 | 1150 | return -IPSET_ERR_EXIST_SETNAME2; |
1110 | 1151 | |
... | ... | @@ -1121,8 +1162,8 @@ |
1121 | 1162 | |
1122 | 1163 | write_lock_bh(&ip_set_ref_lock); |
1123 | 1164 | swap(from->ref, to->ref); |
1124 | - nfnl_set(from_id) = to; | |
1125 | - nfnl_set(to_id) = from; | |
1165 | + nfnl_set(inst, from_id) = to; | |
1166 | + nfnl_set(inst, to_id) = from; | |
1126 | 1167 | write_unlock_bh(&ip_set_ref_lock); |
1127 | 1168 | |
1128 | 1169 | return 0; |
1129 | 1170 | |
... | ... | @@ -1141,9 +1182,10 @@ |
1141 | 1182 | static int |
1142 | 1183 | ip_set_dump_done(struct netlink_callback *cb) |
1143 | 1184 | { |
1185 | + struct ip_set_net *inst = (struct ip_set_net *)cb->data; | |
1144 | 1186 | if (cb->args[2]) { |
1145 | - pr_debug("release set %s\n", nfnl_set(cb->args[1])->name); | |
1146 | - ip_set_put_byindex((ip_set_id_t) cb->args[1]); | |
1187 | + pr_debug("release set %s\n", nfnl_set(inst, cb->args[1])->name); | |
1188 | + __ip_set_put_byindex(inst, (ip_set_id_t) cb->args[1]); | |
1147 | 1189 | } |
1148 | 1190 | return 0; |
1149 | 1191 | } |
... | ... | @@ -1169,6 +1211,7 @@ |
1169 | 1211 | struct nlattr *attr = (void *)nlh + min_len; |
1170 | 1212 | u32 dump_type; |
1171 | 1213 | ip_set_id_t index; |
1214 | + struct ip_set_net *inst = (struct ip_set_net *)cb->data; | |
1172 | 1215 | |
1173 | 1216 | /* Second pass, so parser can't fail */ |
1174 | 1217 | nla_parse(cda, IPSET_ATTR_CMD_MAX, |
... | ... | @@ -1182,7 +1225,7 @@ |
1182 | 1225 | if (cda[IPSET_ATTR_SETNAME]) { |
1183 | 1226 | struct ip_set *set; |
1184 | 1227 | |
1185 | - set = find_set_and_id(nla_data(cda[IPSET_ATTR_SETNAME]), | |
1228 | + set = find_set_and_id(inst, nla_data(cda[IPSET_ATTR_SETNAME]), | |
1186 | 1229 | &index); |
1187 | 1230 | if (set == NULL) |
1188 | 1231 | return -ENOENT; |
... | ... | @@ -1210,6 +1253,7 @@ |
1210 | 1253 | unsigned int flags = NETLINK_CB(cb->skb).portid ? NLM_F_MULTI : 0; |
1211 | 1254 | u32 dump_type, dump_flags; |
1212 | 1255 | int ret = 0; |
1256 | + struct ip_set_net *inst = (struct ip_set_net *)cb->data; | |
1213 | 1257 | |
1214 | 1258 | if (!cb->args[0]) { |
1215 | 1259 | ret = dump_init(cb); |
1216 | 1260 | |
1217 | 1261 | |
... | ... | @@ -1223,18 +1267,18 @@ |
1223 | 1267 | } |
1224 | 1268 | } |
1225 | 1269 | |
1226 | - if (cb->args[1] >= ip_set_max) | |
1270 | + if (cb->args[1] >= inst->ip_set_max) | |
1227 | 1271 | goto out; |
1228 | 1272 | |
1229 | 1273 | dump_type = DUMP_TYPE(cb->args[0]); |
1230 | 1274 | dump_flags = DUMP_FLAGS(cb->args[0]); |
1231 | - max = dump_type == DUMP_ONE ? cb->args[1] + 1 : ip_set_max; | |
1275 | + max = dump_type == DUMP_ONE ? cb->args[1] + 1 : inst->ip_set_max; | |
1232 | 1276 | dump_last: |
1233 | 1277 | pr_debug("args[0]: %u %u args[1]: %ld\n", |
1234 | 1278 | dump_type, dump_flags, cb->args[1]); |
1235 | 1279 | for (; cb->args[1] < max; cb->args[1]++) { |
1236 | 1280 | index = (ip_set_id_t) cb->args[1]; |
1237 | - set = nfnl_set(index); | |
1281 | + set = nfnl_set(inst, index); | |
1238 | 1282 | if (set == NULL) { |
1239 | 1283 | if (dump_type == DUMP_ONE) { |
1240 | 1284 | ret = -ENOENT; |
... | ... | @@ -1312,8 +1356,8 @@ |
1312 | 1356 | release_refcount: |
1313 | 1357 | /* If there was an error or set is done, release set */ |
1314 | 1358 | if (ret || !cb->args[2]) { |
1315 | - pr_debug("release set %s\n", nfnl_set(index)->name); | |
1316 | - ip_set_put_byindex(index); | |
1359 | + pr_debug("release set %s\n", nfnl_set(inst, index)->name); | |
1360 | + __ip_set_put_byindex(inst, index); | |
1317 | 1361 | cb->args[2] = 0; |
1318 | 1362 | } |
1319 | 1363 | out: |
... | ... | @@ -1331,6 +1375,8 @@ |
1331 | 1375 | const struct nlmsghdr *nlh, |
1332 | 1376 | const struct nlattr * const attr[]) |
1333 | 1377 | { |
1378 | + struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | |
1379 | + | |
1334 | 1380 | if (unlikely(protocol_failed(attr))) |
1335 | 1381 | return -IPSET_ERR_PROTOCOL; |
1336 | 1382 | |
... | ... | @@ -1338,6 +1384,7 @@ |
1338 | 1384 | struct netlink_dump_control c = { |
1339 | 1385 | .dump = ip_set_dump_start, |
1340 | 1386 | .done = ip_set_dump_done, |
1387 | + .data = (void *)inst | |
1341 | 1388 | }; |
1342 | 1389 | return netlink_dump_start(ctnl, skb, nlh, &c); |
1343 | 1390 | } |
... | ... | @@ -1416,6 +1463,7 @@ |
1416 | 1463 | const struct nlmsghdr *nlh, |
1417 | 1464 | const struct nlattr * const attr[]) |
1418 | 1465 | { |
1466 | + struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | |
1419 | 1467 | struct ip_set *set; |
1420 | 1468 | struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {}; |
1421 | 1469 | const struct nlattr *nla; |
... | ... | @@ -1434,7 +1482,7 @@ |
1434 | 1482 | attr[IPSET_ATTR_LINENO] == NULL)))) |
1435 | 1483 | return -IPSET_ERR_PROTOCOL; |
1436 | 1484 | |
1437 | - set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); | |
1485 | + set = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME])); | |
1438 | 1486 | if (set == NULL) |
1439 | 1487 | return -ENOENT; |
1440 | 1488 | |
... | ... | @@ -1470,6 +1518,7 @@ |
1470 | 1518 | const struct nlmsghdr *nlh, |
1471 | 1519 | const struct nlattr * const attr[]) |
1472 | 1520 | { |
1521 | + struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | |
1473 | 1522 | struct ip_set *set; |
1474 | 1523 | struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {}; |
1475 | 1524 | const struct nlattr *nla; |
... | ... | @@ -1488,7 +1537,7 @@ |
1488 | 1537 | attr[IPSET_ATTR_LINENO] == NULL)))) |
1489 | 1538 | return -IPSET_ERR_PROTOCOL; |
1490 | 1539 | |
1491 | - set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); | |
1540 | + set = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME])); | |
1492 | 1541 | if (set == NULL) |
1493 | 1542 | return -ENOENT; |
1494 | 1543 | |
... | ... | @@ -1524,6 +1573,7 @@ |
1524 | 1573 | const struct nlmsghdr *nlh, |
1525 | 1574 | const struct nlattr * const attr[]) |
1526 | 1575 | { |
1576 | + struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | |
1527 | 1577 | struct ip_set *set; |
1528 | 1578 | struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {}; |
1529 | 1579 | int ret = 0; |
... | ... | @@ -1534,7 +1584,7 @@ |
1534 | 1584 | !flag_nested(attr[IPSET_ATTR_DATA]))) |
1535 | 1585 | return -IPSET_ERR_PROTOCOL; |
1536 | 1586 | |
1537 | - set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); | |
1587 | + set = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME])); | |
1538 | 1588 | if (set == NULL) |
1539 | 1589 | return -ENOENT; |
1540 | 1590 | |
... | ... | @@ -1559,6 +1609,7 @@ |
1559 | 1609 | const struct nlmsghdr *nlh, |
1560 | 1610 | const struct nlattr * const attr[]) |
1561 | 1611 | { |
1612 | + struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | |
1562 | 1613 | const struct ip_set *set; |
1563 | 1614 | struct sk_buff *skb2; |
1564 | 1615 | struct nlmsghdr *nlh2; |
... | ... | @@ -1568,7 +1619,7 @@ |
1568 | 1619 | attr[IPSET_ATTR_SETNAME] == NULL)) |
1569 | 1620 | return -IPSET_ERR_PROTOCOL; |
1570 | 1621 | |
1571 | - set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); | |
1622 | + set = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME])); | |
1572 | 1623 | if (set == NULL) |
1573 | 1624 | return -ENOENT; |
1574 | 1625 | |
1575 | 1626 | |
... | ... | @@ -1793,8 +1844,10 @@ |
1793 | 1844 | unsigned int *op; |
1794 | 1845 | void *data; |
1795 | 1846 | int copylen = *len, ret = 0; |
1847 | + struct net *net = sock_net(sk); | |
1848 | + struct ip_set_net *inst = ip_set_pernet(net); | |
1796 | 1849 | |
1797 | - if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) | |
1850 | + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) | |
1798 | 1851 | return -EPERM; |
1799 | 1852 | if (optval != SO_IP_SET) |
1800 | 1853 | return -EBADF; |
... | ... | @@ -1843,7 +1896,7 @@ |
1843 | 1896 | } |
1844 | 1897 | req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0'; |
1845 | 1898 | nfnl_lock(NFNL_SUBSYS_IPSET); |
1846 | - find_set_and_id(req_get->set.name, &id); | |
1899 | + find_set_and_id(inst, req_get->set.name, &id); | |
1847 | 1900 | req_get->set.index = id; |
1848 | 1901 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
1849 | 1902 | goto copy; |
1850 | 1903 | |
... | ... | @@ -1858,10 +1911,10 @@ |
1858 | 1911 | } |
1859 | 1912 | req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0'; |
1860 | 1913 | nfnl_lock(NFNL_SUBSYS_IPSET); |
1861 | - find_set_and_id(req_get->set.name, &id); | |
1914 | + find_set_and_id(inst, req_get->set.name, &id); | |
1862 | 1915 | req_get->set.index = id; |
1863 | 1916 | if (id != IPSET_INVALID_ID) |
1864 | - req_get->family = nfnl_set(id)->family; | |
1917 | + req_get->family = nfnl_set(inst, id)->family; | |
1865 | 1918 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
1866 | 1919 | goto copy; |
1867 | 1920 | } |
1868 | 1921 | |
... | ... | @@ -1870,12 +1923,12 @@ |
1870 | 1923 | struct ip_set *set; |
1871 | 1924 | |
1872 | 1925 | if (*len != sizeof(struct ip_set_req_get_set) || |
1873 | - req_get->set.index >= ip_set_max) { | |
1926 | + req_get->set.index >= inst->ip_set_max) { | |
1874 | 1927 | ret = -EINVAL; |
1875 | 1928 | goto done; |
1876 | 1929 | } |
1877 | 1930 | nfnl_lock(NFNL_SUBSYS_IPSET); |
1878 | - set = nfnl_set(req_get->set.index); | |
1931 | + set = nfnl_set(inst, req_get->set.index); | |
1879 | 1932 | strncpy(req_get->set.name, set ? set->name : "", |
1880 | 1933 | IPSET_MAXNAMELEN); |
1881 | 1934 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
1882 | 1935 | |
1883 | 1936 | |
1884 | 1937 | |
1885 | 1938 | |
1886 | 1939 | |
1887 | 1940 | |
1888 | 1941 | |
1889 | 1942 | |
1890 | 1943 | |
1891 | 1944 | |
1892 | 1945 | |
... | ... | @@ -1904,49 +1957,82 @@ |
1904 | 1957 | .owner = THIS_MODULE, |
1905 | 1958 | }; |
1906 | 1959 | |
1907 | -static int __init | |
1908 | -ip_set_init(void) | |
1960 | +static int __net_init | |
1961 | +ip_set_net_init(struct net *net) | |
1909 | 1962 | { |
1963 | + struct ip_set_net *inst = ip_set_pernet(net); | |
1964 | + | |
1910 | 1965 | struct ip_set **list; |
1911 | - int ret; | |
1912 | 1966 | |
1913 | - if (max_sets) | |
1914 | - ip_set_max = max_sets; | |
1915 | - if (ip_set_max >= IPSET_INVALID_ID) | |
1916 | - ip_set_max = IPSET_INVALID_ID - 1; | |
1967 | + inst->ip_set_max = max_sets ? max_sets : CONFIG_IP_SET_MAX; | |
1968 | + if (inst->ip_set_max >= IPSET_INVALID_ID) | |
1969 | + inst->ip_set_max = IPSET_INVALID_ID - 1; | |
1917 | 1970 | |
1918 | - list = kzalloc(sizeof(struct ip_set *) * ip_set_max, GFP_KERNEL); | |
1971 | + list = kzalloc(sizeof(struct ip_set *) * inst->ip_set_max, GFP_KERNEL); | |
1919 | 1972 | if (!list) |
1920 | 1973 | return -ENOMEM; |
1974 | + inst->is_deleted = 0; | |
1975 | + rcu_assign_pointer(inst->ip_set_list, list); | |
1976 | + pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL); | |
1977 | + return 0; | |
1978 | +} | |
1921 | 1979 | |
1922 | - rcu_assign_pointer(ip_set_list, list); | |
1923 | - ret = nfnetlink_subsys_register(&ip_set_netlink_subsys); | |
1980 | +static void __net_exit | |
1981 | +ip_set_net_exit(struct net *net) | |
1982 | +{ | |
1983 | + struct ip_set_net *inst = ip_set_pernet(net); | |
1984 | + | |
1985 | + struct ip_set *set = NULL; | |
1986 | + ip_set_id_t i; | |
1987 | + | |
1988 | + inst->is_deleted = 1; /* flag for ip_set_nfnl_put */ | |
1989 | + | |
1990 | + for (i = 0; i < inst->ip_set_max; i++) { | |
1991 | + set = nfnl_set(inst, i); | |
1992 | + if (set != NULL) | |
1993 | + ip_set_destroy_set(inst, i); | |
1994 | + } | |
1995 | + kfree(rcu_dereference_protected(inst->ip_set_list, 1)); | |
1996 | +} | |
1997 | + | |
1998 | +static struct pernet_operations ip_set_net_ops = { | |
1999 | + .init = ip_set_net_init, | |
2000 | + .exit = ip_set_net_exit, | |
2001 | + .id = &ip_set_net_id, | |
2002 | + .size = sizeof(struct ip_set_net) | |
2003 | +}; | |
2004 | + | |
2005 | + | |
2006 | +static int __init | |
2007 | +ip_set_init(void) | |
2008 | +{ | |
2009 | + int ret = nfnetlink_subsys_register(&ip_set_netlink_subsys); | |
1924 | 2010 | if (ret != 0) { |
1925 | 2011 | pr_err("ip_set: cannot register with nfnetlink.\n"); |
1926 | - kfree(list); | |
1927 | 2012 | return ret; |
1928 | 2013 | } |
1929 | 2014 | ret = nf_register_sockopt(&so_set); |
1930 | 2015 | if (ret != 0) { |
1931 | 2016 | pr_err("SO_SET registry failed: %d\n", ret); |
1932 | 2017 | nfnetlink_subsys_unregister(&ip_set_netlink_subsys); |
1933 | - kfree(list); | |
1934 | 2018 | return ret; |
1935 | 2019 | } |
1936 | - | |
1937 | - pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL); | |
2020 | + ret = register_pernet_subsys(&ip_set_net_ops); | |
2021 | + if (ret) { | |
2022 | + pr_err("ip_set: cannot register pernet_subsys.\n"); | |
2023 | + nf_unregister_sockopt(&so_set); | |
2024 | + nfnetlink_subsys_unregister(&ip_set_netlink_subsys); | |
2025 | + return ret; | |
2026 | + } | |
1938 | 2027 | return 0; |
1939 | 2028 | } |
1940 | 2029 | |
1941 | 2030 | static void __exit |
1942 | 2031 | ip_set_fini(void) |
1943 | 2032 | { |
1944 | - struct ip_set **list = rcu_dereference_protected(ip_set_list, 1); | |
1945 | - | |
1946 | - /* There can't be any existing set */ | |
2033 | + unregister_pernet_subsys(&ip_set_net_ops); | |
1947 | 2034 | nf_unregister_sockopt(&so_set); |
1948 | 2035 | nfnetlink_subsys_unregister(&ip_set_netlink_subsys); |
1949 | - kfree(list); | |
1950 | 2036 | pr_debug("these are the famous last words\n"); |
1951 | 2037 | } |
1952 | 2038 |
net/netfilter/ipset/ip_set_hash_gen.h
... | ... | @@ -1011,7 +1011,8 @@ |
1011 | 1011 | |
1012 | 1012 | #ifdef IP_SET_EMIT_CREATE |
1013 | 1013 | static int |
1014 | -IPSET_TOKEN(HTYPE, _create)(struct ip_set *set, struct nlattr *tb[], u32 flags) | |
1014 | +IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, | |
1015 | + struct nlattr *tb[], u32 flags) | |
1015 | 1016 | { |
1016 | 1017 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; |
1017 | 1018 | u8 hbits; |
net/netfilter/ipset/ip_set_list_set.c
... | ... | @@ -39,6 +39,7 @@ |
39 | 39 | struct list_set { |
40 | 40 | u32 size; /* size of set list array */ |
41 | 41 | struct timer_list gc; /* garbage collection */ |
42 | + struct net *net; /* namespace */ | |
42 | 43 | struct set_elem members[0]; /* the set members */ |
43 | 44 | }; |
44 | 45 | |
... | ... | @@ -171,7 +172,7 @@ |
171 | 172 | if (e->id != IPSET_INVALID_ID) { |
172 | 173 | if (i == map->size - 1) { |
173 | 174 | /* Last element replaced: e.g. add new,before,last */ |
174 | - ip_set_put_byindex(e->id); | |
175 | + ip_set_put_byindex(map->net, e->id); | |
175 | 176 | ip_set_ext_destroy(set, e); |
176 | 177 | } else { |
177 | 178 | struct set_elem *x = list_set_elem(set, map, |
... | ... | @@ -179,7 +180,7 @@ |
179 | 180 | |
180 | 181 | /* Last element pushed off */ |
181 | 182 | if (x->id != IPSET_INVALID_ID) { |
182 | - ip_set_put_byindex(x->id); | |
183 | + ip_set_put_byindex(map->net, x->id); | |
183 | 184 | ip_set_ext_destroy(set, x); |
184 | 185 | } |
185 | 186 | memmove(list_set_elem(set, map, i + 1), e, |
... | ... | @@ -205,7 +206,7 @@ |
205 | 206 | struct list_set *map = set->data; |
206 | 207 | struct set_elem *e = list_set_elem(set, map, i); |
207 | 208 | |
208 | - ip_set_put_byindex(e->id); | |
209 | + ip_set_put_byindex(map->net, e->id); | |
209 | 210 | ip_set_ext_destroy(set, e); |
210 | 211 | |
211 | 212 | if (i < map->size - 1) |
... | ... | @@ -307,7 +308,7 @@ |
307 | 308 | if (SET_WITH_COMMENT(set)) |
308 | 309 | ip_set_init_comment(ext_comment(e, set), ext); |
309 | 310 | /* Set is already added to the list */ |
310 | - ip_set_put_byindex(d->id); | |
311 | + ip_set_put_byindex(map->net, d->id); | |
311 | 312 | return 0; |
312 | 313 | } |
313 | 314 | insert: |
... | ... | @@ -366,6 +367,7 @@ |
366 | 367 | list_set_uadt(struct ip_set *set, struct nlattr *tb[], |
367 | 368 | enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) |
368 | 369 | { |
370 | + struct list_set *map = set->data; | |
369 | 371 | ipset_adtfn adtfn = set->variant->adt[adt]; |
370 | 372 | struct set_adt_elem e = { .refid = IPSET_INVALID_ID }; |
371 | 373 | struct ip_set_ext ext = IP_SET_INIT_UEXT(set); |
... | ... | @@ -385,7 +387,7 @@ |
385 | 387 | ret = ip_set_get_extensions(set, tb, &ext); |
386 | 388 | if (ret) |
387 | 389 | return ret; |
388 | - e.id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s); | |
390 | + e.id = ip_set_get_byname(map->net, nla_data(tb[IPSET_ATTR_NAME]), &s); | |
389 | 391 | if (e.id == IPSET_INVALID_ID) |
390 | 392 | return -IPSET_ERR_NAME; |
391 | 393 | /* "Loop detection" */ |
... | ... | @@ -405,7 +407,8 @@ |
405 | 407 | } |
406 | 408 | |
407 | 409 | if (tb[IPSET_ATTR_NAMEREF]) { |
408 | - e.refid = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAMEREF]), | |
410 | + e.refid = ip_set_get_byname(map->net, | |
411 | + nla_data(tb[IPSET_ATTR_NAMEREF]), | |
409 | 412 | &s); |
410 | 413 | if (e.refid == IPSET_INVALID_ID) { |
411 | 414 | ret = -IPSET_ERR_NAMEREF; |
412 | 415 | |
... | ... | @@ -421,9 +424,9 @@ |
421 | 424 | |
422 | 425 | finish: |
423 | 426 | if (e.refid != IPSET_INVALID_ID) |
424 | - ip_set_put_byindex(e.refid); | |
427 | + ip_set_put_byindex(map->net, e.refid); | |
425 | 428 | if (adt != IPSET_ADD || ret) |
426 | - ip_set_put_byindex(e.id); | |
429 | + ip_set_put_byindex(map->net, e.id); | |
427 | 430 | |
428 | 431 | return ip_set_eexist(ret, flags) ? 0 : ret; |
429 | 432 | } |
... | ... | @@ -438,7 +441,7 @@ |
438 | 441 | for (i = 0; i < map->size; i++) { |
439 | 442 | e = list_set_elem(set, map, i); |
440 | 443 | if (e->id != IPSET_INVALID_ID) { |
441 | - ip_set_put_byindex(e->id); | |
444 | + ip_set_put_byindex(map->net, e->id); | |
442 | 445 | ip_set_ext_destroy(set, e); |
443 | 446 | e->id = IPSET_INVALID_ID; |
444 | 447 | } |
... | ... | @@ -510,7 +513,7 @@ |
510 | 513 | goto nla_put_failure; |
511 | 514 | } |
512 | 515 | if (nla_put_string(skb, IPSET_ATTR_NAME, |
513 | - ip_set_name_byindex(e->id))) | |
516 | + ip_set_name_byindex(map->net, e->id))) | |
514 | 517 | goto nla_put_failure; |
515 | 518 | if (ip_set_put_extensions(skb, set, e, true)) |
516 | 519 | goto nla_put_failure; |
... | ... | @@ -587,7 +590,7 @@ |
587 | 590 | /* Create list:set type of sets */ |
588 | 591 | |
589 | 592 | static bool |
590 | -init_list_set(struct ip_set *set, u32 size) | |
593 | +init_list_set(struct net *net, struct ip_set *set, u32 size) | |
591 | 594 | { |
592 | 595 | struct list_set *map; |
593 | 596 | struct set_elem *e; |
... | ... | @@ -598,6 +601,7 @@ |
598 | 601 | return false; |
599 | 602 | |
600 | 603 | map->size = size; |
604 | + map->net = net; | |
601 | 605 | set->data = map; |
602 | 606 | |
603 | 607 | for (i = 0; i < size; i++) { |
... | ... | @@ -609,7 +613,8 @@ |
609 | 613 | } |
610 | 614 | |
611 | 615 | static int |
612 | -list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |
616 | +list_set_create(struct net *net, struct ip_set *set, struct nlattr *tb[], | |
617 | + u32 flags) | |
613 | 618 | { |
614 | 619 | u32 size = IP_SET_LIST_DEFAULT_SIZE; |
615 | 620 | |
... | ... | @@ -625,7 +630,7 @@ |
625 | 630 | |
626 | 631 | set->variant = &set_variant; |
627 | 632 | set->dsize = ip_set_elem_len(set, tb, sizeof(struct set_elem)); |
628 | - if (!init_list_set(set, size)) | |
633 | + if (!init_list_set(net, set, size)) | |
629 | 634 | return -ENOMEM; |
630 | 635 | if (tb[IPSET_ATTR_TIMEOUT]) { |
631 | 636 | set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
net/netfilter/xt_set.c
... | ... | @@ -81,7 +81,7 @@ |
81 | 81 | struct xt_set_info_match_v0 *info = par->matchinfo; |
82 | 82 | ip_set_id_t index; |
83 | 83 | |
84 | - index = ip_set_nfnl_get_byindex(info->match_set.index); | |
84 | + index = ip_set_nfnl_get_byindex(par->net, info->match_set.index); | |
85 | 85 | |
86 | 86 | if (index == IPSET_INVALID_ID) { |
87 | 87 | pr_warning("Cannot find set indentified by id %u to match\n", |
... | ... | @@ -91,7 +91,7 @@ |
91 | 91 | if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) { |
92 | 92 | pr_warning("Protocol error: set match dimension " |
93 | 93 | "is over the limit!\n"); |
94 | - ip_set_nfnl_put(info->match_set.index); | |
94 | + ip_set_nfnl_put(par->net, info->match_set.index); | |
95 | 95 | return -ERANGE; |
96 | 96 | } |
97 | 97 | |
... | ... | @@ -106,7 +106,7 @@ |
106 | 106 | { |
107 | 107 | struct xt_set_info_match_v0 *info = par->matchinfo; |
108 | 108 | |
109 | - ip_set_nfnl_put(info->match_set.index); | |
109 | + ip_set_nfnl_put(par->net, info->match_set.index); | |
110 | 110 | } |
111 | 111 | |
112 | 112 | /* Revision 1 match */ |
... | ... | @@ -131,7 +131,7 @@ |
131 | 131 | struct xt_set_info_match_v1 *info = par->matchinfo; |
132 | 132 | ip_set_id_t index; |
133 | 133 | |
134 | - index = ip_set_nfnl_get_byindex(info->match_set.index); | |
134 | + index = ip_set_nfnl_get_byindex(par->net, info->match_set.index); | |
135 | 135 | |
136 | 136 | if (index == IPSET_INVALID_ID) { |
137 | 137 | pr_warning("Cannot find set indentified by id %u to match\n", |
... | ... | @@ -141,7 +141,7 @@ |
141 | 141 | if (info->match_set.dim > IPSET_DIM_MAX) { |
142 | 142 | pr_warning("Protocol error: set match dimension " |
143 | 143 | "is over the limit!\n"); |
144 | - ip_set_nfnl_put(info->match_set.index); | |
144 | + ip_set_nfnl_put(par->net, info->match_set.index); | |
145 | 145 | return -ERANGE; |
146 | 146 | } |
147 | 147 | |
... | ... | @@ -153,7 +153,7 @@ |
153 | 153 | { |
154 | 154 | struct xt_set_info_match_v1 *info = par->matchinfo; |
155 | 155 | |
156 | - ip_set_nfnl_put(info->match_set.index); | |
156 | + ip_set_nfnl_put(par->net, info->match_set.index); | |
157 | 157 | } |
158 | 158 | |
159 | 159 | /* Revision 3 match */ |
... | ... | @@ -228,7 +228,7 @@ |
228 | 228 | ip_set_id_t index; |
229 | 229 | |
230 | 230 | if (info->add_set.index != IPSET_INVALID_ID) { |
231 | - index = ip_set_nfnl_get_byindex(info->add_set.index); | |
231 | + index = ip_set_nfnl_get_byindex(par->net, info->add_set.index); | |
232 | 232 | if (index == IPSET_INVALID_ID) { |
233 | 233 | pr_warning("Cannot find add_set index %u as target\n", |
234 | 234 | info->add_set.index); |
235 | 235 | |
... | ... | @@ -237,12 +237,12 @@ |
237 | 237 | } |
238 | 238 | |
239 | 239 | if (info->del_set.index != IPSET_INVALID_ID) { |
240 | - index = ip_set_nfnl_get_byindex(info->del_set.index); | |
240 | + index = ip_set_nfnl_get_byindex(par->net, info->del_set.index); | |
241 | 241 | if (index == IPSET_INVALID_ID) { |
242 | 242 | pr_warning("Cannot find del_set index %u as target\n", |
243 | 243 | info->del_set.index); |
244 | 244 | if (info->add_set.index != IPSET_INVALID_ID) |
245 | - ip_set_nfnl_put(info->add_set.index); | |
245 | + ip_set_nfnl_put(par->net, info->add_set.index); | |
246 | 246 | return -ENOENT; |
247 | 247 | } |
248 | 248 | } |
249 | 249 | |
... | ... | @@ -251,9 +251,9 @@ |
251 | 251 | pr_warning("Protocol error: SET target dimension " |
252 | 252 | "is over the limit!\n"); |
253 | 253 | if (info->add_set.index != IPSET_INVALID_ID) |
254 | - ip_set_nfnl_put(info->add_set.index); | |
254 | + ip_set_nfnl_put(par->net, info->add_set.index); | |
255 | 255 | if (info->del_set.index != IPSET_INVALID_ID) |
256 | - ip_set_nfnl_put(info->del_set.index); | |
256 | + ip_set_nfnl_put(par->net, info->del_set.index); | |
257 | 257 | return -ERANGE; |
258 | 258 | } |
259 | 259 | |
260 | 260 | |
... | ... | @@ -270,9 +270,9 @@ |
270 | 270 | const struct xt_set_info_target_v0 *info = par->targinfo; |
271 | 271 | |
272 | 272 | if (info->add_set.index != IPSET_INVALID_ID) |
273 | - ip_set_nfnl_put(info->add_set.index); | |
273 | + ip_set_nfnl_put(par->net, info->add_set.index); | |
274 | 274 | if (info->del_set.index != IPSET_INVALID_ID) |
275 | - ip_set_nfnl_put(info->del_set.index); | |
275 | + ip_set_nfnl_put(par->net, info->del_set.index); | |
276 | 276 | } |
277 | 277 | |
278 | 278 | /* Revision 1 target */ |
... | ... | @@ -301,7 +301,7 @@ |
301 | 301 | ip_set_id_t index; |
302 | 302 | |
303 | 303 | if (info->add_set.index != IPSET_INVALID_ID) { |
304 | - index = ip_set_nfnl_get_byindex(info->add_set.index); | |
304 | + index = ip_set_nfnl_get_byindex(par->net, info->add_set.index); | |
305 | 305 | if (index == IPSET_INVALID_ID) { |
306 | 306 | pr_warning("Cannot find add_set index %u as target\n", |
307 | 307 | info->add_set.index); |
308 | 308 | |
... | ... | @@ -310,12 +310,12 @@ |
310 | 310 | } |
311 | 311 | |
312 | 312 | if (info->del_set.index != IPSET_INVALID_ID) { |
313 | - index = ip_set_nfnl_get_byindex(info->del_set.index); | |
313 | + index = ip_set_nfnl_get_byindex(par->net, info->del_set.index); | |
314 | 314 | if (index == IPSET_INVALID_ID) { |
315 | 315 | pr_warning("Cannot find del_set index %u as target\n", |
316 | 316 | info->del_set.index); |
317 | 317 | if (info->add_set.index != IPSET_INVALID_ID) |
318 | - ip_set_nfnl_put(info->add_set.index); | |
318 | + ip_set_nfnl_put(par->net, info->add_set.index); | |
319 | 319 | return -ENOENT; |
320 | 320 | } |
321 | 321 | } |
322 | 322 | |
... | ... | @@ -324,9 +324,9 @@ |
324 | 324 | pr_warning("Protocol error: SET target dimension " |
325 | 325 | "is over the limit!\n"); |
326 | 326 | if (info->add_set.index != IPSET_INVALID_ID) |
327 | - ip_set_nfnl_put(info->add_set.index); | |
327 | + ip_set_nfnl_put(par->net, info->add_set.index); | |
328 | 328 | if (info->del_set.index != IPSET_INVALID_ID) |
329 | - ip_set_nfnl_put(info->del_set.index); | |
329 | + ip_set_nfnl_put(par->net, info->del_set.index); | |
330 | 330 | return -ERANGE; |
331 | 331 | } |
332 | 332 | |
333 | 333 | |
... | ... | @@ -339,9 +339,9 @@ |
339 | 339 | const struct xt_set_info_target_v1 *info = par->targinfo; |
340 | 340 | |
341 | 341 | if (info->add_set.index != IPSET_INVALID_ID) |
342 | - ip_set_nfnl_put(info->add_set.index); | |
342 | + ip_set_nfnl_put(par->net, info->add_set.index); | |
343 | 343 | if (info->del_set.index != IPSET_INVALID_ID) |
344 | - ip_set_nfnl_put(info->del_set.index); | |
344 | + ip_set_nfnl_put(par->net, info->del_set.index); | |
345 | 345 | } |
346 | 346 | |
347 | 347 | /* Revision 2 target */ |
net/sched/em_ipset.c
... | ... | @@ -24,11 +24,12 @@ |
24 | 24 | { |
25 | 25 | struct xt_set_info *set = data; |
26 | 26 | ip_set_id_t index; |
27 | + struct net *net = qdisc_dev(tp->q)->nd_net; | |
27 | 28 | |
28 | 29 | if (data_len != sizeof(*set)) |
29 | 30 | return -EINVAL; |
30 | 31 | |
31 | - index = ip_set_nfnl_get_byindex(set->index); | |
32 | + index = ip_set_nfnl_get_byindex(net, set->index); | |
32 | 33 | if (index == IPSET_INVALID_ID) |
33 | 34 | return -ENOENT; |
34 | 35 | |
... | ... | @@ -37,7 +38,7 @@ |
37 | 38 | if (em->data) |
38 | 39 | return 0; |
39 | 40 | |
40 | - ip_set_nfnl_put(index); | |
41 | + ip_set_nfnl_put(net, index); | |
41 | 42 | return -ENOMEM; |
42 | 43 | } |
43 | 44 | |
... | ... | @@ -45,7 +46,7 @@ |
45 | 46 | { |
46 | 47 | const struct xt_set_info *set = (const void *) em->data; |
47 | 48 | if (set) { |
48 | - ip_set_nfnl_put(set->index); | |
49 | + ip_set_nfnl_put(qdisc_dev(p->q)->nd_net, set->index); | |
49 | 50 | kfree((void *) em->data); |
50 | 51 | } |
51 | 52 | } |