diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | ChangeLog | 27 | ||||
-rw-r--r-- | configure.ac | 23 | ||||
-rw-r--r-- | include/libipset/session.h | 3 | ||||
-rw-r--r-- | kernel/ChangeLog | 35 | ||||
-rw-r--r-- | kernel/include/linux/netfilter/ipset/ip_set.h | 4 | ||||
-rw-r--r-- | kernel/include/linux/netfilter/ipset/ip_set_compat.h.in | 21 | ||||
-rw-r--r-- | kernel/net/netfilter/ipset/Kconfig | 2 | ||||
-rw-r--r-- | kernel/net/netfilter/ipset/ip_set_bitmap_gen.h | 14 | ||||
-rw-r--r-- | kernel/net/netfilter/ipset/ip_set_core.c | 129 | ||||
-rw-r--r-- | kernel/net/netfilter/ipset/ip_set_hash_gen.h | 19 | ||||
-rw-r--r-- | kernel/net/netfilter/ipset/ip_set_hash_netiface.c | 10 | ||||
-rw-r--r-- | kernel/net/netfilter/ipset/ip_set_hash_netportnet.c | 1 | ||||
-rw-r--r-- | kernel/net/netfilter/ipset/ip_set_list_set.c | 13 | ||||
-rw-r--r-- | lib/Makefile.am | 1 | ||||
-rw-r--r-- | lib/data.c | 2 | ||||
-rw-r--r-- | lib/ipset.c | 4 | ||||
-rw-r--r-- | lib/print.c | 19 | ||||
-rw-r--r-- | lib/session.c | 117 | ||||
-rw-r--r-- | src/ipset.8 | 6 | ||||
-rw-r--r-- | src/ui.c | 2 | ||||
-rw-r--r-- | tests/hash:ip,port.t | 8 | ||||
-rw-r--r-- | tests/hash:ip,port.t.list2 | 2 | ||||
-rwxr-xr-x | tests/netnetgen.sh | 2 | ||||
-rw-r--r-- | tests/restore.t | 24 | ||||
-rwxr-xr-x | tests/setlist_resize.sh | 6 |
26 files changed, 395 insertions, 101 deletions
@@ -16,6 +16,8 @@ Makefile.in *.mod.o.cmd *.mod.cmd *.mod +*.order.cmd +*.symvers.cmd .tmp_versions Module.symvers modules.order @@ -1,3 +1,30 @@ +7.21 + - The patch "Fix hex literals in json output" broke save mode, restore it + - Fix -Werror=format-extra-args warning + - Workaround misleading -Wstringop-truncation warning + +7.20 + - Ignore *.order.cmd and *.symvers.cmd files in kernel builds + - Bash completion utility updated + - Fix json output for -name option (Mark) + - Fix hex literals in json output + - tests: increase timeout to cope with slow virtual test machine + +7.19 + - build: Fix the double-prefix in pkgconfig (Sam James) + +7.18 + - Add json output to list command (Thomas Oberhammer) + - tests: hash:ip,port.t: Replace VRRP by GRE protocol (Phil Sutter) + - tests: hash:ip,port.t: 'vrrp' is printed as 'carp' (Phil Sutter) + - tests: cidr.sh: Add ipcalc fallback (Phil Sutter) + - tests: xlate: Make test input valid (Phil Sutter) + - tests: xlate: Test built binary by default (Phil Sutter) + - xlate: Drop dead code (Phil Sutter) + - xlate: Fix for fd leak in error path (Phil Sutter) + - configure.ac: fix bashisms (Sam James) + - lib/Makefile.am: fix pkgconfig dir (Sam James) + 7.17 - Tests: When verifying comments/timeouts, make sure entries don't expire - Tests: Make sure the internal batches add the correct number of elements diff --git a/configure.ac b/configure.ac index dc11b14..db9e3f8 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ dnl Boilerplate -AC_INIT([ipset], [7.17], [kadlec@netfilter.org]) +AC_INIT([ipset], [7.21], [kadlec@netfilter.org]) AC_CONFIG_AUX_DIR([build-aux]) AC_CANONICAL_HOST AC_CONFIG_MACRO_DIR([m4]) @@ -14,6 +14,7 @@ LT_CONFIG_LTDL_DIR([libltdl]) LTDL_INIT([nonrecursive]) PKG_PROG_PKG_CONFIG +PKG_INSTALLDIR dnl Shortcut: Linux supported alone case "$host" in @@ -724,6 +725,16 @@ else AC_SUBST(HAVE_TIMER_SETUP, undef) fi +AC_MSG_CHECKING([kernel source for timer_shutdown_sync() in timer.h]) +if test -f $ksourcedir/include/linux/timer.h && \ + $GREP -q ' timer_shutdown_sync' $ksourcedir/include/linux/timer.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_TIMER_SHUTDOWN_SYNC, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_TIMER_SHUTDOWN_SYNC, undef) +fi + AC_MSG_CHECKING([kernel source for lockdep_nfnl_is_held() in nfnetlink.h]) if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \ $GREP -q ' lockdep_nfnl_is_held' $ksourcedir/include/linux/netfilter/nfnetlink.h; then @@ -754,6 +765,16 @@ else AC_SUBST(HAVE_STRSCPY, undef) fi +AC_MSG_CHECKING([kernel source for strscpy_pad() in string.h]) +if test -f $ksourcedir/include/linux/timer.h && \ + $GREP -q ' strscpy_pad' $ksourcedir/include/linux/string.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_STRSCPY_PAD, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_STRSCPY, undef) +fi + AC_MSG_CHECKING([kernel source for synchronize_rcu_bh() in rcutiny.h and rcupdate.h]) if test -f $ksourcedir/include/linux/rcupdate.h && \ $GREP -q 'static inline void synchronize_rcu_bh' \ diff --git a/include/libipset/session.h b/include/libipset/session.h index 5f18a6e..365e17e 100644 --- a/include/libipset/session.h +++ b/include/libipset/session.h @@ -84,6 +84,8 @@ enum ipset_envopt { IPSET_ENV_LIST_SETNAME = (1 << IPSET_ENV_BIT_LIST_SETNAME), IPSET_ENV_BIT_LIST_HEADER = 5, IPSET_ENV_LIST_HEADER = (1 << IPSET_ENV_BIT_LIST_HEADER), + IPSET_ENV_BIT_QUOTED = 6, + IPSET_ENV_QUOTED = (1 << IPSET_ENV_BIT_QUOTED), }; extern bool ipset_envopt_test(struct ipset_session *session, @@ -98,6 +100,7 @@ enum ipset_output_mode { IPSET_LIST_PLAIN, IPSET_LIST_SAVE, IPSET_LIST_XML, + IPSET_LIST_JSON, }; extern int ipset_session_output(struct ipset_session *session, diff --git a/kernel/ChangeLog b/kernel/ChangeLog index fd23007..1b05fbd 100644 --- a/kernel/ChangeLog +++ b/kernel/ChangeLog @@ -1,3 +1,38 @@ +7.21 + - netfilter: ipset: Suppress false sparse warnings + - tests: Verify module unload when sets with timeout were just destroyed + - netfilter: ipset: remove set destroy at ip_set module removal + - netfilter: ipset: Cleanup the code of destroy operation and explain + the two stages in comments + - netfilter: ipset: Missing gc cancellations fixed + +7.20 + - treewide: Convert del_timer*() to timer_shutdown*() (Steven Rostedt) + - Use timer_shutdown_sync() when available, instead of del_timer_sync() + - netfilter: ipset: fix race condition between swap/destroy and kernel + side add/del/test v4 + - netfilter: ipset: fix race condition between swap/destroy and kernel + side add/del/test v3 + - netfilter: ipset: fix race condition between swap/destroy and kernel + side add/del/test v2 + - netfilter: ipset: fix race condition between swap/destroy and kernel + side add/del/test + +7.18 + - netfilter: ipset: Fix race between IPSET_CMD_CREATE and IPSET_CMD_SWAP + (reported by Kyle Zeng) + - netfilter: ipset: add the missing IP_SET_HASH_WITH_NET0 macro for + ip_set_hash_netportnet.c (Kyle Zeng) + - compatibility: handle strscpy_pad() + - netfilter: ipset: refactor deprecated strncpy (Justin Stitt) + - netfilter: ipset: remove rcu_read_lock_bh pair from ip_set_test + (Florian Westphal) + - netfilter: ipset: Replace strlcpy with strscpy (Azeem Shaikh) + - netfilter: ipset: Add schedule point in call_ad(). (Kuniyuki Iwashima) + - net: Kconfig: fix spellos (Randy Dunlap) + - netfilter: ipset: Fix overflow before widen in the bitmap_ip_create() + function. (Gavrilov Ilia) + 7.17 - netfilter: ipset: Rework long task execution when adding/deleting entries - netfilter: ipset: fix hash:net,port,net hang with /0 subnet diff --git a/kernel/include/linux/netfilter/ipset/ip_set.h b/kernel/include/linux/netfilter/ipset/ip_set.h index 0c6eee2..7691b7a 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set.h +++ b/kernel/include/linux/netfilter/ipset/ip_set.h @@ -189,6 +189,8 @@ struct ip_set_type_variant { /* Return true if "b" set is the same as "a" * according to the create set parameters */ bool (*same_set)(const struct ip_set *a, const struct ip_set *b); + /* Cancel ongoing garbage collectors before destroying the set*/ + void (*cancel_gc)(struct ip_set *set); /* Region-locking is used */ bool region_lock; }; @@ -245,6 +247,8 @@ extern void ip_set_type_unregister(struct ip_set_type *set_type); /* A generic IP set */ struct ip_set { + /* For call_cru in destroy */ + struct rcu_head rcu; /* The name of the set */ char name[IPSET_MAXNAMELEN]; /* Lock protecting the set data */ diff --git a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in index 7d3f536..5746f39 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in +++ b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in @@ -51,7 +51,9 @@ #@HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS@ HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS #@HAVE_TYPEDEF_SCTP_SCTPHDR_T@ HAVE_TYPEDEF_SCTP_SCTPHDR_T #@HAVE_TIMER_SETUP@ HAVE_TIMER_SETUP +#@HAVE_TIMER_SHUTDOWN_SYNC@ HAVE_TIMER_SHUTDOWN_SYNC #@HAVE_STRSCPY@ HAVE_STRSCPY +#@HAVE_STRSCPY_PAD@ HAVE_STRSCPY_PAD #@HAVE_SYNCHRONIZE_RCU_BH@ HAVE_SYNCHRONIZE_RCU_BH #@HAVE_LOCKDEP_NFNL_IS_HELD@ HAVE_LOCKDEP_NFNL_IS_HELD #@HAVE_COND_RESCHED_RCU@ HAVE_COND_RESCHED_RCU @@ -505,6 +507,10 @@ static inline struct nlmsghdr *nfnl_msg_put(struct sk_buff *skb, u32 portid, struct type *var = set->data #endif +#ifndef HAVE_TIMER_SHUTDOWN_SYNC +#define timer_shutdown_sync(timer) del_timer_sync(timer) +#endif + #ifndef HAVE_STRSCPY static inline ssize_t strscpy(char * dest, const char * src, size_t count) { @@ -514,6 +520,21 @@ static inline ssize_t strscpy(char * dest, const char * src, size_t count) } #endif +#ifndef HAVE_STRSCPY_PAD +static inline ssize_t strscpy_pad(char *dest, const char *src, size_t count) +{ + ssize_t written; + + written = strscpy(dest, src, count); + if (written < 0 || written == count - 1) + return written; + + memset(dest + written + 1, 0, count - written - 1); + + return written; +} +#endif + #ifndef HAVE_NLA_STRSCPY #define nla_strscpy nla_strlcpy #endif diff --git a/kernel/net/netfilter/ipset/Kconfig b/kernel/net/netfilter/ipset/Kconfig index 861659f..8772af5 100644 --- a/kernel/net/netfilter/ipset/Kconfig +++ b/kernel/net/netfilter/ipset/Kconfig @@ -29,7 +29,7 @@ config IP_SET_BITMAP_IP depends on IP_SET help This option adds the bitmap:ip set type support, by which one - can store IPv4 addresses (or network addresse) from a range. + can store IPv4 addresses (or network addresses) from a range. To compile it as a module, choose M here. If unsure, say N. diff --git a/kernel/net/netfilter/ipset/ip_set_bitmap_gen.h b/kernel/net/netfilter/ipset/ip_set_bitmap_gen.h index 0479750..3245b6b 100644 --- a/kernel/net/netfilter/ipset/ip_set_bitmap_gen.h +++ b/kernel/net/netfilter/ipset/ip_set_bitmap_gen.h @@ -29,6 +29,7 @@ #define mtype_del IPSET_TOKEN(MTYPE, _del) #define mtype_list IPSET_TOKEN(MTYPE, _list) #define mtype_gc IPSET_TOKEN(MTYPE, _gc) +#define mtype_cancel_gc IPSET_TOKEN(MTYPE, _cancel_gc) #define mtype MTYPE #define get_ext(set, map, id) ((map)->extensions + ((set)->dsize * (id))) @@ -58,9 +59,6 @@ mtype_destroy(struct ip_set *set) { struct mtype *map = set->data; - if (SET_WITH_TIMEOUT(set)) - del_timer_sync(&map->gc); - if (set->dsize && set->extensions & IPSET_EXT_DESTROY) mtype_ext_cleanup(set); ip_set_free(map->members); @@ -290,6 +288,15 @@ mtype_gc(GC_ARG) add_timer(&map->gc); } +static void +mtype_cancel_gc(struct ip_set *set) +{ + struct mtype *map = set->data; + + if (SET_WITH_TIMEOUT(set)) + del_timer_sync(&map->gc); +} + static const struct ip_set_type_variant mtype = { .kadt = mtype_kadt, .uadt = mtype_uadt, @@ -303,6 +310,7 @@ static const struct ip_set_type_variant mtype = { .head = mtype_head, .list = mtype_list, .same_set = mtype_same_set, + .cancel_gc = mtype_cancel_gc, }; #endif /* __IP_SET_BITMAP_IP_GEN_H */ diff --git a/kernel/net/netfilter/ipset/ip_set_core.c b/kernel/net/netfilter/ipset/ip_set_core.c index a80b999..c31dbc3 100644 --- a/kernel/net/netfilter/ipset/ip_set_core.c +++ b/kernel/net/netfilter/ipset/ip_set_core.c @@ -30,7 +30,6 @@ static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */ struct ip_set_net { struct ip_set * __rcu *ip_set_list; /* all individual sets */ ip_set_id_t ip_set_max; /* max number of sets */ - bool is_deleted; /* deleted by ip_set_net_exit */ bool is_destroyed; /* all sets are destroyed */ }; @@ -62,6 +61,8 @@ MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET); ip_set_dereference((inst)->ip_set_list)[id] #define ip_set_ref_netlink(inst,id) \ rcu_dereference_raw((inst)->ip_set_list)[id] +#define ip_set_dereference_nfnl(p) \ + rcu_dereference_check(p, lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET)) /* The set types are implemented in modules and registered set types * can be found in ip_set_type_list. Adding/deleting types is @@ -684,6 +685,14 @@ __ip_set_put(struct ip_set *set) * a separate reference counter */ static void +__ip_set_get_netlink(struct ip_set *set) +{ + write_lock_bh(&ip_set_ref_lock); + set->ref_netlink++; + write_unlock_bh(&ip_set_ref_lock); +} + +static void __ip_set_put_netlink(struct ip_set *set) { write_lock_bh(&ip_set_ref_lock); @@ -701,15 +710,10 @@ __ip_set_put_netlink(struct ip_set *set) static struct ip_set * ip_set_rcu_get(struct net *net, ip_set_id_t index) { - struct ip_set *set; struct ip_set_net *inst = ip_set_pernet(net); - rcu_read_lock(); - /* ip_set_list itself needs to be protected */ - set = rcu_dereference(inst->ip_set_list)[index]; - rcu_read_unlock(); - - return set; + /* ip_set_list and the set pointer need to be protected */ + return ip_set_dereference_nfnl(inst->ip_set_list)[index]; } static inline void @@ -740,9 +744,7 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb, !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) return 0; - rcu_read_lock_bh(); ret = set->variant->kadt(set, skb, par, IPSET_TEST, opt); - rcu_read_unlock_bh(); if (ret == -EAGAIN) { /* Type requests element to be completed */ @@ -875,7 +877,7 @@ ip_set_name_byindex(struct net *net, ip_set_id_t index, char *name) BUG_ON(!set); read_lock_bh(&ip_set_ref_lock); - strncpy(name, set->name, IPSET_MAXNAMELEN); + strscpy_pad(name, set->name, IPSET_MAXNAMELEN); read_unlock_bh(&ip_set_ref_lock); } EXPORT_SYMBOL_GPL(ip_set_name_byindex); @@ -923,11 +925,9 @@ ip_set_nfnl_put(struct net *net, ip_set_id_t index) struct ip_set_net *inst = ip_set_pernet(net); nfnl_lock(NFNL_SUBSYS_IPSET); - if (!inst->is_deleted) { /* already deleted from ip_set_net_exit() */ - set = ip_set(inst, index); - if (set) - __ip_set_put(set); - } + set = ip_set(inst, index); + if (set) + __ip_set_put(set); nfnl_unlock(NFNL_SUBSYS_IPSET); } EXPORT_SYMBOL_GPL(ip_set_nfnl_put); @@ -1161,6 +1161,7 @@ IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl, return ret; cleanup: + set->variant->cancel_gc(set); set->variant->destroy(set); put_out: module_put(set->type->me); @@ -1178,17 +1179,50 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = { .len = IPSET_MAXNAMELEN - 1 }, }; +/* Destroying a set is split into two stages when a DESTROY command issued: + * - Cancel garbage collectors and decrement the module reference counter: + * - Cancelling may wait and we are allowed to do it at this stage. + * - Module remove is protected by rcu_barrier() which waits for + * the second stage to be finished. + * - In order to prevent the race between kernel side add/del/test element + * operations and destroy, the destroying of the set data areas are + * performed via a call_rcu() call. + */ + +/* Call set variant specific destroy function and reclaim the set data. */ static void -ip_set_destroy_set(struct ip_set *set) +ip_set_destroy_set_variant(struct ip_set *set) { - pr_debug("set: %s\n", set->name); - /* Must call it without holding any lock */ set->variant->destroy(set); - module_put(set->type->me); kfree(set); } +static void +ip_set_destroy_set_variant_rcu(struct rcu_head *head) +{ + struct ip_set *set = container_of(head, struct ip_set, rcu); + + ip_set_destroy_set_variant(set); +} + +/* Cancel the garbage collectors and decrement module references */ +static void +ip_set_destroy_cancel_gc(struct ip_set *set) +{ + set->variant->cancel_gc(set); + module_put(set->type->me); +} + +/* Use when we may wait for the complete destroy to be finished. + */ +static void +ip_set_destroy_set(struct ip_set *set) +{ + ip_set_destroy_cancel_gc(set); + ip_set_destroy_set_variant(set); +} + static int IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, @@ -1204,9 +1238,6 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl, if (unlikely(protocol_min_failed(attr))) return -IPSET_ERR_PROTOCOL; - /* Must wait for flush to be really finished in list:set */ - rcu_barrier(); - /* Commands are serialized and references are * protected by the ip_set_ref_lock. * External systems (i.e. xt_set) must call @@ -1217,8 +1248,10 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl, * counter, so if it's already zero, we can proceed * without holding the lock. */ - read_lock_bh(&ip_set_ref_lock); if (!attr[IPSET_ATTR_SETNAME]) { + /* Must wait for flush to be really finished in list:set */ + rcu_barrier(); + read_lock_bh(&ip_set_ref_lock); for (i = 0; i < inst->ip_set_max; i++) { s = ip_set(inst, i); if (s && (s->ref || s->ref_netlink)) { @@ -1239,6 +1272,9 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl, inst->is_destroyed = false; } else { u32 flags = flag_exist(INFO_NLH(info, nlh)); + u16 features = 0; + + read_lock_bh(&ip_set_ref_lock); s = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]), &i); if (!s) { @@ -1249,10 +1285,16 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl, ret = -IPSET_ERR_BUSY; goto out; } + features = s->type->features; ip_set(inst, i) = NULL; read_unlock_bh(&ip_set_ref_lock); - - ip_set_destroy_set(s); + if (features & IPSET_TYPE_NAME) { + /* Must wait for flush to be really finished */ + rcu_barrier(); + } + /* Must cancel garbage collectors */ + ip_set_destroy_cancel_gc(s); + call_rcu(&s->rcu, ip_set_destroy_set_variant_rcu); } return 0; out: @@ -1350,11 +1392,11 @@ IPSET_CBFN(ip_set_rename, struct net *net, struct sock *ctnl, goto out; } } - ret = strscpy(set->name, name2, IPSET_MAXNAMELEN); + strscpy_pad(set->name, name2, IPSET_MAXNAMELEN); out: write_unlock_bh(&ip_set_ref_lock); - return ret < 0 ? ret : 0; + return ret; } /* Swap two sets so that name/index points to the other. @@ -1408,9 +1450,9 @@ IPSET_CBFN(ip_set_swap, struct net *net, struct sock *ctnl, return -EBUSY; } - strncpy(from_name, from->name, IPSET_MAXNAMELEN); - strncpy(from->name, to->name, IPSET_MAXNAMELEN); - strncpy(to->name, from_name, IPSET_MAXNAMELEN); + strscpy_pad(from_name, from->name, IPSET_MAXNAMELEN); + strscpy_pad(from->name, to->name, IPSET_MAXNAMELEN); + strscpy_pad(to->name, from_name, IPSET_MAXNAMELEN); swap(from->ref, to->ref); ip_set(inst, from_id) = to; @@ -1750,6 +1792,14 @@ CALL_AD(struct net *net, struct sock *ctnl, struct sk_buff *skb, bool eexist = flags & IPSET_FLAG_EXIST, retried = false; do { + if (retried) { + __ip_set_get_netlink(set); + nfnl_unlock(NFNL_SUBSYS_IPSET); + cond_resched(); + nfnl_lock(NFNL_SUBSYS_IPSET); + __ip_set_put_netlink(set); + } + ip_set_lock(set); ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried); ip_set_unlock(set); @@ -2431,7 +2481,6 @@ ip_set_net_init(struct net *net) #else goto err_alloc; #endif - inst->is_deleted = false; inst->is_destroyed = false; rcu_assign_pointer(inst->ip_set_list, list); return 0; @@ -2448,20 +2497,6 @@ ip_set_net_exit(struct net *net) { struct ip_set_net *inst = ip_set_pernet(net); - struct ip_set *set = NULL; - ip_set_id_t i; - - inst->is_deleted = true; /* flag for ip_set_nfnl_put */ - - nfnl_lock(NFNL_SUBSYS_IPSET); - for (i = 0; i < inst->ip_set_max; i++) { - set = ip_set(inst, i); - if (set) { - ip_set(inst, i) = NULL; - ip_set_destroy_set(set); - } - } - nfnl_unlock(NFNL_SUBSYS_IPSET); kvfree(rcu_dereference_protected(inst->ip_set_list, 1)); #ifndef HAVE_NET_OPS_ID kvfree(inst); @@ -2526,8 +2561,8 @@ ip_set_fini(void) { nf_unregister_sockopt(&so_set); nfnetlink_subsys_unregister(&ip_set_netlink_subsys); - UNREGISTER_PERNET_SUBSYS(&ip_set_net_ops); + pr_debug("these are the famous last words\n"); } diff --git a/kernel/net/netfilter/ipset/ip_set_hash_gen.h b/kernel/net/netfilter/ipset/ip_set_hash_gen.h index af38991..76c3894 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_gen.h +++ b/kernel/net/netfilter/ipset/ip_set_hash_gen.h @@ -222,6 +222,7 @@ static const union nf_inet_addr zeromask = {}; #undef mtype_gc_do #undef mtype_gc #undef mtype_gc_init +#undef mtype_cancel_gc #undef mtype_variant #undef mtype_data_match @@ -266,6 +267,7 @@ static const union nf_inet_addr zeromask = {}; #define mtype_gc_do IPSET_TOKEN(MTYPE, _gc_do) #define mtype_gc IPSET_TOKEN(MTYPE, _gc) #define mtype_gc_init IPSET_TOKEN(MTYPE, _gc_init) +#define mtype_cancel_gc IPSET_TOKEN(MTYPE, _cancel_gc) #define mtype_variant IPSET_TOKEN(MTYPE, _variant) #define mtype_data_match IPSET_TOKEN(MTYPE, _data_match) @@ -430,7 +432,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy) u32 i; for (i = 0; i < jhash_size(t->htable_bits); i++) { - n = __ipset_dereference(hbucket(t, i)); + n = (__force struct hbucket *)hbucket(t, i); if (!n) continue; if (set->extensions & IPSET_EXT_DESTROY && ext_destroy) @@ -450,10 +452,7 @@ mtype_destroy(struct ip_set *set) struct htype *h = set->data; struct list_head *l, *lt; - if (SET_WITH_TIMEOUT(set)) - cancel_delayed_work_sync(&h->gc.dwork); - - mtype_ahash_destroy(set, ipset_dereference_nfnl(h->table), true); + mtype_ahash_destroy(set, (__force struct htable *)h->table, true); list_for_each_safe(l, lt, &h->ad) { list_del(l); kfree(l); @@ -598,6 +597,15 @@ mtype_gc_init(struct htable_gc *gc) queue_delayed_work(system_power_efficient_wq, &gc->dwork, HZ); } +static void +mtype_cancel_gc(struct ip_set *set) +{ + struct htype *h = set->data; + + if (SET_WITH_TIMEOUT(set)) + cancel_delayed_work_sync(&h->gc.dwork); +} + static int mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, struct ip_set_ext *mext, u32 flags); @@ -1441,6 +1449,7 @@ static const struct ip_set_type_variant mtype_variant = { .uref = mtype_uref, .resize = mtype_resize, .same_set = mtype_same_set, + .cancel_gc = mtype_cancel_gc, .region_lock = true, }; diff --git a/kernel/net/netfilter/ipset/ip_set_hash_netiface.c b/kernel/net/netfilter/ipset/ip_set_hash_netiface.c index af210c7..5baa852 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_netiface.c @@ -41,7 +41,7 @@ MODULE_ALIAS("ip_set_hash:net,iface"); #define IP_SET_HASH_WITH_MULTI #define IP_SET_HASH_WITH_NET0 -#define STRLCPY(a, b) strlcpy(a, b, IFNAMSIZ) +#define STRSCPY(a, b) strscpy(a, b, IFNAMSIZ) /* IPv4 variant */ @@ -183,11 +183,11 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb, if (!eiface) return -EINVAL; - STRLCPY(e.iface, eiface); + STRSCPY(e.iface, eiface); e.physdev = 1; #endif } else { - STRLCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out)); + STRSCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out)); } if (strlen(e.iface) == 0) @@ -401,11 +401,11 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb, if (!eiface) return -EINVAL; - STRLCPY(e.iface, eiface); + STRSCPY(e.iface, eiface); e.physdev = 1; #endif } else { - STRLCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out)); + STRSCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out)); } if (strlen(e.iface) == 0) diff --git a/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c b/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c index fd080ab..d5774a1 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c @@ -37,6 +37,7 @@ MODULE_ALIAS("ip_set_hash:net,port,net"); #define IP_SET_HASH_WITH_PROTO #define IP_SET_HASH_WITH_NETS #define IPSET_NET_COUNT 2 +#define IP_SET_HASH_WITH_NET0 /* IPv4 variant */ diff --git a/kernel/net/netfilter/ipset/ip_set_list_set.c b/kernel/net/netfilter/ipset/ip_set_list_set.c index 8c7fef8..cc2e5b9 100644 --- a/kernel/net/netfilter/ipset/ip_set_list_set.c +++ b/kernel/net/netfilter/ipset/ip_set_list_set.c @@ -429,9 +429,6 @@ list_set_destroy(struct ip_set *set) struct list_set *map = set->data; struct set_elem *e, *n; - if (SET_WITH_TIMEOUT(set)) - del_timer_sync(&map->gc); - list_for_each_entry_safe(e, n, &map->members, list) { list_del(&e->list); ip_set_put_byindex(map->net, e->id); @@ -548,6 +545,15 @@ list_set_same_set(const struct ip_set *a, const struct ip_set *b) a->extensions == b->extensions; } +static void +list_set_cancel_gc(struct ip_set *set) +{ + struct list_set *map = set->data; + + if (SET_WITH_TIMEOUT(set)) + timer_shutdown_sync(&map->gc); +} + static const struct ip_set_type_variant set_variant = { .kadt = list_set_kadt, .uadt = list_set_uadt, @@ -561,6 +567,7 @@ static const struct ip_set_type_variant set_variant = { .head = list_set_head, .list = list_set_list, .same_set = list_set_same_set, + .cancel_gc = list_set_cancel_gc, }; static void diff --git a/lib/Makefile.am b/lib/Makefile.am index 50d937d..a9edf95 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -46,7 +46,6 @@ EXTRA_libipset_la_SOURCES = \ EXTRA_DIST = $(IPSET_SETTYPE_LIST) libipset.map -pkgconfigdir = $(prefix)/$(libdir)/pkgconfig pkgconfig_DATA = libipset.pc dist_man_MANS = libipset.3 @@ -111,7 +111,7 @@ ipset_strlcpy(char *dst, const char *src, size_t len) assert(dst); assert(src); - strncpy(dst, src, len); + memcpy(dst, src, len); dst[len - 1] = '\0'; } diff --git a/lib/ipset.c b/lib/ipset.c index 8e63af5..c910d88 100644 --- a/lib/ipset.c +++ b/lib/ipset.c @@ -235,7 +235,7 @@ const struct ipset_envopts ipset_envopts[] = { { .name = { "-o", "-output" }, .has_arg = IPSET_MANDATORY_ARG, .flag = IPSET_OPT_MAX, .parse = ipset_parse_output, - .help = "plain|save|xml\n" + .help = "plain|save|xml|json\n" " Specify output mode for listing sets.\n" " Default value for \"list\" command is mode \"plain\"\n" " and for \"save\" command is mode \"save\".", @@ -429,6 +429,8 @@ ipset_parse_output(struct ipset *ipset, return ipset_session_output(session, IPSET_LIST_PLAIN); else if (STREQ(str, "xml")) return ipset_session_output(session, IPSET_LIST_XML); + else if (STREQ(str, "json")) + return ipset_session_output(session, IPSET_LIST_JSON); else if (STREQ(str, "save")) return ipset_session_output(session, IPSET_LIST_SAVE); diff --git a/lib/print.c b/lib/print.c index 50f0ad6..6ea79cb 100644 --- a/lib/print.c +++ b/lib/print.c @@ -411,10 +411,11 @@ ipset_print_number(char *buf, unsigned int len, int ipset_print_hexnumber(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, - uint8_t env UNUSED) + uint8_t env) { size_t maxsize; const void *number; + const char *quoted = env & IPSET_ENV_QUOTED ? "\"" : ""; assert(buf); assert(len > 0); @@ -424,17 +425,17 @@ ipset_print_hexnumber(char *buf, unsigned int len, maxsize = ipset_data_sizeof(opt, AF_INET); D("opt: %u, maxsize %zu", opt, maxsize); if (maxsize == sizeof(uint8_t)) - return snprintf(buf, len, "0x%02"PRIx8, - *(const uint8_t *) number); + return snprintf(buf, len, "%s0x%02"PRIx8"%s", + quoted, *(const uint8_t *) number, quoted); else if (maxsize == sizeof(uint16_t)) - return snprintf(buf, len, "0x%04"PRIx16, - *(const uint16_t *) number); + return snprintf(buf, len, "%s0x%04"PRIx16"%s", + quoted, *(const uint16_t *) number, quoted); else if (maxsize == sizeof(uint32_t)) - return snprintf(buf, len, "0x%08"PRIx32, - *(const uint32_t *) number); + return snprintf(buf, len, "%s0x%08"PRIx32"%s", + quoted, *(const uint32_t *) number, quoted); else if (maxsize == sizeof(uint64_t)) - return snprintf(buf, len, "0x%016"PRIx64, - *(const uint64_t *) number); + return snprintf(buf, len, "%s0x%016"PRIx64"%s", + quoted, *(const uint64_t *) number, quoted); else assert(0); return 0; diff --git a/lib/session.c b/lib/session.c index cdc59e0..f822288 100644 --- a/lib/session.c +++ b/lib/session.c @@ -860,6 +860,7 @@ list_adt(struct ipset_session *session, struct nlattr *nla[]) const struct ipset_arg *arg; size_t offset = 0; int i, found = 0; + static char last_setname[IPSET_MAXNAMELEN] = ""; D("enter"); /* Check and load type, family */ @@ -894,6 +895,13 @@ list_adt(struct ipset_session *session, struct nlattr *nla[]) case IPSET_LIST_XML: safe_snprintf(session, "<member><elem>"); break; + case IPSET_LIST_JSON: + /* print separator if a member for this set was printed before */ + if (STREQ(ipset_data_setname(data), last_setname)) + safe_snprintf(session, ","); + strcpy(last_setname, ipset_data_setname(data)); + safe_snprintf(session, "\n {\n \"elem\" : \""); + break; case IPSET_LIST_PLAIN: default: break; @@ -902,6 +910,8 @@ list_adt(struct ipset_session *session, struct nlattr *nla[]) safe_dprintf(session, ipset_print_elem, IPSET_OPT_ELEM); if (session->mode == IPSET_LIST_XML) safe_snprintf(session, "</elem>"); + if (session->mode == IPSET_LIST_JSON) + safe_snprintf(session, "\""); for (i = 0; type->cmd[IPSET_ADD].args[i] != IPSET_ARG_NONE; i++) { arg = ipset_keyword(type->cmd[IPSET_ADD].args[i]); @@ -929,6 +939,15 @@ list_adt(struct ipset_session *session, struct nlattr *nla[]) safe_dprintf(session, arg->print, arg->opt); safe_snprintf(session, "</%s>", arg->name[0]); break; + case IPSET_LIST_JSON: + if (arg->has_arg == IPSET_NO_ARG) { + safe_snprintf(session, + ",\n \"%s\" : true", arg->name[0]); + break; + } + safe_snprintf(session, ",\n \"%s\" : ", arg->name[0]); + safe_dprintf(session, arg->print, arg->opt); + break; default: break; } @@ -936,6 +955,8 @@ list_adt(struct ipset_session *session, struct nlattr *nla[]) if (session->mode == IPSET_LIST_XML) safe_snprintf(session, "</member>\n"); + else if (session->mode == IPSET_LIST_JSON) + safe_snprintf(session, "\n }"); else safe_snprintf(session, "\n"); @@ -972,6 +993,7 @@ list_create(struct ipset_session *session, struct nlattr *nla[]) const struct ipset_arg *arg; uint8_t family; int i; + static bool firstipset = true; for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_CREATE_MAX; i++) if (nla[i]) { @@ -1007,6 +1029,19 @@ list_create(struct ipset_session *session, struct nlattr *nla[]) ipset_data_setname(data), type->name, type->revision); break; + case IPSET_LIST_JSON: + if (!firstipset) + safe_snprintf(session, ",\n"); + firstipset = false; + safe_snprintf(session, + " \{\n" + " \"name\" : \"%s\",\n" + " \"type\" : \"%s\",\n" + " \"revision\" : %u,\n" + " \"header\" : \{\n", + ipset_data_setname(data), + type->name, type->revision); + break; default: break; } @@ -1042,6 +1077,22 @@ list_create(struct ipset_session *session, struct nlattr *nla[]) safe_dprintf(session, arg->print, arg->opt); safe_snprintf(session, "</%s>", arg->name[0]); break; + case IPSET_LIST_JSON: + if (arg->has_arg == IPSET_NO_ARG) { + safe_snprintf(session, + " \"%s\" : true,\n", arg->name[0]); + break; + } + if (arg->opt == IPSET_OPT_FAMILY) { + safe_snprintf(session, " \"%s\" : \"", arg->name[0]); + safe_dprintf(session, arg->print, arg->opt); + safe_snprintf(session, "\",\n"); + break; + } + safe_snprintf(session, " \"%s\" : ", arg->name[0]); + safe_dprintf(session, arg->print, arg->opt); + safe_snprintf(session, ",\n"); + break; default: break; } @@ -1079,6 +1130,21 @@ list_create(struct ipset_session *session, struct nlattr *nla[]) "</header>\n" : "</header>\n<members>\n"); break; + case IPSET_LIST_JSON: + safe_snprintf(session, " \"memsize\" : "); + safe_dprintf(session, ipset_print_number, IPSET_OPT_MEMSIZE); + safe_snprintf(session, ",\n \"references\" : "); + safe_dprintf(session, ipset_print_number, IPSET_OPT_REFERENCES); + if (ipset_data_test(data, IPSET_OPT_ELEMENTS)) { + safe_snprintf(session, ",\n \"numentries\" : "); + safe_dprintf(session, ipset_print_number, IPSET_OPT_ELEMENTS); + } + safe_snprintf(session, "\n"); + safe_snprintf(session, + session->envopts & IPSET_ENV_LIST_HEADER ? + " },\n" : + " },\n \"members\" : ["); + break; default: break; } @@ -1214,11 +1280,24 @@ print_set_done(struct ipset_session *session, bool callback_done) if (session->saved_setname[0] != '\0') safe_snprintf(session, "</members>\n</ipset>\n"); break; + case IPSET_LIST_JSON: + if (session->envopts & IPSET_ENV_LIST_SETNAME) + break; + if (session->envopts & IPSET_ENV_LIST_HEADER) { + if (session->saved_setname[0] != '\0') + safe_snprintf(session, " }"); + break; + } + if (session->saved_setname[0] != '\0') + safe_snprintf(session, "\n ]\n }"); + break; default: break; } if (callback_done && session->mode == IPSET_LIST_XML) safe_snprintf(session, "</ipsets>\n"); + if (callback_done && session->mode == IPSET_LIST_JSON) + safe_snprintf(session, "\n]\n"); return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_STOP; } @@ -1227,6 +1306,7 @@ callback_list(struct ipset_session *session, struct nlattr *nla[], enum ipset_cmd cmd) { struct ipset_data *data = session->data; + static bool firstipset = true; if (setjmp(printf_failure)) { session->saved_setname[0] = '\0'; @@ -1245,7 +1325,13 @@ callback_list(struct ipset_session *session, struct nlattr *nla[], if (session->mode == IPSET_LIST_XML) safe_snprintf(session, "<ipset name=\"%s\"/>\n", ipset_data_setname(data)); - else + else if (session->mode == IPSET_LIST_JSON) { + if (!firstipset) + safe_snprintf(session, ",\n"); + firstipset = false; + safe_snprintf(session, " { \"name\" : \"%s\" }", + ipset_data_setname(data)); + } else safe_snprintf(session, "%s\n", ipset_data_setname(data)); return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_OK; @@ -2195,18 +2281,27 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno) session->cmd = cmd; session->lineno = lineno; - /* Set default output mode */ - if (cmd == IPSET_CMD_LIST) { + if (cmd == IPSET_CMD_LIST || cmd == IPSET_CMD_SAVE) { + /* Set default output mode */ if (session->mode == IPSET_LIST_NONE) - session->mode = IPSET_LIST_PLAIN; - } else if (cmd == IPSET_CMD_SAVE) { - if (session->mode == IPSET_LIST_NONE) - session->mode = IPSET_LIST_SAVE; + session->mode = cmd == IPSET_CMD_LIST ? + IPSET_LIST_PLAIN : IPSET_LIST_SAVE; + /* Reset just in case there are multiple modes in a session */ + ipset_envopt_unset(session, IPSET_ENV_QUOTED); + switch (session->mode) { + case IPSET_LIST_XML: + /* Start the root element in XML mode */ + safe_snprintf(session, "<ipsets>\n"); + break; + case IPSET_LIST_JSON: + /* Start the root element in json mode */ + ipset_envopt_set(session, IPSET_ENV_QUOTED); + safe_snprintf(session, "[\n"); + break; + default: + break; + } } - /* Start the root element in XML mode */ - if ((cmd == IPSET_CMD_LIST || cmd == IPSET_CMD_SAVE) && - session->mode == IPSET_LIST_XML) - safe_snprintf(session, "<ipsets>\n"); D("next: build_msg"); /* Build new message or append buffered commands */ diff --git a/src/ipset.8 b/src/ipset.8 index f9a880b..04febda 100644 --- a/src/ipset.8 +++ b/src/ipset.8 @@ -21,7 +21,7 @@ ipset \(em administration tool for IP sets .PP COMMANDS := { \fBcreate\fR | \fBadd\fR | \fBdel\fR | \fBtest\fR | \fBdestroy\fR | \fBlist\fR | \fBsave\fR | \fBrestore\fR | \fBflush\fR | \fBrename\fR | \fBswap\fR | \fBhelp\fR | \fBversion\fR | \fB\-\fR } .PP -\fIOPTIONS\fR := { \fB\-exist\fR | \fB\-output\fR { \fBplain\fR | \fBsave\fR | \fBxml\fR } | \fB\-quiet\fR | \fB\-resolve\fR | \fB\-sorted\fR | \fB\-name\fR | \fB\-terse\fR | \fB\-file\fR \fIfilename\fR } +\fIOPTIONS\fR := { \fB\-exist\fR | \fB\-output\fR { \fBplain\fR | \fBsave\fR | \fBxml\fR } | \fBjson\fR } | \fB\-quiet\fR | \fB\-resolve\fR | \fB\-sorted\fR | \fB\-name\fR | \fB\-terse\fR | \fB\-file\fR \fIfilename\fR } .PP \fBipset\fR \fBcreate\fR \fISETNAME\fR \fITYPENAME\fR [ \fICREATE\-OPTIONS\fR ] .PP @@ -118,7 +118,7 @@ option is given, the entries are listed/saved sorted (which may be slow). The option \fB\-output\fR can be used to control the format of the listing: -\fBplain\fR, \fBsave\fR or \fBxml\fR. +\fBplain\fR, \fBsave\fR, \fBxml\fR or \fBjson\fR. (The default is \fBplain\fR.) If the option @@ -187,7 +187,7 @@ cannot be abbreviated. Ignore errors when exactly the same set is to be created or already added entry is added or missing entry is deleted. .TP -\fB\-o\fP, \fB\-output\fP { \fBplain\fR | \fBsave\fR | \fBxml\fR } +\fB\-o\fP, \fB\-output\fP { \fBplain\fR | \fBsave\fR | \fBxml\fR | \fBjson\fR } Select the output format to the \fBlist\fR command. @@ -180,7 +180,7 @@ const struct ipset_envopts ipset_envopts[] = { { .name = { "-o", "-output" }, .has_arg = IPSET_MANDATORY_ARG, .flag = IPSET_OPT_MAX, .parse = ipset_parse_output, - .help = "plain|save|xml\n" + .help = "plain|save|xml|json\n" " Specify output mode for listing sets.\n" " Default value for \"list\" command is mode \"plain\"\n" " and for \"save\" command is mode \"save\".", diff --git a/tests/hash:ip,port.t b/tests/hash:ip,port.t index addbe3b..f65fb59 100644 --- a/tests/hash:ip,port.t +++ b/tests/hash:ip,port.t @@ -62,10 +62,10 @@ 0 ipset test test 2.0.0.1,tcp:80 # Test element with UDP protocol 0 ipset test test 2.0.0.1,udp:80 -# Add element with vrrp -0 ipset add test 2.0.0.1,vrrp:0 -# Test element with vrrp -0 ipset test test 2.0.0.1,vrrp:0 +# Add element with GRE +0 ipset add test 2.0.0.1,gre:0 +# Test element with GRE +0 ipset test test 2.0.0.1,gre:0 # Add element with sctp 0 ipset add test 2.0.0.1,sctp:80 # Test element with sctp diff --git a/tests/hash:ip,port.t.list2 b/tests/hash:ip,port.t.list2 index 0c5d3a1..2550422 100644 --- a/tests/hash:ip,port.t.list2 +++ b/tests/hash:ip,port.t.list2 @@ -6,6 +6,6 @@ Size in memory: 480 References: 0 Number of entries: 3 Members: -2.0.0.1,carp:0 +2.0.0.1,gre:0 2.0.0.1,tcp:80 2.0.0.1,udp:80 diff --git a/tests/netnetgen.sh b/tests/netnetgen.sh index 64bb70d..32aac18 100755 --- a/tests/netnetgen.sh +++ b/tests/netnetgen.sh @@ -6,7 +6,7 @@ while [ -n "$1" ]; do comment=" comment" ;; timeout) - timeout=" timeout 10" + timeout=" timeout 60" ;; *) ;; diff --git a/tests/restore.t b/tests/restore.t index ffde2d1..dda143f 100644 --- a/tests/restore.t +++ b/tests/restore.t @@ -6,4 +6,28 @@ 0 ipset x # Check auto-increasing maximal number of sets 0 ./setlist_resize.sh +# Create bitmap set with timeout +0 ipset create test1 bitmap:ip range 2.0.0.1-2.1.0.0 timeout 5 +# Add element to bitmap set +0 ipset add test1 2.0.0.2 timeout 30 +# Create hash set with timeout +0 ipset -N test2 iphash --hashsize 128 timeout 4 +# Add element to hash set +0 ipset add test2 2.0.0.3 timeout 30 +# Create list set with timeout +0 ipset -N test3 list:set timeout 3 +# Add bitmap set to list set +0 ipset a test3 test1 timeout 30 +# Add hash set to list set +0 ipset a test3 test2 timeout 30 +# Flush list set +0 ipset f test3 +# Destroy all sets +0 ipset x +# Remove the ip_set_list_set kernel module +0 rmmod ip_set_list_set +# Remove the ip_set_bitmap_ip kernel module +0 rmmod ip_set_bitmap_ip +# Remove the ip_set_hash_ip kernel module +0 rmmod ip_set_hash_ip # eof diff --git a/tests/setlist_resize.sh b/tests/setlist_resize.sh index 3255656..848f1d1 100755 --- a/tests/setlist_resize.sh +++ b/tests/setlist_resize.sh @@ -12,7 +12,7 @@ for x in ip_set_list_set ip_set_hash_netiface ip_set_hash_ipportnet \ ip_set_hash_netportnet ip_set_hash_ipmark ip_set_hash_mac \ ip_set_bitmap_port ip_set_bitmap_ipmac \ ip_set_bitmap_ip xt_set ip_set; do - rmmod $x + rmmod $x >/dev/null 2>&1 done create() { @@ -31,6 +31,6 @@ for x in `seq 1 $loop`; do test `$ipset l -n | wc -l` -eq 1024 || exit 1 $ipset x test `lsmod|grep -w ^ip_set_hash_ip | awk '{print $3}'` -eq 0 || exit 1 - rmmod ip_set_hash_ip - rmmod ip_set + rmmod ip_set_hash_ip >/dev/null 2>&1 + rmmod ip_set >/dev/null 2>&1 done |