diff options
211 files changed, 8485 insertions, 4779 deletions
@@ -1,4 +1,5 @@ *~ +*.orig *.la *.lo *.o @@ -13,10 +14,15 @@ Makefile.in *.ko.cmd *.mod.c *.mod.o.cmd +*.mod.cmd +*.mod +*.order.cmd +*.symvers.cmd .tmp_versions Module.symvers modules.order kernel/include/linux/netfilter/ipset/ip_set_compat.h +kernel/include/linux/netfilter/ipset/ip_set_compiler.h /aclocal.m4 /autom4te.cache/ @@ -1,3 +1,101 @@ +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 + - Tests: Verify that hash:net,port,net type can handle 0/0 properly + - Makefile: Create LZMA-compressed dist-files (Phil Sutter) + +7.16 + - Add new ipset_parse_bitmask() function to the library interface + - test: Make sure no more than 64 clashing elements can be added + to hash:net,iface sets + - netfilter: ipset: add tests for the new bitmask feature (Vishwanath Pai) + - netfilter: ipset: Update the man page to include netmask/bitmask options + (Vishwanath Pai) + - netfilter: ipset: Add bitmask support to hash:netnet (Vishwanath Pai) + - netfilter: ipset: Add bitmask support to hash:ipport (Vishwanath Pai) + - netfilter: ipset: Add bitmask support to hash:ip (Vishwanath Pai) + - netfilter: ipset: Add support for new bitmask parameter (Vishwanath Pai) + - ipset-translate: allow invoking with a path name (Quentin Armitage) + - Fix IPv6 sets nftables translation (Pablo Neira Ayuso) + - Fix typo in ipset-translate man page (Bernhard M. Wiedemann) + +7.14 + - Add missing function to libipset.map and bump library version + (reported by Jan Engelhardt) + +7.13 + - When parsing protocols by number, do not check it in /etc/protocols. + - Add missing hunk to patch "Allow specifying protocols by number" + +7.12 + - Allow specifying protocols by number (Haw Loeung) + - Fix example in ipset.8 manpage discovered by Pablo Neira Ayuso. + - tests: add tests ipset to nftables (Pablo Neira Ayuso) + - add ipset to nftables translation infrastructure (Pablo Neira Ayuso) + - lib: Detach restore routine from parser (Pablo Neira Ayuso) + - lib: split parser from command execution (Pablo Neira Ayuso) + - Fix patch "Parse port before trying by service name" + +7.11 + - Parse port before trying by service name (Haw Loeung) + - Silence unused-but-set-variable warnings (reported by + Serhey Popovych) + - Handle -Werror=implicit-fallthrough= in debug mode compiling + - ipset: fix print format warning (Neutron Soutmun) + - Updated utilities + - Argument parsing buffer overflow in ipset_parse_argv fixed + (reported by Marshall Whittaker) + - +7.9 + - Fix library versioning (Jan Engelhardt) + +7.7 + - Expose the initval hash parameter to userspace + - Handle all variable header parts in helper scripts instead ot test tasks + - Add bucketsize parameter to all hash types + - Support the -exist flag with the destroy command + +7.6 + - Add checking system_power_efficient_wq in the kernel source tree + - .gitignore: add temporary files to the list + +7.5 + - configure.ac: Support building with old autoconf 2.63 + (Serhey Popovych) + - configure.ac: Build on kernels without skb->vlan_proto correctly + (Serhey Popovych) + - configure.ac: Add cond_resched_rcu() checks (Serhey Popovych) + - configure.ac: Better match for ipv6_skip_exthdr() frag_offp + arg presence (Serhey Popovych) + - Document explicitly that protocol is not stored in bitmap:port + 7.4 - Fix compatibility support for netlink extended ACK and add synchronize_rcu_bh() checking diff --git a/Make_global.am b/Make_global.am index 673aa41..9ba6adf 100644 --- a/Make_global.am +++ b/Make_global.am @@ -69,7 +69,7 @@ # interface. # curr:rev:age -LIBVERSION = 14:0:1 +LIBVERSION = 17:0:4 AM_CPPFLAGS = $(kinclude_CFLAGS) $(all_includes) -I$(top_srcdir)/include diff --git a/Makefile.am b/Makefile.am index eab32ee..cc821e6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -93,6 +93,9 @@ update_includes: kernel/include/uapi/linux/netfilter/ipset/$$x \ > include/libipset/linux_$$x; \ done + for x in ip_set_compiler.h; do \ + cp kernel/include/linux/netfilter/ipset/$$x include/libipset/$x; \ + done update_utils: wget -4 -O /tmp/ipset-bash-completion.tar.gz http://sourceforge.net/projects/ipset-bashcompl/files/latest/download diff --git a/configure.ac b/configure.ac index e3ddcce..db9e3f8 100644 --- a/configure.ac +++ b/configure.ac @@ -1,18 +1,20 @@ dnl Boilerplate -AC_INIT([ipset], [7.4], [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]) AC_CONFIG_HEADER([config.h]) -AM_INIT_AUTOMAKE([foreign subdir-objects tar-pax]) +AM_INIT_AUTOMAKE([foreign subdir-objects tar-pax no-dist-gzip dist-xz]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) +AC_PROG_LN_S AC_ENABLE_STATIC LT_INIT([dlopen]) LT_CONFIG_LTDL_DIR([libltdl]) LTDL_INIT([nonrecursive]) PKG_PROG_PKG_CONFIG +PKG_INSTALLDIR dnl Shortcut: Linux supported alone case "$host" in @@ -26,7 +28,7 @@ AC_ARG_WITH([kmod], [Build the kernel module (default: yes)]), [BUILDKMOD="$withval";], [BUILDKMOD="yes";]) -AM_CONDITIONAL(WITH_KMOD, test "$BUILDKMOD" == "yes") +AM_CONDITIONAL(WITH_KMOD, test "$BUILDKMOD" = "yes") dnl Additional arguments dnl Kernel build directory or source tree @@ -75,7 +77,7 @@ if test "x$enable_bashcompl" = "xyes"; then AC_SUBST(bashcompdir) fi -if test "$BUILDKMOD" == "yes" +if test "$BUILDKMOD" = "yes" then dnl Sigh: check kernel version dependencies if test "$KBUILDDIR" != "" @@ -203,9 +205,33 @@ AC_CHECK_TYPES([union nf_inet_addr],,,[#include <linux/types.h> dnl Checks for functions AC_CHECK_FUNCS(gethostbyname2) -if test "$BUILDKMOD" == "yes" +if test "$BUILDKMOD" = "yes" then dnl Check kernel incompatibilities... Ugly like hell + +AC_MSG_CHECKING([kernel source for INIT_DEFERRABLE_WORK]) +if test -f $ksourcedir/include/linux/workqueue.h && \ + $GREP -q 'INIT_DEFERRABLE_WORK' $ksourcedir/include/linux/workqueue.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_INIT_DEFERRABLE_WORK, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_INIT_DEFERRABLE_WORK, undef) +fi + +AC_MSG_CHECKING([kernel source for system_power_efficient_wq]) +if test -f $ksourcedir/include/linux/workqueue.h && \ + $GREP -q 'system_power_efficient_wq' $ksourcedir/include/linux/workqueue.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_SYSTEM_POWER_EFFICIENT_WQ, define) +elif test -f $ksourcedir/include/linux/workqueue.h && \ + $GREP -q 'system_wq' $ksourcedir/include/linux/workqueue.h; then + AC_MSG_RESULT(no) + AC_SUBST(HAVE_SYSTEM_POWER_EFFICIENT_WQ, undef) +else + AC_MSG_ERROR([Kernel source tree is too old, at least v2.36 is required]) +fi + AC_MSG_CHECKING([kernel source for struct xt_action_param]) if test -f $ksourcedir/include/linux/netfilter/x_tables.h && \ $GREP -q 'struct xt_action_param' $ksourcedir/include/linux/netfilter/x_tables.h; then @@ -295,9 +321,13 @@ elif test -f $ksourcedir/include/linux/netlink.h && \ $AWK '/ netlink_dump_start\(/,/\)/' $ksourcedir/include/linux/netlink.h | $GREP -q 'min_dump_alloc.*;'; then AC_MSG_RESULT(6 args) AC_SUBST(HAVE_NETLINK_DUMP_START_ARGS, 6) -else +elif test -f $ksourcedir/include/linux/netlink.h && \ + $AWK '/^struct netlink_dump_control {/,/\}/' $ksourcedir/include/linux/netlink.h | $GREP -q '\(\*start\)'; then AC_MSG_RESULT(4 args) AC_SUBST(HAVE_NETLINK_DUMP_START_ARGS, 4) +else + AC_MSG_RESULT(7 fake args) + AC_SUBST(HAVE_NETLINK_DUMP_START_ARGS, 7) fi AC_MSG_CHECKING([kernel source for ns_capable]) @@ -414,6 +444,10 @@ if test -f $ksourcedir/include/linux/mm.h && \ $GREP -q 'kvcalloc' $ksourcedir/include/linux/mm.h; then AC_MSG_RESULT(yes) AC_SUBST(HAVE_KVCALLOC, define) +elif test -f $ksourcedir/include/linux/slab.h && \ + $GREP -q 'kvcalloc' $ksourcedir/include/linux/slab.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_KVCALLOC, define) else AC_MSG_RESULT(no) AC_SUBST(HAVE_KVCALLOC, undef) @@ -424,11 +458,35 @@ if test -f $ksourcedir/include/linux/mm.h && \ $GREP -q 'kvfree' $ksourcedir/include/linux/mm.h; then AC_MSG_RESULT(yes) AC_SUBST(HAVE_KVFREE, define) +elif test -f $ksourcedir/include/linux/slab.h && \ + $GREP -q 'kvfree' $ksourcedir/include/linux/slab.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_KVFREE, define) else AC_MSG_RESULT(no) AC_SUBST(HAVE_KVFREE, undef) fi +AC_MSG_CHECKING([kernel source for bitmap_zalloc]) +if test -f $ksourcedir/include/linux/bitmap.h && \ + $GREP -q 'bitmap_zalloc' $ksourcedir/include/linux/bitmap.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_BITMAP_ZALLOC, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_BITMAP_ZALLOC, undef) +fi + +AC_MSG_CHECKING([kernel source for bitmap_zero]) +if test -f $ksourcedir/include/linux/bitmap.h && \ + $GREP -q 'bitmap_zero' $ksourcedir/include/linux/bitmap.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_BITMAP_ZERO, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_BITMAP_ZERO, undef) +fi + AC_MSG_CHECKING([kernel source for struct net in struct xt_mtchk_param]) if test -f $ksourcedir/include/linux/netfilter/x_tables.h && \ $AWK '/^struct xt_mtchk_param /,/^}/' $ksourcedir/include/linux/netfilter/x_tables.h | \ @@ -667,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 @@ -677,6 +745,16 @@ else AC_SUBST(HAVE_LOCKDEP_NFNL_IS_HELD, undef) fi +AC_MSG_CHECKING([kernel source for nla_strscpy() in netlink.h]) +if test -f $ksourcedir/include/net/netlink.h && \ + $GREP -q ' nla_strscpy' $ksourcedir/include/net/netlink.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_NLA_STRSCPY, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_NLA_STRSCPY, undef) +fi + AC_MSG_CHECKING([kernel source for strscpy() in string.h]) if test -f $ksourcedir/include/linux/timer.h && \ $GREP -q ' strscpy' $ksourcedir/include/linux/string.h; then @@ -687,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' \ @@ -698,6 +786,110 @@ else AC_SUBST(HAVE_SYNCHRONIZE_RCU_BH, undef) fi +AC_MSG_CHECKING([kernel source for the fourth arg of list_for_each_entry_rcu() in rculist.h]) +if test -f $ksourcedir/include/linux/rculist.h && \ + $GREP -q 'define list_for_each_entry_rcu(pos, head, member, cond' $ksourcedir/include/linux/rculist.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS, undef) +fi + +AC_MSG_CHECKING([kernel source for skb_protocol() in if_vlan.h]) +if test -f $ksourcedir/include/linux/if_vlan.h && \ + $GREP -q 'static inline __be16 skb_protocol' $ksourcedir/include/linux/if_vlan.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_SKB_PROTOCOL, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_SKB_PROTOCOL, undef) +fi + +AC_MSG_CHECKING([kernel source for NLA_POLICY_EXACT_LEN() in netlink.h]) +if test -f $ksourcedir/include/net/netlink.h && \ + $GREP -q 'define NLA_POLICY_EXACT_LEN' $ksourcedir/include/net/netlink.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_NLA_POLICY_EXACT_LEN, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_NLA_POLICY_EXACT_LEN, undef) +fi + +AC_MSG_CHECKING([kernel source for nfnl_msg_put() in nfnetlink.h]) +if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \ + $GREP -q 'nfnl_msg_put' $ksourcedir/include/linux/netfilter/nfnetlink.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_NFNL_MSG_PUT, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_NFNL_MSG_PUT, undef) +fi + +AC_MSG_CHECKING([kernel source for struct nfnl_info in nfnl_callback function]) +if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \ + $AWK '/^struct nfnl_callback /,/^}/' $ksourcedir/include/linux/netfilter/nfnetlink.h | $GREP -q 'struct nfnl_info'; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_NFNL_INFO_IN_NFNL_CALLBACK, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_NFNL_INFO_IN_NFNL_CALLBACK, undef) +fi + +AC_MSG_CHECKING([kernel source for enum nfnl_callback_type]) +if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \ + $GREP -q 'enum nfnl_callback_type ' $ksourcedir/include/linux/netfilter/nfnetlink.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_NFNL_CALLBACK_TYPE, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_NFNL_CALLBACK_TYPE, undef) +fi + +AC_MSG_CHECKING([kernel source of handling -EAGAIN in nfnetlink_unicast]) +if test -f $ksourcedir/net/netfilter/nfnetlink.c && \ + $AWK '/nfnetlink_unicast\(/,/^}/' $ksourcedir/net/netfilter/nfnetlink.c | $GREP -q 'err == -EAGAIN'; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_EAGAIN_IN_NFNETLINK_UNICAST, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_EAGAIN_IN_NFNETLINK_UNICAST, undef) +fi + +AC_MSG_CHECKING([kernel source for nlmsg_unicast which returns zero in case of success]) +if test -f $ksourcedir/include/net/netlink.h && \ + $AWK '/static inline int nlmsg_unicast\(/,/^}/' $ksourcedir/include/net/netlink.h | $GREP -q 'err > 0'; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_NLMSG_UNICAST, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_NLMSG_UNICAST, undef) +fi + +AC_MSG_CHECKING([kernel source for kvzalloc() in mm.h and slab.h]) +if test -f $ksourcedir/include/linux/mm.h && \ + $GREP -q 'static inline void \*kvzalloc(' $ksourcedir/include/linux/mm.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_KVZALLOC, define) +elif test -f $ksourcedir/include/linux/slab.h && \ + $GREP -q 'kvzalloc' $ksourcedir/include/linux/slab.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_KVZALLOC, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_KVZALLOC, undef) +fi + +AC_MSG_CHECKING([kernel source for GFP_KERNEL_ACCOUNT in gfp.h]) +if test -f $ksourcedir/include/linux/gfp.h && \ + $GREP -q 'define GFP_KERNEL_ACCOUNT' $ksourcedir/include/linux/gfp.h; then + AC_MSG_RESULT(yes) + AC_SUBST(HAVE_GFP_KERNEL_ACCOUNT, define) +else + AC_MSG_RESULT(no) + AC_SUBST(HAVE_GFP_KERNEL_ACCOUNT, undef) +fi + AC_MSG_CHECKING([kernel source for struct net_generic]) if test -f $ksourcedir/include/net/netns/generic.h && \ $GREP -q 'struct net_generic' $ksourcedir/include/net/netns/generic.h; then @@ -753,7 +945,8 @@ dnl Checks for library functions. dnl Generate output AC_CONFIG_FILES([Makefile include/libipset/Makefile lib/Makefile lib/libipset.pc src/Makefile utils/Makefile - kernel/include/linux/netfilter/ipset/ip_set_compat.h]) + kernel/include/linux/netfilter/ipset/ip_set_compat.h + kernel/include/linux/netfilter/ipset/ip_set_compiler.h]) AC_OUTPUT dnl Summary diff --git a/include/libipset/Makefile.am b/include/libipset/Makefile.am index c7f7b2b..2c04029 100644 --- a/include/libipset/Makefile.am +++ b/include/libipset/Makefile.am @@ -17,6 +17,7 @@ pkginclude_HEADERS = \ transport.h \ types.h \ ipset.h \ - utils.h + utils.h \ + xlate.h EXTRA_DIST = debug.h icmp.h icmpv6.h diff --git a/include/libipset/args.h b/include/libipset/args.h index 616cca5..a549e42 100644 --- a/include/libipset/args.h +++ b/include/libipset/args.h @@ -56,6 +56,9 @@ enum ipset_keywords { IPSET_ARG_SKBMARK, /* skbmark */ IPSET_ARG_SKBPRIO, /* skbprio */ IPSET_ARG_SKBQUEUE, /* skbqueue */ + IPSET_ARG_BUCKETSIZE, /* bucketsize */ + IPSET_ARG_INITVAL, /* initval */ + IPSET_ARG_BITMASK, /* bitmask */ IPSET_ARG_MAX, }; diff --git a/include/libipset/data.h b/include/libipset/data.h index 851773a..afaf18c 100644 --- a/include/libipset/data.h +++ b/include/libipset/data.h @@ -37,6 +37,7 @@ enum ipset_opt { IPSET_OPT_RESIZE, IPSET_OPT_SIZE, IPSET_OPT_FORCEADD, + IPSET_OPT_BITMASK, /* Create-specific options, filled out by the kernel */ IPSET_OPT_ELEMENTS, IPSET_OPT_REFERENCES, @@ -67,8 +68,10 @@ enum ipset_opt { IPSET_OPT_SKBPRIO, IPSET_OPT_SKBQUEUE, IPSET_OPT_IFACE_WILDCARD, + IPSET_OPT_BUCKETSIZE, + IPSET_OPT_INITVAL, /* Internal options */ - IPSET_OPT_FLAGS = 48, /* IPSET_FLAG_EXIST| */ + IPSET_OPT_FLAGS = 49, /* IPSET_FLAG_EXIST| */ IPSET_OPT_CADT_FLAGS, /* IPSET_FLAG_BEFORE| */ IPSET_OPT_ELEM, IPSET_OPT_TYPE, @@ -103,7 +106,8 @@ enum ipset_opt { | IPSET_FLAG(IPSET_OPT_COUNTERS)\ | IPSET_FLAG(IPSET_OPT_CREATE_COMMENT)\ | IPSET_FLAG(IPSET_OPT_FORCEADD)\ - | IPSET_FLAG(IPSET_OPT_SKBINFO)) + | IPSET_FLAG(IPSET_OPT_SKBINFO)\ + | IPSET_FLAG(IPSET_OPT_BITMASK)) #define IPSET_ADT_FLAGS \ (IPSET_FLAG(IPSET_OPT_IP) \ diff --git a/include/libipset/debug.h b/include/libipset/debug.h index 9743d59..92d5f89 100644 --- a/include/libipset/debug.h +++ b/include/libipset/debug.h @@ -11,6 +11,7 @@ #include <stdio.h> #include <sys/socket.h> #include <linux/netlink.h> +#define DD(cmd) cmd #define D(fmt, args...) \ fprintf(stderr, "%s: %s: " fmt "\n", __FILE__, __func__ , ## args) #define IF_D(test, fmt, args...) \ @@ -25,6 +26,7 @@ dump_nla(struct nlattr *nla[], int maxlen) D("nla[%u] does%s exist", i, nla[i] ? "" : " NOT"); } #else +#define DD(cmd) #define D(fmt, args...) #define IF_D(test, fmt, args...) #define dump_nla(nla, maxlen) diff --git a/include/libipset/ip_set_compiler.h b/include/libipset/ip_set_compiler.h new file mode 100644 index 0000000..1b392f8 --- /dev/null +++ b/include/libipset/ip_set_compiler.h @@ -0,0 +1,15 @@ +#ifndef __IP_SET_COMPILER_H +#define __IP_SET_COMPILER_H + +/* Compiler attributes */ +#ifndef __has_attribute +# define __has_attribute(x) __GCC4_has_attribute_##x +# define __GCC4_has_attribute___fallthrough__ 0 +#endif + +#if __has_attribute(__fallthrough__) +# define fallthrough __attribute__((__fallthrough__)) +#else +# define fallthrough do {} while (0) /* fallthrough */ +#endif +#endif /* __IP_SET_COMPILER_H */ diff --git a/include/libipset/linux_ip_set.h b/include/libipset/linux_ip_set.h index 7fd9948..4e32a50 100644 --- a/include/libipset/linux_ip_set.h +++ b/include/libipset/linux_ip_set.h @@ -89,14 +89,15 @@ enum { IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */ IPSET_ATTR_MARK, /* 10 */ IPSET_ATTR_MARKMASK, /* 11 */ + IPSET_ATTR_BITMASK, /* 12 */ /* Reserve empty slots */ IPSET_ATTR_CADT_MAX = 16, /* Create-only specific attributes */ - IPSET_ATTR_GC, + IPSET_ATTR_INITVAL, /* was unused IPSET_ATTR_GC */ IPSET_ATTR_HASHSIZE, IPSET_ATTR_MAXELEM, IPSET_ATTR_NETMASK, - IPSET_ATTR_PROBES, + IPSET_ATTR_BUCKETSIZE, /* was unused IPSET_ATTR_PROBES */ IPSET_ATTR_RESIZE, IPSET_ATTR_SIZE, /* Kernel-only */ @@ -157,6 +158,7 @@ enum ipset_errno { IPSET_ERR_COMMENT, IPSET_ERR_INVALID_MARKMASK, IPSET_ERR_SKBINFO, + IPSET_ERR_BITMASK_NETMASK_EXCL, /* Type specific error codes */ IPSET_ERR_TYPE_SPECIFIC = 4352, @@ -214,6 +216,8 @@ enum ipset_cadt_flags { enum ipset_create_flags { IPSET_CREATE_FLAG_BIT_FORCEADD = 0, IPSET_CREATE_FLAG_FORCEADD = (1 << IPSET_CREATE_FLAG_BIT_FORCEADD), + IPSET_CREATE_FLAG_BIT_BUCKETSIZE = 1, + IPSET_CREATE_FLAG_BUCKETSIZE = (1 << IPSET_CREATE_FLAG_BIT_BUCKETSIZE), IPSET_CREATE_FLAG_BIT_MAX = 7, }; diff --git a/include/libipset/list_sort.h b/include/libipset/list_sort.h index 70bb02d..d9d7b36 100644 --- a/include/libipset/list_sort.h +++ b/include/libipset/list_sort.h @@ -61,7 +61,7 @@ static inline void list_del(struct list_head *entry) // entry->prev = (void *) 0; } -static inline void __list_splice(const struct list_head *list, +static inline void __list_splice(struct list_head *list, struct list_head *prev, struct list_head *next) { @@ -75,7 +75,7 @@ static inline void __list_splice(const struct list_head *list, next->prev = last; } -static inline void list_splice(const struct list_head *list, +static inline void list_splice(struct list_head *list, struct list_head *head) { if (!list_empty(list)) diff --git a/include/libipset/parse.h b/include/libipset/parse.h index 3fa9129..0123d4b 100644 --- a/include/libipset/parse.h +++ b/include/libipset/parse.h @@ -92,6 +92,8 @@ extern int ipset_parse_uint8(struct ipset_session *session, enum ipset_opt opt, const char *str); extern int ipset_parse_netmask(struct ipset_session *session, enum ipset_opt opt, const char *str); +extern int ipset_parse_bitmask(struct ipset_session *session, + enum ipset_opt opt, const char *str); extern int ipset_parse_flag(struct ipset_session *session, enum ipset_opt opt, const char *str); extern int ipset_parse_typename(struct ipset_session *session, diff --git a/include/libipset/print.h b/include/libipset/print.h index f455259..9443ee1 100644 --- a/include/libipset/print.h +++ b/include/libipset/print.h @@ -35,6 +35,9 @@ extern int ipset_print_ipaddr(char *buf, unsigned int len, extern int ipset_print_number(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, uint8_t env); +extern int ipset_print_hexnumber(char *buf, unsigned int len, + const struct ipset_data *data, + enum ipset_opt opt, uint8_t env); extern int ipset_print_name(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, uint8_t env); 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/include/libipset/xlate.h b/include/libipset/xlate.h new file mode 100644 index 0000000..6569768 --- /dev/null +++ b/include/libipset/xlate.h @@ -0,0 +1,6 @@ +#ifndef LIBIPSET_XLATE_H +#define LIBIPSET_XLATE_H + +int ipset_xlate_argv(struct ipset *ipset, int argc, char *argv[]); + +#endif diff --git a/kernel/ChangeLog b/kernel/ChangeLog index 79e736e..1b05fbd 100644 --- a/kernel/ChangeLog +++ b/kernel/ChangeLog @@ -1,3 +1,147 @@ +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 + +7.16 + - netfilter: ipset: restore allowing 64 clashing elements in hash:net,iface + - Fix all debug mode warnings + - netfilter: ipset: Add support for new bitmask parameter (Vishwanath Pai) + - netfilter: ipset: regression in ip_set_hash_ip.c (Vishwanath Pai) + - netfilter: move from strlcpy with unused retval to strscpy + (Wolfram Sang) + - compatibility: handle unsafe_memcpy() + - netlink: Bounds-check struct nlmsgerr creation (Kees Cook) + - compatibility: move to skb_protocol in the code from tc_skb_protocol + - Compatibility: check kvcalloc, kvfree, kvzalloc in slab.h too + - sched: consistently handle layer3 header accesses in the presence + of VLANs (Toke Høiland-Jørgensen) + - treewide: Replace GPLv2 boilerplate/reference with SPDX + - rule 500 (Thomas Gleixner) + - headers: Remove some left-over license text in + include/uapi/linux/netfilter/ (Christophe JAILLET) + - netfilter: ipset: enforce documented limit to prevent allocating + huge memory + - netfilter: ipset: Fix oversized kvmalloc() calls + +7.15 + - netfilter: ipset: Fix maximal range check in hash_ipportnet4_uadt() + (Nathan Chancellor) + +7.14 + - 64bit division isn't allowed on 32bit, replace it with shift + +7.13 + - Limit the maximal range of consecutive elements to add/delete fix + +7.12 + - Limit the maximal range of consecutive elements to add/delete + - Backport "netfilter: use nfnetlink_unicast()" + - Backport "netfilter: nfnetlink: consolidate callback type" + - Backport "netfilter: nfnetlink: add struct nfnl_info and + pass it to callbacks" + - Backport "netfilter: add helper function to set up the + nfnetlink header and use it" + +7.10 + - Fix patch "Handle false warning from -Wstringop-overflow" + - Backward compatibility: handle renaming nla_strlcpy to nla_strscpy + - treewide: rename nla_strlcpy to nla_strscpy. (Francis Laniel) + - netfilter: ipset: fix shift-out-of-bounds in htable_bits() + (Vasily Averin) + - netfilter: ipset: fixes possible oops in mtype_resize (Vasily Averin) + - Handle false warning from -Wstringop-overflow + - Backward compatibility: handle missing strscpy with a wrapper of strlcpy. + - Move compiler specific compatibility support to separated file (broken + compatibility support reported by Ed W) + +7.8 + - Complete backward compatibility fix for package copy of <linux/jhash.h> + - Compatibility: check for kvzalloc() and GFP_KERNEL_ACCOUNT + - netfilter: ipset: enable memory accounting for ipset allocations + (Vasily Averin) + - netfilter: ipset: prevent uninit-value in hash_ip6_add (Eric Dumazet) + - Compatibility: use skb_policy() from if_vlan.h if available + - Compatibility: Check for the fourth arg of list_for_each_entry_rcu() + - Backward compatibility fix for the package copy of <linux/jhash.h> + +7.7 + - Expose the initval hash parameter to userspace + - Add bucketsize parameter to all hash types + - Use fallthrough pseudo-keyword in the package copy of <linux/jhash.h> too + - Support the -exist flag with the destroy command + - netfilter: Use fallthrough pseudo-keyword (Gustavo A. R. Silva) + - netfilter: Replace zero-length array with flexible-array member + (Gustavo A. R. Silva) + - netfilter: ipset: call ip_set_free() instead of kfree() (Eric Dumazet) + - netfiler: ipset: fix unaligned atomic access (Russell King) + - netfilter: ipset: Fix subcounter update skip (Phil Sutter) + - ipset: Update byte and packet counters regardless of whether they match + (Stefano Brivio) + - netfilter: ipset: Pass lockdep expression to RCU lists (Amol Grover) + - ip_set: Fix compatibility with kernels between v3.3 and v4.5 + (Serhey Popovych) + - ip_set: Fix build on kernels without INIT_DEFERRABLE_WORK + (Serhey Popovych) + - ipset: Support kernels with at least system_wq support + - ip_set: Fix build on kernels without system_power_efficient_wq + (Serhey Popovych) + +7.6 + - netfilter: ipset: Fix forceadd evaluation path + - netfilter: ipset: Correct the reported memory size + - ip_set: Include kernel header instead of UAPI (Serhey Popovych) + - netfilter: ipset: Fix "INFO: rcu detected stall in hash_xxx" reports + - netfilter: ipset: fix suspicious RCU usage in find_set_and_id + - Add compatibility support for bitmap_zalloc() and bitmap_zero() + - netfilter: ipset: use bitmap infrastructure completely + - netfilter: fix a use-after-free in mtype_destroy() (Cong Wang) + +7.5 + - netfilter: ipset: avoid null deref when IPSET_ATTR_LINENO is present + (Florian Westphal) + - ip_set: Pass init_net when @net is missing in match check params + data structure (Serhey Popovych) + - netfilter: xt_set: Do not restrict --map-set to the mangle table + (Serhey Popovych) + - compat: em_ipset: Build on old kernels (Serhey Popovych) + - compat: Use skb_vlan_tag_present() instead of vlan_tx_tag_present() + (Serhey Popovych) + 7.4 - Fix nla_policies to fully support NL_VALIDATE_STRICT - treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 diff --git a/kernel/include/linux/jhash.h b/kernel/include/linux/jhash.h index c700a77..d144e33 100644 --- a/kernel/include/linux/jhash.h +++ b/kernel/include/linux/jhash.h @@ -1,5 +1,6 @@ #ifndef _LINUX_JHASH_H #define _LINUX_JHASH_H +#include <linux/netfilter/ipset/ip_set_compiler.h> /* jhash.h: Jenkins hash support. * @@ -87,17 +88,17 @@ static inline u32 jhash(const void *key, u32 length, u32 initval) /* Last block: affect all 32 bits of (c) */ /* All the case statements fall through */ switch (length) { - case 12: c += (u32)k[11]<<24; - case 11: c += (u32)k[10]<<16; - case 10: c += (u32)k[9]<<8; - case 9: c += k[8]; - case 8: b += (u32)k[7]<<24; - case 7: b += (u32)k[6]<<16; - case 6: b += (u32)k[5]<<8; - case 5: b += k[4]; - case 4: a += (u32)k[3]<<24; - case 3: a += (u32)k[2]<<16; - case 2: a += (u32)k[1]<<8; + case 12: c += (u32)k[11]<<24; fallthrough; + case 11: c += (u32)k[10]<<16; fallthrough; + case 10: c += (u32)k[9]<<8; fallthrough; + case 9: c += k[8]; fallthrough; + case 8: b += (u32)k[7]<<24; fallthrough; + case 7: b += (u32)k[6]<<16; fallthrough; + case 6: b += (u32)k[5]<<8; fallthrough; + case 5: b += k[4]; fallthrough; + case 4: a += (u32)k[3]<<24; fallthrough; + case 3: a += (u32)k[2]<<16; fallthrough; + case 2: a += (u32)k[1]<<8; fallthrough; case 1: a += k[0]; __jhash_final(a, b, c); case 0: /* Nothing left to add */ @@ -133,8 +134,8 @@ static inline u32 jhash2(const u32 *k, u32 length, u32 initval) /* Handle the last 3 u32's: all the case statements fall through */ switch (length) { - case 3: c += k[2]; - case 2: b += k[1]; + case 3: c += k[2]; fallthrough; + case 2: b += k[1]; fallthrough; case 1: a += k[0]; __jhash_final(a, b, c); case 0: /* Nothing left to add */ diff --git a/kernel/include/linux/netfilter/ipset/ip_set.h b/kernel/include/linux/netfilter/ipset/ip_set.h index 3949e32..7691b7a 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set.h +++ b/kernel/include/linux/netfilter/ipset/ip_set.h @@ -99,7 +99,7 @@ struct ip_set_counter { struct ip_set_comment_rcu { struct rcu_head rcu; - char str[0]; + char str[]; }; struct ip_set_comment { @@ -122,6 +122,7 @@ struct ip_set_ext { u32 timeout; u8 packets_op; u8 bytes_op; + bool target; }; struct ip_set; @@ -188,8 +189,24 @@ 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; }; +struct ip_set_region { + spinlock_t lock; /* Region lock */ + size_t ext_size; /* Size of the dynamic extensions */ + u32 elements; /* Number of elements vs timeout */ +}; + +/* Max range where every element is added/deleted in one step */ +#define IPSET_MAX_RANGE (1<<14) + +/* The max revision number supported by any set type + 1 */ +#define IPSET_REVISION_MAX 9 + /* The core set type structure */ struct ip_set_type { struct list_head list; @@ -207,6 +224,8 @@ struct ip_set_type { u8 family; /* Type revisions */ u8 revision_min, revision_max; + /* Revision-specific supported (create) flags */ + u8 create_flags[IPSET_REVISION_MAX+1]; /* Set features to control swapping */ u16 features; @@ -228,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 */ @@ -437,13 +458,6 @@ ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr) sizeof(*addr)); } -/* Calculate the bytes required to store the inclusive range of a-b */ -static inline int -bitmap_bytes(u32 a, u32 b) -{ - return 4 * ((((b - a + 8) / 8) + 3) / 4); -} - /* How often should the gc be run by default */ #define IPSET_GC_TIME (3 * 60) @@ -518,8 +532,18 @@ ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo, *skbinfo = ext->skbinfo; } +static inline void +nf_inet_addr_mask_inplace(union nf_inet_addr *a1, + const union nf_inet_addr *mask) +{ + a1->all[0] &= mask->all[0]; + a1->all[1] &= mask->all[1]; + a1->all[2] &= mask->all[2]; + a1->all[3] &= mask->all[3]; +} + #define IP_SET_INIT_KEXT(skb, opt, set) \ - { .bytes = (skb)->len, .packets = 1, \ + { .bytes = (skb)->len, .packets = 1, .target = true,\ .timeout = ip_set_adt_opt_timeout(opt, set) } #define IP_SET_INIT_UEXT(set) \ 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 d71c3fd..5746f39 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in +++ b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in @@ -5,6 +5,8 @@ * xt_set.c, ip_set_core.c, ip_set_getport.c, pfxlen.c too. */ +#@HAVE_INIT_DEFERRABLE_WORK@ HAVE_INIT_DEFERRABLE_WORK +#@HAVE_SYSTEM_POWER_EFFICIENT_WQ@ HAVE_SYSTEM_POWER_EFFICIENT_WQ #@HAVE_STRUCT_XT_ACTION_PARAM@ HAVE_STRUCT_XT_ACTION_PARAM #@HAVE_VZALLOC@ HAVE_VZALLOC #@HAVE_ETHER_ADDR_EQUAL@ HAVE_ETHER_ADDR_EQUAL @@ -26,6 +28,8 @@ #@HAVE_RBTREE_POSTORDER_FOR_EACH_ENTRY_SAFE@ HAVE_RBTREE_POSTORDER_FOR_EACH_ENTRY_SAFE #@HAVE_KVCALLOC@ HAVE_KVCALLOC #@HAVE_KVFREE@ HAVE_KVFREE +#@HAVE_BITMAP_ZALLOC@ HAVE_BITMAP_ZALLOC +#@HAVE_BITMAP_ZERO@ HAVE_BITMAP_ZERO #@HAVE_XT_MTCHK_PARAM_STRUCT_NET@ HAVE_XT_MTCHK_PARAM_STRUCT_NET #@HAVE_TCF_EMATCH_OPS_CHANGE_ARG_NET@ HAVE_TCF_EMATCH_OPS_CHANGE_ARG_NET #@HAVE_TCF_EMATCH_STRUCT_NET@ HAVE_TCF_EMATCH_STRUCT_NET @@ -47,11 +51,24 @@ #@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 #@HAVE_SKB_IIF@ HAVE_SKB_IIF +#@HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS@ HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS +#@HAVE_SKB_PROTOCOL@ HAVE_SKB_PROTOCOL +#@HAVE_NLA_POLICY_EXACT_LEN@ HAVE_NLA_POLICY_EXACT_LEN +#@HAVE_KVZALLOC@ HAVE_KVZALLOC +#@HAVE_GFP_KERNEL_ACCOUNT@ HAVE_GFP_KERNEL_ACCOUNT +#@HAVE_NLA_STRSCPY@ HAVE_NLA_STRSCPY +#@HAVE_NFNL_MSG_PUT@ HAVE_NFNL_MSG_PUT +#@HAVE_NFNL_INFO_IN_NFNL_CALLBACK@ HAVE_NFNL_INFO_IN_NFNL_CALLBACK +#@HAVE_NFNL_CALLBACK_TYPE@ HAVE_NFNL_CALLBACK_TYPE +#@HAVE_EAGAIN_IN_NFNETLINK_UNICAST@ HAVE_EAGAIN_IN_NFNETLINK_UNICAST +#@HAVE_NLMSG_UNICAST@ HAVE_NLMSG_UNICAST #ifdef HAVE_EXPORT_SYMBOL_GPL_IN_MODULE_H #include <linux/module.h> @@ -166,6 +183,14 @@ static inline void cond_resched_rcu(void) #error "NETFILTER_NETLINK must be enabled: select NFACCT/NFQUEUE/LOG over NFNETLINK" #endif +#ifndef HAVE_INIT_DEFERRABLE_WORK +#define INIT_DEFERRABLE_WORK INIT_DELAYED_WORK_DEFERRABLE +#endif + +#ifndef HAVE_SYSTEM_POWER_EFFICIENT_EQ +#define system_power_efficient_wq system_wq +#endif + #ifndef HAVE_STRUCT_XT_ACTION_PARAM #define xt_action_param xt_match_param #endif @@ -253,6 +278,16 @@ static inline void kvfree(const void *addr) } #endif +#ifndef HAVE_BITMAP_ZALLOC +#define bitmap_zalloc(nbits, flags) \ + kmalloc(BITS_TO_LONGS(nbits) * sizeof(unsigned long), (flags) | __GFP_ZERO) +#endif + +#ifndef HAVE_BITMAP_ZERO +#define bitmap_zero(dst, nbits) \ + memset(dst, 0, BITS_TO_LONGS(nbits) * sizeof(unsigned long)) +#endif + #ifndef HAVE_NLA_PUT_BE16 static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) { @@ -320,18 +355,44 @@ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype, } #endif -#ifdef HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS -#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(net, nl, skb, nlh, cda, e) -#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(net, nl, skb, ad, nlh, cda, e) -#define IPSET_SOCK_NET(net, ctnl) net +#ifdef HAVE_NFNL_INFO_IN_NFNL_CALLBACK +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(skb, i, cda) +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda, i) +#define IPSET_SOCK_NET(n, ctnl, i) (i)->net +#define INFO_NLH(i, n) (i)->nlh +#define INFO_NET(i, n) (i)->net +#define INFO_SK(i, n) (i)->sk +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l) +#elif defined(HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS) +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(net, nl, skb, nlh, cda, e) +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda, e) +#define IPSET_SOCK_NET(net, ctnl, i) net +#define INFO_NLH(i, n) n +#define INFO_NET(i, n) n +#define INFO_SK(i, n) n +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l) #elif defined(HAVE_NET_IN_NFNL_CALLBACK_FN) -#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(net, nl, skb, nlh, cda) -#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(net, nl, skb, ad, nlh, cda) -#define IPSET_SOCK_NET(net, ctnl) net +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(net, nl, skb, nlh, cda) +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda) +#define IPSET_SOCK_NET(net, ctnl, i) net +#define INFO_NLH(i, n) n +#define INFO_NET(i, n) n +#define INFO_SK(i, n) n +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l) #else -#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(nl, skb, nlh, cda) -#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(nl, skb, ad, nlh, cda) -#define IPSET_SOCK_NET(net, ctnl) sock_net(ctnl) +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(nl, skb, nlh, cda) +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(nl, skb, ad, nlh, cda) +#define IPSET_SOCK_NET(net, ctnl, i) sock_net(ctnl) +#define INFO_NLH(i, n) n +#define INFO_NET(i, n) n +#define INFO_SK(i, n) n +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(ctnl, skb, set, tb, adt, flags, l) +#endif + +#ifdef HAVE_NFNL_CALLBACK_TYPE +#define SET_NFNL_CALLBACK_TYPE(t) .type = t, +#else +#define SET_NFNL_CALLBACK_TYPE(t) #endif #ifndef HAVE_TC_SKB_PROTOCOL @@ -347,7 +408,8 @@ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype, #define skb_vlan_tag_present vlan_tx_tag_present #endif -static inline __be16 tc_skb_protocol(const struct sk_buff *skb) +#ifndef HAVE_SKB_PROTOCOL +static inline __be16 skb_protocol(const struct sk_buff *skb, bool skip_vlan) { if (skb_vlan_tag_present(skb)) #ifdef HAVE_VLAN_PROTO_IN_SK_BUFF @@ -358,6 +420,7 @@ static inline __be16 tc_skb_protocol(const struct sk_buff *skb) return skb->protocol; } #endif +#endif #ifdef HAVE_XT_NET #define IPSET_DEV_NET(par) xt_net(par) @@ -374,6 +437,36 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type) } #endif +#ifndef HAVE_NFNL_MSG_PUT +#include <linux/netfilter/nfnetlink.h> +static inline void nfnl_fill_hdr(struct nlmsghdr *nlh, u8 family, u8 version, + __be16 res_id) +{ + struct nfgenmsg *nfmsg; + + nfmsg = nlmsg_data(nlh); + nfmsg->nfgen_family = family; + nfmsg->version = version; + nfmsg->res_id = res_id; +} + +static inline struct nlmsghdr *nfnl_msg_put(struct sk_buff *skb, u32 portid, + u32 seq, int type, int flags, + u8 family, u8 version, + __be16 res_id) +{ + struct nlmsghdr *nlh; + + nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg), flags); + if (!nlh) + return NULL; + + nfnl_fill_hdr(nlh, family, version, res_id); + + return nlh; +} +#endif + #ifdef HAVE_NETLINK_EXTENDED_ACK #define NETLINK_ACK(in_skb, nlh, err, extack) netlink_ack(in_skb, nlh, err, extack) #else @@ -414,8 +507,53 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type) struct type *var = set->data #endif +#ifndef HAVE_TIMER_SHUTDOWN_SYNC +#define timer_shutdown_sync(timer) del_timer_sync(timer) +#endif + #ifndef HAVE_STRSCPY -#define strscpy(dst, src, n) (strncpy(dst, src, n) == (dst)) +static inline ssize_t strscpy(char * dest, const char * src, size_t count) +{ + size_t ret = strlcpy(dest, src, count); + + return (ret >= count ? -E2BIG : ret); +} +#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 + +#if !defined(HAVE_EAGAIN_IN_NFNETLINK_UNICAST) || !defined(HAVE_NLMSG_UNICAST) +#define NFNETLINK_UNICAST(cntl, skb, net, portid) ipset_nfnetlink_unicast(cntl, skb, portid) +static inline int ipset_nfnetlink_unicast(struct sock *ctnl, struct sk_buff *skb, u32 portid) +{ + int err = netlink_unicast(ctnl, skb, portid, MSG_DONTWAIT); + + if (err > 0) + err = 0; + if (err == -EAGAIN) + err = -ENOBUFS; + + return err; +} +#else +#define NFNETLINK_UNICAST(cntl, skb, net, portid) nfnetlink_unicast(skb, net, portid) #endif #ifndef smp_mb__before_atomic @@ -447,5 +585,52 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type) #define dev_get_by_index_rcu __dev_get_by_index #endif +#ifdef HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS +#define list_for_each_entry_rcu_compat(pos, head, member, cond) \ + list_for_each_entry_rcu(pos, head, member, cond) +#else +#define list_for_each_entry_rcu_compat(pos, head, member, cond) \ + list_for_each_entry_rcu(pos, head, member) +#endif + +#ifndef HAVE_NLA_POLICY_EXACT_LEN +#define NLA_POLICY_EXACT_LEN(_len) { \ + .type = NLA_UNSPEC, \ + .len = _len \ +} +#endif + +#ifndef HAVE_KVZALLOC +#include <linux/slab.h> +#include <linux/vmalloc.h> +#ifndef GFP_KERNEL_ACCOUNT +#define GFP_KERNEL_ACCOUNT GFP_KERNEL +#endif +static inline void *kvzalloc(size_t size, gfp_t flags) +{ + void *members = NULL; + + if (size < KMALLOC_MAX_SIZE) + members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); + + if (members) { + pr_debug("%p: allocated with kmalloc\n", members); + return members; + } + + members = vzalloc(size); + if (!members) + return NULL; + pr_debug("%p: allocated with vmalloc\n", members); + + return members; +} +#endif + +#ifndef unsafe_memcpy +#define unsafe_memcpy(dst, src, bytes, justification) \ + memcpy(dst, src, bytes) +#endif + #endif /* IP_SET_COMPAT_HEADERS */ #endif /* __IP_SET_COMPAT_H */ diff --git a/kernel/include/linux/netfilter/ipset/ip_set_compiler.h.in b/kernel/include/linux/netfilter/ipset/ip_set_compiler.h.in new file mode 100644 index 0000000..1b392f8 --- /dev/null +++ b/kernel/include/linux/netfilter/ipset/ip_set_compiler.h.in @@ -0,0 +1,15 @@ +#ifndef __IP_SET_COMPILER_H +#define __IP_SET_COMPILER_H + +/* Compiler attributes */ +#ifndef __has_attribute +# define __has_attribute(x) __GCC4_has_attribute_##x +# define __GCC4_has_attribute___fallthrough__ 0 +#endif + +#if __has_attribute(__fallthrough__) +# define fallthrough __attribute__((__fallthrough__)) +#else +# define fallthrough do {} while (0) /* fallthrough */ +#endif +#endif /* __IP_SET_COMPILER_H */ diff --git a/kernel/include/linux/netfilter/ipset/ip_set_getport.h b/kernel/include/linux/netfilter/ipset/ip_set_getport.h index 09c5a96..83b88f1 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set_getport.h +++ b/kernel/include/linux/netfilter/ipset/ip_set_getport.h @@ -4,7 +4,7 @@ #include <linux/skbuff.h> #include <linux/types.h> -#include <uapi/linux/in.h> +#include <linux/in.h> extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src, __be16 *port, u8 *proto); diff --git a/kernel/include/uapi/linux/netfilter/ipset/ip_set.h b/kernel/include/uapi/linux/netfilter/ipset/ip_set.h index 7545af4..b81f1ae 100644 --- a/kernel/include/uapi/linux/netfilter/ipset/ip_set.h +++ b/kernel/include/uapi/linux/netfilter/ipset/ip_set.h @@ -3,10 +3,6 @@ * Patrick Schaaf <bof@bof.de> * Martin Josefsson <gandalf@wlug.westbo.se> * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@netfilter.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #ifndef _UAPI_IP_SET_H #define _UAPI_IP_SET_H @@ -89,14 +85,15 @@ enum { IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */ IPSET_ATTR_MARK, /* 10 */ IPSET_ATTR_MARKMASK, /* 11 */ + IPSET_ATTR_BITMASK, /* 12 */ /* Reserve empty slots */ IPSET_ATTR_CADT_MAX = 16, /* Create-only specific attributes */ - IPSET_ATTR_GC, + IPSET_ATTR_INITVAL, /* was unused IPSET_ATTR_GC */ IPSET_ATTR_HASHSIZE, IPSET_ATTR_MAXELEM, IPSET_ATTR_NETMASK, - IPSET_ATTR_PROBES, + IPSET_ATTR_BUCKETSIZE, /* was unused IPSET_ATTR_PROBES */ IPSET_ATTR_RESIZE, IPSET_ATTR_SIZE, /* Kernel-only */ @@ -157,6 +154,7 @@ enum ipset_errno { IPSET_ERR_COMMENT, IPSET_ERR_INVALID_MARKMASK, IPSET_ERR_SKBINFO, + IPSET_ERR_BITMASK_NETMASK_EXCL, /* Type specific error codes */ IPSET_ERR_TYPE_SPECIFIC = 4352, @@ -214,6 +212,8 @@ enum ipset_cadt_flags { enum ipset_create_flags { IPSET_CREATE_FLAG_BIT_FORCEADD = 0, IPSET_CREATE_FLAG_FORCEADD = (1 << IPSET_CREATE_FLAG_BIT_FORCEADD), + IPSET_CREATE_FLAG_BIT_BUCKETSIZE = 1, + IPSET_CREATE_FLAG_BUCKETSIZE = (1 << IPSET_CREATE_FLAG_BIT_BUCKETSIZE), IPSET_CREATE_FLAG_BIT_MAX = 7, }; 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 5bf6bbd..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,12 +59,9 @@ mtype_destroy(struct ip_set *set) { struct mtype *map = set->data; - if (SET_WITH_TIMEOUT(set)) - del_timer_sync(&map->gc); - - ip_set_free(map->members); if (set->dsize && set->extensions & IPSET_EXT_DESTROY) mtype_ext_cleanup(set); + ip_set_free(map->members); ip_set_free(map); set->data = NULL; @@ -76,7 +74,7 @@ mtype_flush(struct ip_set *set) if (set->extensions & IPSET_EXT_DESTROY) mtype_ext_cleanup(set); - memset(map->members, 0, map->memsize); + bitmap_zero(map->members, map->elements); set->elements = 0; set->ext_size = 0; } @@ -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_bitmap_ip.c b/kernel/net/netfilter/ipset/ip_set_bitmap_ip.c index 14d8e1a..f37169c 100644 --- a/kernel/net/netfilter/ipset/ip_set_bitmap_ip.c +++ b/kernel/net/netfilter/ipset/ip_set_bitmap_ip.c @@ -37,7 +37,7 @@ MODULE_ALIAS("ip_set_bitmap:ip"); /* Type structure */ struct bitmap_ip { - void *members; /* the set members */ + unsigned long *members; /* the set members */ u32 first_ip; /* host byte order, included in range */ u32 last_ip; /* host byte order, included in range */ u32 elements; /* number of max elements in the set */ @@ -48,7 +48,7 @@ struct bitmap_ip { #ifdef HAVE_TIMER_SETUP struct ip_set *set; /* attached to this ip_set */ #endif - unsigned char extensions[0] /* data extensions */ + unsigned char extensions[] /* data extensions */ __aligned(__alignof__(u64)); }; @@ -222,7 +222,7 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map, u32 first_ip, u32 last_ip, u32 elements, u32 hosts, u8 netmask) { - map->members = ip_set_alloc(map->memsize); + map->members = bitmap_zalloc(elements, GFP_KERNEL | __GFP_NOWARN); if (!map->members) return false; map->first_ip = first_ip; @@ -312,8 +312,8 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[], return -IPSET_ERR_BITMAP_RANGE; pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask); - hosts = 2 << (32 - netmask - 1); - elements = 2 << (netmask - mask_bits - 1); + hosts = 2U << (32 - netmask - 1); + elements = 2UL << (netmask - mask_bits - 1); } if (elements > IPSET_BITMAP_MAX_RANGE + 1) return -IPSET_ERR_BITMAP_RANGE_SIZE; @@ -326,11 +326,11 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[], if (!map) return -ENOMEM; - map->memsize = bitmap_bytes(0, elements - 1); + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); set->variant = &bitmap_ip; if (!init_map_ip(set, map, first_ip, last_ip, elements, hosts, netmask)) { - kfree(map); + ip_set_free(map); return -ENOMEM; } if (tb[IPSET_ATTR_TIMEOUT]) { diff --git a/kernel/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/kernel/net/netfilter/ipset/ip_set_bitmap_ipmac.c index fae14e2..3d25d29 100644 --- a/kernel/net/netfilter/ipset/ip_set_bitmap_ipmac.c +++ b/kernel/net/netfilter/ipset/ip_set_bitmap_ipmac.c @@ -43,7 +43,7 @@ enum { /* Type structure */ struct bitmap_ipmac { - void *members; /* the set members */ + unsigned long *members; /* the set members */ u32 first_ip; /* host byte order, included in range */ u32 last_ip; /* host byte order, included in range */ u32 elements; /* number of max elements in the set */ @@ -52,7 +52,7 @@ struct bitmap_ipmac { #ifdef HAVE_TIMER_SETUP struct ip_set *set; /* attached to this ip_set */ #endif - unsigned char extensions[0] /* MAC + data extensions */ + unsigned char extensions[] /* MAC + data extensions */ __aligned(__alignof__(u64)); }; @@ -302,7 +302,7 @@ static bool init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map, u32 first_ip, u32 last_ip, u32 elements) { - map->members = ip_set_alloc(map->memsize); + map->members = bitmap_zalloc(elements, GFP_KERNEL | __GFP_NOWARN); if (!map->members) return false; map->first_ip = first_ip; @@ -365,10 +365,10 @@ bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[], if (!map) return -ENOMEM; - map->memsize = bitmap_bytes(0, elements - 1); + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); set->variant = &bitmap_ipmac; if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) { - kfree(map); + ip_set_free(map); return -ENOMEM; } if (tb[IPSET_ATTR_TIMEOUT]) { diff --git a/kernel/net/netfilter/ipset/ip_set_bitmap_port.c b/kernel/net/netfilter/ipset/ip_set_bitmap_port.c index c38d28e..2a570d8 100644 --- a/kernel/net/netfilter/ipset/ip_set_bitmap_port.c +++ b/kernel/net/netfilter/ipset/ip_set_bitmap_port.c @@ -31,7 +31,7 @@ MODULE_ALIAS("ip_set_bitmap:port"); /* Type structure */ struct bitmap_port { - void *members; /* the set members */ + unsigned long *members; /* the set members */ u16 first_port; /* host byte order, included in range */ u16 last_port; /* host byte order, included in range */ u32 elements; /* number of max elements in the set */ @@ -40,7 +40,7 @@ struct bitmap_port { #ifdef HAVE_TIMER_SETUP struct ip_set *set; /* attached to this ip_set */ #endif - unsigned char extensions[0] /* data extensions */ + unsigned char extensions[] /* data extensions */ __aligned(__alignof__(u64)); }; @@ -234,7 +234,7 @@ static bool init_map_port(struct ip_set *set, struct bitmap_port *map, u16 first_port, u16 last_port) { - map->members = ip_set_alloc(map->memsize); + map->members = bitmap_zalloc(map->elements, GFP_KERNEL | __GFP_NOWARN); if (!map->members) return false; map->first_port = first_port; @@ -276,10 +276,10 @@ bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[], return -ENOMEM; map->elements = elements; - map->memsize = bitmap_bytes(0, map->elements); + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); set->variant = &bitmap_port; if (!init_map_port(set, map, first_port, last_port)) { - kfree(map); + ip_set_free(map); return -ENOMEM; } if (tb[IPSET_ATTR_TIMEOUT]) { diff --git a/kernel/net/netfilter/ipset/ip_set_core.c b/kernel/net/netfilter/ipset/ip_set_core.c index 4d8e8b1..c31dbc3 100644 --- a/kernel/net/netfilter/ipset/ip_set_core.c +++ b/kernel/net/netfilter/ipset/ip_set_core.c @@ -21,6 +21,7 @@ #include <linux/netfilter/x_tables.h> #include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/ipset/ip_set.h> +#include <linux/netfilter/ipset/ip_set_compiler.h> static LIST_HEAD(ip_set_type_list); /* all registered set types */ static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */ @@ -29,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 */ }; @@ -61,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 @@ -86,7 +88,8 @@ find_set_type(const char *name, u8 family, u8 revision) { struct ip_set_type *type; - list_for_each_entry_rcu(type, &ip_set_type_list, list) + list_for_each_entry_rcu_compat(type, &ip_set_type_list, list, + lockdep_is_held(&ip_set_type_mutex)) if (STRNCMP(type->name, name) && (type->family == family || type->family == NFPROTO_UNSPEC) && @@ -249,22 +252,7 @@ EXPORT_SYMBOL_GPL(ip_set_type_unregister); void * ip_set_alloc(size_t size) { - void *members = NULL; - - if (size < KMALLOC_MAX_SIZE) - members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); - - if (members) { - pr_debug("%p: allocated with kmalloc\n", members); - return members; - } - - members = vzalloc(size); - if (!members) - return NULL; - pr_debug("%p: allocated with vmalloc\n", members); - - return members; + return kvzalloc(size, GFP_KERNEL_ACCOUNT); } EXPORT_SYMBOL_GPL(ip_set_alloc); @@ -285,8 +273,7 @@ flag_nested(const struct nlattr *nla) static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = { [IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 }, - [IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY, - .len = sizeof(struct in6_addr) }, + [IPSET_ATTR_IPADDR_IPV6] = NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)), }; int @@ -368,7 +355,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment, c = kmalloc(sizeof(*c) + len + 1, GFP_ATOMIC); if (unlikely(!c)) return; - strlcpy(c->str, ext->comment, len + 1); + strscpy(c->str, ext->comment, len + 1); set->ext_size += sizeof(*c) + strlen(c->str) + 1; rcu_assign_pointer(comment->c, c); } @@ -459,6 +446,8 @@ ip_set_elem_len(struct ip_set *set, struct nlattr *tb[], size_t len, for (id = 0; id < IPSET_EXT_ID_MAX; id++) { if (!add_extension(id, cadt_flags, tb)) continue; + if (align < ip_set_extensions[id].align) + align = ip_set_extensions[id].align; len = ALIGN(len, ip_set_extensions[id].align); set->offset[id] = len; set->extensions |= ip_set_extensions[id].type; @@ -649,13 +638,14 @@ ip_set_match_extensions(struct ip_set *set, const struct ip_set_ext *ext, if (SET_WITH_COUNTER(set)) { struct ip_set_counter *counter = ext_counter(data, set); + ip_set_update_counter(counter, ext, flags); + if (flags & IPSET_FLAG_MATCH_COUNTERS && !(ip_set_match_counter(ip_set_get_packets(counter), mext->packets, mext->packets_op) && ip_set_match_counter(ip_set_get_bytes(counter), mext->bytes, mext->bytes_op))) return false; - ip_set_update_counter(counter, ext, flags); } if (SET_WITH_SKBINFO(set)) ip_set_get_skbinfo(ext_skbinfo(data, set), @@ -695,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); @@ -712,15 +710,24 @@ __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(); + /* ip_set_list and the set pointer need to be protected */ + return ip_set_dereference_nfnl(inst->ip_set_list)[index]; +} - return set; +static inline void +ip_set_lock(struct ip_set *set) +{ + if (!set->variant->region_lock) + spin_lock_bh(&set->lock); +} + +static inline void +ip_set_unlock(struct ip_set *set) +{ + if (!set->variant->region_lock) + spin_unlock_bh(&set->lock); } int @@ -737,16 +744,14 @@ 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 */ pr_debug("element must be completed, ADD is triggered\n"); - spin_lock_bh(&set->lock); + ip_set_lock(set); set->variant->kadt(set, skb, par, IPSET_ADD, opt); - spin_unlock_bh(&set->lock); + ip_set_unlock(set); ret = 1; } else { /* --return-nomatch: invert matched element */ @@ -775,9 +780,9 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb, !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) return -IPSET_ERR_TYPE_MISMATCH; - spin_lock_bh(&set->lock); + ip_set_lock(set); ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt); - spin_unlock_bh(&set->lock); + ip_set_unlock(set); return ret; } @@ -797,9 +802,9 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb, !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) return -IPSET_ERR_TYPE_MISMATCH; - spin_lock_bh(&set->lock); + ip_set_lock(set); ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt); - spin_unlock_bh(&set->lock); + ip_set_unlock(set); return ret; } @@ -872,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); @@ -920,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); @@ -961,20 +964,9 @@ static struct nlmsghdr * start_msg(struct sk_buff *skb, u32 portid, u32 seq, unsigned int flags, enum ipset_cmd cmd) { - struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; - - nlh = nlmsg_put(skb, portid, seq, nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd), - sizeof(*nfmsg), flags); - if (!nlh) - return NULL; - - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = NFPROTO_IPV4; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - - return nlh; + return nfnl_msg_put(skb, portid, seq, + nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd), flags, + NFPROTO_IPV4, NFNETLINK_V0, 0); } /* Create a set */ @@ -1044,7 +1036,8 @@ static int IPSET_CBFN(ip_set_none, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { return -EOPNOTSUPP; } @@ -1053,16 +1046,17 @@ static int IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { - struct net *net = IPSET_SOCK_NET(n, ctnl); + struct net *net = IPSET_SOCK_NET(n, ctnl, info); struct ip_set_net *inst = ip_set_pernet(net); struct ip_set *set, *clash = NULL; ip_set_id_t index = IPSET_INVALID_ID; struct nlattr *tb[IPSET_ATTR_CREATE_MAX + 1] = {}; const char *name, *typename; u8 family, revision; - u32 flags = flag_exist(nlh); + u32 flags = flag_exist(INFO_NLH(info, nlh)); int ret = 0; if (unlikely(protocol_min_failed(attr) || @@ -1088,7 +1082,7 @@ IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl, if (!set) return -ENOMEM; spin_lock_init(&set->lock); - strlcpy(set->name, name, IPSET_MAXNAMELEN); + strscpy(set->name, name, IPSET_MAXNAMELEN); set->family = family; set->revision = revision; @@ -1110,8 +1104,10 @@ IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl, ret = -IPSET_ERR_PROTOCOL; goto put_out; } + /* Set create flags depending on the type revision */ + set->flags |= set->type->create_flags[revision]; - ret = set->type->create(net, set, tb, flags); + ret = set->type->create(INFO_NET(info, net), set, tb, flags); if (ret != 0) goto put_out; @@ -1165,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); @@ -1182,24 +1179,58 @@ 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, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); struct ip_set *s; ip_set_id_t i; int ret = 0; @@ -1207,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 @@ -1220,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)) { @@ -1241,19 +1271,30 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl, /* Modified by ip_set_destroy() only, which is serialized */ 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) { - ret = -ENOENT; + if (!(flags & IPSET_FLAG_EXIST)) + ret = -ENOENT; goto out; } else if (s->ref || s->ref_netlink) { 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: @@ -1268,18 +1309,19 @@ ip_set_flush_set(struct ip_set *set) { pr_debug("set: %s\n", set->name); - spin_lock_bh(&set->lock); + ip_set_lock(set); set->variant->flush(set); - spin_unlock_bh(&set->lock); + ip_set_unlock(set); } static int IPSET_CBFN(ip_set_flush, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); struct ip_set *s; ip_set_id_t i; @@ -1318,9 +1360,10 @@ static int IPSET_CBFN(ip_set_rename, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); struct ip_set *set, *s; const char *name2; ip_set_id_t i; @@ -1349,7 +1392,7 @@ IPSET_CBFN(ip_set_rename, struct net *net, struct sock *ctnl, goto out; } } - strncpy(set->name, name2, IPSET_MAXNAMELEN); + strscpy_pad(set->name, name2, IPSET_MAXNAMELEN); out: write_unlock_bh(&ip_set_ref_lock); @@ -1369,9 +1412,10 @@ static int IPSET_CBFN(ip_set_swap, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); struct ip_set *from, *to; ip_set_id_t from_id, to_id; char from_name[IPSET_MAXNAMELEN]; @@ -1406,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; @@ -1490,31 +1534,40 @@ ip_set_dump_policy[IPSET_ATTR_CMD_MAX + 1] = { }; static int -dump_init(struct netlink_callback *cb, struct ip_set_net *inst) +ip_set_dump_start(struct netlink_callback *cb) { struct nlmsghdr *nlh = nlmsg_hdr(cb->skb); int min_len = nlmsg_total_size(sizeof(struct nfgenmsg)); struct nlattr *cda[IPSET_ATTR_CMD_MAX + 1]; struct nlattr *attr = (void *)nlh + min_len; + struct sk_buff *skb = cb->skb; + struct ip_set_net *inst = ip_set_pernet(sock_net(skb->sk)); u32 dump_type; - ip_set_id_t index; int ret; ret = NLA_PARSE(cda, IPSET_ATTR_CMD_MAX, attr, nlh->nlmsg_len - min_len, ip_set_dump_policy, NULL); if (ret) - return ret; + goto error; cb->args[IPSET_CB_PROTO] = nla_get_u8(cda[IPSET_ATTR_PROTOCOL]); if (cda[IPSET_ATTR_SETNAME]) { + ip_set_id_t index; struct ip_set *set; +#if HAVE_NETLINK_DUMP_START_ARGS != 4 + read_lock_bh(&ip_set_ref_lock); +#endif set = find_set_and_id(inst, nla_data(cda[IPSET_ATTR_SETNAME]), &index); - if (!set) - return -ENOENT; - +#if HAVE_NETLINK_DUMP_START_ARGS != 4 + read_unlock_bh(&ip_set_ref_lock); +#endif + if (!set) { + ret = -ENOENT; + goto error; + } dump_type = DUMP_ONE; cb->args[IPSET_CB_INDEX] = index; } else { @@ -1530,10 +1583,17 @@ dump_init(struct netlink_callback *cb, struct ip_set_net *inst) cb->args[IPSET_CB_DUMP] = dump_type; return 0; + +error: + /* We have to create and send the error message manually :-( */ + if (nlh->nlmsg_flags & NLM_F_ACK) { + NETLINK_ACK(cb->skb, nlh, ret, NULL); + } + return ret; } static int -ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) +ip_set_dump_do(struct sk_buff *skb, struct netlink_callback *cb) { ip_set_id_t index = IPSET_INVALID_ID, max; struct ip_set *set = NULL; @@ -1545,16 +1605,14 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) int ret = 0; if (!cb->args[IPSET_CB_DUMP]) { - ret = dump_init(cb, inst); +#if HAVE_NETLINK_DUMP_START_ARGS == 4 + return -EINVAL; +#else + ret = ip_set_dump_start(cb); if (ret < 0) { - nlh = nlmsg_hdr(cb->skb); - /* We have to create and send the error message - * manually :-( - */ - if (nlh->nlmsg_flags & NLM_F_ACK) - NETLINK_ACK(cb->skb, nlh, ret, NULL); return ret; } +#endif } if (cb->args[IPSET_CB_INDEX] >= inst->ip_set_max) @@ -1634,7 +1692,7 @@ dump_last: goto next_set; if (set->variant->uref) set->variant->uref(set, cb, true); - /* fall through */ + fallthrough; default: ret = set->variant->list(set, skb, cb); if (!cb->args[IPSET_CB_ARG0]) @@ -1685,26 +1743,30 @@ static int IPSET_CBFN(ip_set_dump, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { if (unlikely(protocol_min_failed(attr))) return -IPSET_ERR_PROTOCOL; #if HAVE_NETLINK_DUMP_START_ARGS == 5 return netlink_dump_start(ctnl, skb, nlh, - ip_set_dump_start, + ip_set_dump_do, ip_set_dump_done); #elif HAVE_NETLINK_DUMP_START_ARGS == 6 return netlink_dump_start(ctnl, skb, nlh, - ip_set_dump_start, + ip_set_dump_do, ip_set_dump_done, 0); #else { struct netlink_dump_control c = { - .dump = ip_set_dump_start, +#if HAVE_NETLINK_DUMP_START_ARGS == 4 + .start = ip_set_dump_start, +#endif + .dump = ip_set_dump_do, .done = ip_set_dump_done, }; - return netlink_dump_start(ctnl, skb, nlh, &c); + return netlink_dump_start(INFO_SK(info, ctnl), skb, INFO_NLH(info, nlh), &c); } #endif } @@ -1721,8 +1783,8 @@ static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = { }; static int -call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, - struct nlattr *tb[], enum ipset_adt adt, +CALL_AD(struct net *net, struct sock *ctnl, struct sk_buff *skb, + struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 flags, bool use_lineno) { int ret; @@ -1730,13 +1792,22 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, bool eexist = flags & IPSET_FLAG_EXIST, retried = false; do { - spin_lock_bh(&set->lock); + 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); - spin_unlock_bh(&set->lock); + ip_set_unlock(set); retried = true; - } while (ret == -EAGAIN && - set->variant->resize && - (ret = set->variant->resize(set, retried)) == 0); + } while (ret == -ERANGE || + (ret == -EAGAIN && + set->variant->resize && + (ret = set->variant->resize(set, retried)) == 0)); if (!ret || (ret == -IPSET_ERR_EXIST && eexist)) return 0; @@ -1755,11 +1826,12 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, skb2 = nlmsg_new(payload, GFP_KERNEL); if (!skb2) return -ENOMEM; - rep = __nlmsg_put(skb2, NETLINK_PORTID(skb), - nlh->nlmsg_seq, NLMSG_ERROR, payload, 0); + rep = nlmsg_put(skb2, NETLINK_PORTID(skb), + nlh->nlmsg_seq, NLMSG_ERROR, payload, 0); errmsg = nlmsg_data(rep); errmsg->error = ret; - memcpy(&errmsg->msg, nlh, nlh->nlmsg_len); + unsafe_memcpy(&errmsg->msg, nlh, nlh->nlmsg_len, + /* Bounds checked by the skb layer. */); cmdattr = (void *)&errmsg->msg + min_len; ret = NLA_PARSE(cda, IPSET_ATTR_CMD_MAX, cmdattr, @@ -1774,8 +1846,7 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, *errline = lineno; - netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), - MSG_DONTWAIT); + NFNETLINK_UNICAST(ctnl, skb2, net, NETLINK_PORTID(skb)); /* Signal netlink not to send its ACK/errmsg. */ return -EINTR; } @@ -1783,19 +1854,18 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, return ret; } -static int -IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl, - struct sk_buff *skb, - enum ipset_adt adt, - const struct nlmsghdr *nlh, - const struct nlattr * const attr[], - struct netlink_ext_ack *extack) -{ - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); +static int IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl, + struct sk_buff *skb, + enum ipset_adt adt, + const struct nlmsghdr *nlh, + const struct nlattr * const attr[], + struct netlink_ext_ack *extack, const struct nfnl_info *info) +{ + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); struct ip_set *set; struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; const struct nlattr *nla; - u32 flags = flag_exist(nlh); + u32 flags = flag_exist(INFO_NLH(info, nlh)); bool use_lineno; int ret = 0; @@ -1820,7 +1890,7 @@ IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl, attr[IPSET_ATTR_DATA], set->type->adt_policy, NULL)) return -IPSET_ERR_PROTOCOL; - ret = call_ad(ctnl, skb, set, tb, adt, flags, + ret = CALL_AD(net, ctnl, skb, set, tb, adt, flags, use_lineno); } else { int nla_rem; @@ -1831,7 +1901,7 @@ IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl, NLA_PARSE_NESTED(tb, IPSET_ATTR_ADT_MAX, nla, set->type->adt_policy, NULL)) return -IPSET_ERR_PROTOCOL; - ret = call_ad(ctnl, skb, set, tb, adt, + ret = CALL_AD(net, ctnl, skb, set, tb, adt, flags, use_lineno); if (ret < 0) return ret; @@ -1844,20 +1914,22 @@ static int IPSET_CBFN(ip_set_uadd, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { - return IPSET_CBFN_AD(ip_set_ad, net, ctnl, skb, - IPSET_ADD, nlh, attr, extack); + return IPSET_CBFN_AD(ip_set_ad, INFO_NET(info, net), INFO_SK(info, ctnl), skb, + IPSET_ADD, INFO_NLH(info, nlh), attr, extack, info); } static int IPSET_CBFN(ip_set_udel, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { - return IPSET_CBFN_AD(ip_set_ad, net, ctnl, skb, - IPSET_DEL, nlh, attr, extack); + return IPSET_CBFN_AD(ip_set_ad, INFO_NET(info, net), INFO_SK(info, ctnl), skb, + IPSET_DEL, INFO_NLH(info, nlh), attr, extack, info); } static int @@ -1865,12 +1937,14 @@ IPSET_CBFN(ip_set_utest, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); struct ip_set *set; struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; int ret = 0; + u32 lineno; if (unlikely(protocol_min_failed(attr) || !attr[IPSET_ATTR_SETNAME] || @@ -1887,7 +1961,7 @@ IPSET_CBFN(ip_set_utest, struct net *net, struct sock *ctnl, return -IPSET_ERR_PROTOCOL; rcu_read_lock_bh(); - ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0); + ret = set->variant->uadt(set, tb, IPSET_TEST, &lineno, 0, 0); rcu_read_unlock_bh(); /* Userspace can't trigger element to be re-added */ if (ret == -EAGAIN) @@ -1902,13 +1976,13 @@ static int IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); const struct ip_set *set; struct sk_buff *skb2; struct nlmsghdr *nlh2; - int ret = 0; if (unlikely(protocol_min_failed(attr) || !attr[IPSET_ATTR_SETNAME])) @@ -1922,7 +1996,7 @@ IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl, if (!skb2) return -ENOMEM; - nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0, IPSET_CMD_HEADER); if (!nlh2) goto nlmsg_failure; @@ -1934,11 +2008,7 @@ IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl, goto nla_put_failure; nlmsg_end(skb2, nlh2); - ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT); - if (ret < 0) - return ret; - - return 0; + return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb)); nla_put_failure: nlmsg_cancel(skb2, nlh2); @@ -1960,7 +2030,8 @@ static int IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { struct sk_buff *skb2; struct nlmsghdr *nlh2; @@ -1983,7 +2054,7 @@ IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl, if (!skb2) return -ENOMEM; - nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0, IPSET_CMD_TYPE); if (!nlh2) goto nlmsg_failure; @@ -1996,11 +2067,7 @@ IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl, nlmsg_end(skb2, nlh2); pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len); - ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT); - if (ret < 0) - return ret; - - return 0; + return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb)); nla_put_failure: nlmsg_cancel(skb2, nlh2); @@ -2020,11 +2087,11 @@ static int IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { struct sk_buff *skb2; struct nlmsghdr *nlh2; - int ret = 0; if (unlikely(!attr[IPSET_ATTR_PROTOCOL])) return -IPSET_ERR_PROTOCOL; @@ -2033,7 +2100,7 @@ IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl, if (!skb2) return -ENOMEM; - nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0, IPSET_CMD_PROTOCOL); if (!nlh2) goto nlmsg_failure; @@ -2043,11 +2110,7 @@ IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl, goto nla_put_failure; nlmsg_end(skb2, nlh2); - ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT); - if (ret < 0) - return ret; - - return 0; + return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb)); nla_put_failure: nlmsg_cancel(skb2, nlh2); @@ -2062,14 +2125,14 @@ static int IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); struct sk_buff *skb2; struct nlmsghdr *nlh2; ip_set_id_t id = IPSET_INVALID_ID; const struct ip_set *set; - int ret = 0; if (unlikely(protocol_failed(attr) || !attr[IPSET_ATTR_SETNAME])) @@ -2083,7 +2146,7 @@ IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl, if (!skb2) return -ENOMEM; - nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0, IPSET_CMD_GET_BYNAME); if (!nlh2) goto nlmsg_failure; @@ -2093,11 +2156,7 @@ IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl, goto nla_put_failure; nlmsg_end(skb2, nlh2); - ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT); - if (ret < 0) - return ret; - - return 0; + return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb)); nla_put_failure: nlmsg_cancel(skb2, nlh2); @@ -2115,14 +2174,14 @@ static int IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const attr[], - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + const struct nfnl_info *info) { - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); struct sk_buff *skb2; struct nlmsghdr *nlh2; ip_set_id_t id = IPSET_INVALID_ID; const struct ip_set *set; - int ret = 0; if (unlikely(protocol_failed(attr) || !attr[IPSET_ATTR_INDEX])) @@ -2139,7 +2198,7 @@ IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl, if (!skb2) return -ENOMEM; - nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0, IPSET_CMD_GET_BYINDEX); if (!nlh2) goto nlmsg_failure; @@ -2148,11 +2207,7 @@ IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl, goto nla_put_failure; nlmsg_end(skb2, nlh2); - ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT); - if (ret < 0) - return ret; - - return 0; + return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb)); nla_put_failure: nlmsg_cancel(skb2, nlh2); @@ -2164,80 +2219,96 @@ nlmsg_failure: static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = { [IPSET_CMD_NONE] = { .call = ip_set_none, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, }, [IPSET_CMD_CREATE] = { .call = ip_set_create, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_create_policy, }, [IPSET_CMD_DESTROY] = { .call = ip_set_destroy, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_setname_policy, }, [IPSET_CMD_FLUSH] = { .call = ip_set_flush, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_setname_policy, }, [IPSET_CMD_RENAME] = { .call = ip_set_rename, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_setname2_policy, }, [IPSET_CMD_SWAP] = { .call = ip_set_swap, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_setname2_policy, }, [IPSET_CMD_LIST] = { .call = ip_set_dump, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_dump_policy, }, [IPSET_CMD_SAVE] = { .call = ip_set_dump, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_setname_policy, }, [IPSET_CMD_ADD] = { .call = ip_set_uadd, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_adt_policy, }, [IPSET_CMD_DEL] = { .call = ip_set_udel, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_adt_policy, }, [IPSET_CMD_TEST] = { .call = ip_set_utest, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_adt_policy, }, [IPSET_CMD_HEADER] = { .call = ip_set_header, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_setname_policy, }, [IPSET_CMD_TYPE] = { .call = ip_set_type, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_type_policy, }, [IPSET_CMD_PROTOCOL] = { .call = ip_set_protocol, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_protocol_policy, }, [IPSET_CMD_GET_BYNAME] = { .call = ip_set_byname, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_setname_policy, }, [IPSET_CMD_GET_BYINDEX] = { .call = ip_set_byindex, + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_index_policy, }, @@ -2410,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; @@ -2427,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); @@ -2505,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 1767fed..76c3894 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_gen.h +++ b/kernel/net/netfilter/ipset/ip_set_hash_gen.h @@ -8,13 +8,21 @@ #include <linux/rcupdate.h> #include <linux/jhash.h> #include <linux/types.h> +#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/ipset/ip_set.h> -#define __ipset_dereference_protected(p, c) rcu_dereference_protected(p, c) -#define ipset_dereference_protected(p, set) \ - __ipset_dereference_protected(p, lockdep_is_held(&(set)->lock)) - -#define rcu_dereference_bh_nfnl(p) rcu_dereference_bh_check(p, 1) +#define __ipset_dereference(p) \ + rcu_dereference_protected(p, 1) +#define ipset_dereference_nfnl(p) \ + rcu_dereference_protected(p, \ + lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET)) +#define ipset_dereference_set(p, set) \ + rcu_dereference_protected(p, \ + lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \ + lockdep_is_held(&(set)->lock)) +#define ipset_dereference_bh_nfnl(p) \ + rcu_dereference_bh_check(p, \ + lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET)) /* Hashing which uses arrays to resolve clashing. The hash table is resized * (doubled) when searching becomes too long. @@ -30,37 +38,12 @@ */ /* Number of elements to store in an initial array block */ -#define AHASH_INIT_SIZE 4 +#define AHASH_INIT_SIZE 2 /* Max number of elements to store in an array block */ -#define AHASH_MAX_SIZE (3 * AHASH_INIT_SIZE) +#define AHASH_MAX_SIZE (6 * AHASH_INIT_SIZE) /* Max muber of elements in the array block when tuned */ #define AHASH_MAX_TUNED 64 - -/* Max number of elements can be tuned */ -#ifdef IP_SET_HASH_WITH_MULTI -#define AHASH_MAX(h) ((h)->ahash_max) - -static u8 -tune_ahash_max(u8 curr, u32 multi) -{ - u32 n; - - if (multi < curr) - return curr; - - n = curr + AHASH_INIT_SIZE; - /* Currently, at listing one hash bucket must fit into a message. - * Therefore we have a hard limit here. - */ - return n > curr && n <= AHASH_MAX_TUNED ? n : curr; -} - -#define TUNE_AHASH_MAX(h, multi) \ - ((h)->ahash_max = tune_ahash_max((h)->ahash_max, multi)) -#else -#define AHASH_MAX(h) AHASH_MAX_SIZE -#define TUNE_AHASH_MAX(h, multi) -#endif +#define AHASH_MAX(h) ((h)->bucketsize) /* A hash bucket */ struct hbucket { @@ -69,16 +52,40 @@ struct hbucket { DECLARE_BITMAP(used, AHASH_MAX_TUNED); u8 size; /* size of the array */ u8 pos; /* position of the first free entry */ - unsigned char value[0] /* the array of the values */ + unsigned char value[] /* the array of the values */ __aligned(__alignof__(u64)); }; +/* Region size for locking == 2^HTABLE_REGION_BITS */ +#define HTABLE_REGION_BITS 10 +#define ahash_numof_locks(htable_bits) \ + ((htable_bits) < HTABLE_REGION_BITS ? 1 \ + : jhash_size((htable_bits) - HTABLE_REGION_BITS)) +#define ahash_sizeof_regions(htable_bits) \ + (ahash_numof_locks(htable_bits) * sizeof(struct ip_set_region)) +#define ahash_region(n, htable_bits) \ + ((n) % ahash_numof_locks(htable_bits)) +#define ahash_bucket_start(h, htable_bits) \ + ((htable_bits) < HTABLE_REGION_BITS ? 0 \ + : (h) * jhash_size(HTABLE_REGION_BITS)) +#define ahash_bucket_end(h, htable_bits) \ + ((htable_bits) < HTABLE_REGION_BITS ? jhash_size(htable_bits) \ + : ((h) + 1) * jhash_size(HTABLE_REGION_BITS)) + +struct htable_gc { + struct delayed_work dwork; + struct ip_set *set; /* Set the gc belongs to */ + u32 region; /* Last gc run position */ +}; + /* The hash table: the table size stored here in order to make resizing easy */ struct htable { atomic_t ref; /* References for resizing */ - atomic_t uref; /* References for dumping */ + atomic_t uref; /* References for dumping and gc */ u8 htable_bits; /* size of hash table == 2^htable_bits */ - struct hbucket __rcu *bucket[0]; /* hashtable buckets */ + u32 maxelem; /* Maxelem per region */ + struct ip_set_region *hregion; /* Region locks and ext sizes */ + struct hbucket __rcu *bucket[]; /* hashtable buckets */ }; #define hbucket(h, i) ((h)->bucket[i]) @@ -101,31 +108,17 @@ htable_size(u8 hbits) { size_t hsize; - /* We must fit both into u32 in jhash and size_t */ + /* We must fit both into u32 in jhash and INT_MAX in kvmalloc_node() */ if (hbits > 31) return 0; hsize = jhash_size(hbits); - if ((((size_t)-1) - sizeof(struct htable)) / sizeof(struct hbucket *) + if ((INT_MAX - sizeof(struct htable)) / sizeof(struct hbucket *) < hsize) return 0; return hsize * sizeof(struct hbucket *) + sizeof(struct htable); } -/* Compute htable_bits from the user input parameter hashsize */ -static u8 -htable_bits(u32 hashsize) -{ - /* Assume that hashsize == 2^htable_bits */ - u8 bits = fls(hashsize - 1); - - if (jhash_size(bits) != hashsize) - /* Round up to the first 2^n value */ - bits = fls(hashsize); - - return bits; -} - #ifdef IP_SET_HASH_WITH_NETS #if IPSET_NET_COUNT > 1 #define __CIDR(cidr, i) (cidr[i]) @@ -163,6 +156,21 @@ htable_bits(u32 hashsize) #define NLEN 0 #endif /* IP_SET_HASH_WITH_NETS */ +#define SET_ELEM_EXPIRED(set, d) \ + (SET_WITH_TIMEOUT(set) && \ + ip_set_timeout_expired(ext_timeout(d, set))) + +#if defined(IP_SET_HASH_WITH_NETMASK) || defined(IP_SET_HASH_WITH_BITMASK) +static const union nf_inet_addr onesmask = { + .all[0] = 0xffffffff, + .all[1] = 0xffffffff, + .all[2] = 0xffffffff, + .all[3] = 0xffffffff +}; + +static const union nf_inet_addr zeromask = {}; +#endif + #endif /* _IP_SET_HASH_GEN_H */ #ifndef MTYPE @@ -206,12 +214,15 @@ htable_bits(u32 hashsize) #undef mtype_test_cidrs #undef mtype_test #undef mtype_uref -#undef mtype_expire #undef mtype_resize +#undef mtype_ext_size +#undef mtype_resize_ad #undef mtype_head #undef mtype_list +#undef mtype_gc_do #undef mtype_gc #undef mtype_gc_init +#undef mtype_cancel_gc #undef mtype_variant #undef mtype_data_match @@ -248,12 +259,15 @@ htable_bits(u32 hashsize) #define mtype_test_cidrs IPSET_TOKEN(MTYPE, _test_cidrs) #define mtype_test IPSET_TOKEN(MTYPE, _test) #define mtype_uref IPSET_TOKEN(MTYPE, _uref) -#define mtype_expire IPSET_TOKEN(MTYPE, _expire) #define mtype_resize IPSET_TOKEN(MTYPE, _resize) +#define mtype_ext_size IPSET_TOKEN(MTYPE, _ext_size) +#define mtype_resize_ad IPSET_TOKEN(MTYPE, _resize_ad) #define mtype_head IPSET_TOKEN(MTYPE, _head) #define mtype_list IPSET_TOKEN(MTYPE, _list) +#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) @@ -276,36 +290,44 @@ htable_bits(u32 hashsize) /* The generic hash structure */ struct htype { struct htable __rcu *table; /* the hash table */ - struct timer_list gc; /* garbage collection when timeout enabled */ -#ifdef HAVE_TIMER_SETUP - struct ip_set *set; /* attached to this ip_set */ -#endif + struct htable_gc gc; /* gc workqueue */ u32 maxelem; /* max elements in the hash */ u32 initval; /* random jhash init value */ #ifdef IP_SET_HASH_WITH_MARKMASK u32 markmask; /* markmask value for mark mask to store */ #endif -#ifdef IP_SET_HASH_WITH_MULTI - u8 ahash_max; /* max elements in an array block */ -#endif -#ifdef IP_SET_HASH_WITH_NETMASK + u8 bucketsize; /* max elements in an array block */ +#if defined(IP_SET_HASH_WITH_NETMASK) || defined(IP_SET_HASH_WITH_BITMASK) u8 netmask; /* netmask value for subnets to store */ + union nf_inet_addr bitmask; /* stores bitmask */ #endif + struct list_head ad; /* Resize add|del backlist */ struct mtype_elem next; /* temporary storage for uadd */ #ifdef IP_SET_HASH_WITH_NETS struct net_prefixes nets[NLEN]; /* book-keeping of prefixes */ #endif }; +/* ADD|DEL entries saved during resize */ +struct mtype_resize_ad { + struct list_head list; + enum ipset_adt ad; /* ADD|DEL element */ + struct mtype_elem d; /* Element value */ + struct ip_set_ext ext; /* Extensions for ADD */ + struct ip_set_ext mext; /* Target extensions for ADD */ + u32 flags; /* Flags for ADD */ +}; + #ifdef IP_SET_HASH_WITH_NETS /* Network cidr size book keeping when the hash stores different * sized networks. cidr == real cidr + 1 to support /0. */ static void -mtype_add_cidr(struct htype *h, u8 cidr, u8 n) +mtype_add_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n) { int i, j; + spin_lock_bh(&set->lock); /* Add in increasing prefix order, so larger cidr first */ for (i = 0, j = -1; i < NLEN && h->nets[i].cidr[n]; i++) { if (j != -1) { @@ -314,7 +336,7 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n) j = i; } else if (h->nets[i].cidr[n] == cidr) { h->nets[CIDR_POS(cidr)].nets[n]++; - return; + goto unlock; } } if (j != -1) { @@ -323,24 +345,29 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n) } h->nets[i].cidr[n] = cidr; h->nets[CIDR_POS(cidr)].nets[n] = 1; +unlock: + spin_unlock_bh(&set->lock); } static void -mtype_del_cidr(struct htype *h, u8 cidr, u8 n) +mtype_del_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n) { u8 i, j, net_end = NLEN - 1; + spin_lock_bh(&set->lock); for (i = 0; i < NLEN; i++) { if (h->nets[i].cidr[n] != cidr) continue; h->nets[CIDR_POS(cidr)].nets[n]--; if (h->nets[CIDR_POS(cidr)].nets[n] > 0) - return; + goto unlock; for (j = i; j < net_end && h->nets[j].cidr[n]; j++) h->nets[j].cidr[n] = h->nets[j + 1].cidr[n]; h->nets[j].cidr[n] = 0; - return; + goto unlock; } +unlock: + spin_unlock_bh(&set->lock); } #endif @@ -348,7 +375,7 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 n) static size_t mtype_ahash_memsize(const struct htype *h, const struct htable *t) { - return sizeof(*h) + sizeof(*t); + return sizeof(*h) + sizeof(*t) + ahash_sizeof_regions(t->htable_bits); } /* Get the ith element from the array block n */ @@ -372,24 +399,29 @@ mtype_flush(struct ip_set *set) struct htype *h = set->data; struct htable *t; struct hbucket *n; - u32 i; - - t = ipset_dereference_protected(h->table, set); - for (i = 0; i < jhash_size(t->htable_bits); i++) { - n = __ipset_dereference_protected(hbucket(t, i), 1); - if (!n) - continue; - if (set->extensions & IPSET_EXT_DESTROY) - mtype_ext_cleanup(set, n); - /* FIXME: use slab cache */ - rcu_assign_pointer(hbucket(t, i), NULL); - kfree_rcu(n, rcu); + u32 r, i; + + t = ipset_dereference_nfnl(h->table); + for (r = 0; r < ahash_numof_locks(t->htable_bits); r++) { + spin_lock_bh(&t->hregion[r].lock); + for (i = ahash_bucket_start(r, t->htable_bits); + i < ahash_bucket_end(r, t->htable_bits); i++) { + n = __ipset_dereference(hbucket(t, i)); + if (!n) + continue; + if (set->extensions & IPSET_EXT_DESTROY) + mtype_ext_cleanup(set, n); + /* FIXME: use slab cache */ + rcu_assign_pointer(hbucket(t, i), NULL); + kfree_rcu(n, rcu); + } + t->hregion[r].ext_size = 0; + t->hregion[r].elements = 0; + spin_unlock_bh(&t->hregion[r].lock); } #ifdef IP_SET_HASH_WITH_NETS memset(h->nets, 0, sizeof(h->nets)); #endif - set->elements = 0; - set->ext_size = 0; } /* Destroy the hashtable part of the set */ @@ -400,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_protected(hbucket(t, i), 1); + n = (__force struct hbucket *)hbucket(t, i); if (!n) continue; if (set->extensions & IPSET_EXT_DESTROY && ext_destroy) @@ -409,6 +441,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy) kfree(n); } + ip_set_free(t->hregion); ip_set_free(t); } @@ -417,28 +450,18 @@ static void mtype_destroy(struct ip_set *set) { struct htype *h = set->data; + struct list_head *l, *lt; - if (SET_WITH_TIMEOUT(set)) - del_timer_sync(&h->gc); - - mtype_ahash_destroy(set, - __ipset_dereference_protected(h->table, 1), true); + mtype_ahash_destroy(set, (__force struct htable *)h->table, true); + list_for_each_safe(l, lt, &h->ad) { + list_del(l); + kfree(l); + } kfree(h); set->data = NULL; } -static void -mtype_gc_init(struct ip_set *set, void (*gc)(GC_ARG)) -{ - struct htype *h = set->data; - - TIMER_SETUP(&h->gc, gc); - mod_timer(&h->gc, jiffies + IPSET_GC_PERIOD(set->timeout) * HZ); - pr_debug("gc initialized, run in every %u\n", - IPSET_GC_PERIOD(set->timeout)); -} - static bool mtype_same_set(const struct ip_set *a, const struct ip_set *b) { @@ -448,8 +471,8 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b) /* Resizing changes htable_bits, so we ignore it */ return x->maxelem == y->maxelem && a->timeout == b->timeout && -#ifdef IP_SET_HASH_WITH_NETMASK - x->netmask == y->netmask && +#if defined(IP_SET_HASH_WITH_NETMASK) || defined(IP_SET_HASH_WITH_BITMASK) + nf_inet_addr_cmp(&x->bitmask, &y->bitmask) && #endif #ifdef IP_SET_HASH_WITH_MARKMASK x->markmask == y->markmask && @@ -457,11 +480,9 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b) a->extensions == b->extensions; } -/* Delete expired elements from the hashtable */ static void -mtype_expire(struct ip_set *set, struct htype *h) +mtype_gc_do(struct ip_set *set, struct htype *h, struct htable *t, u32 r) { - struct htable *t; struct hbucket *n, *tmp; struct mtype_elem *data; u32 i, j, d; @@ -469,10 +490,12 @@ mtype_expire(struct ip_set *set, struct htype *h) #ifdef IP_SET_HASH_WITH_NETS u8 k; #endif + u8 htable_bits = t->htable_bits; - t = ipset_dereference_protected(h->table, set); - for (i = 0; i < jhash_size(t->htable_bits); i++) { - n = __ipset_dereference_protected(hbucket(t, i), 1); + spin_lock_bh(&t->hregion[r].lock); + for (i = ahash_bucket_start(r, htable_bits); + i < ahash_bucket_end(r, htable_bits); i++) { + n = __ipset_dereference(hbucket(t, i)); if (!n) continue; for (j = 0, d = 0; j < n->pos; j++) { @@ -488,58 +511,108 @@ mtype_expire(struct ip_set *set, struct htype *h) smp_mb__after_atomic(); #ifdef IP_SET_HASH_WITH_NETS for (k = 0; k < IPSET_NET_COUNT; k++) - mtype_del_cidr(h, + mtype_del_cidr(set, h, NCIDR_PUT(DCIDR_GET(data->cidr, k)), k); #endif + t->hregion[r].elements--; ip_set_ext_destroy(set, data); - set->elements--; d++; } if (d >= AHASH_INIT_SIZE) { if (d >= n->size) { - set->ext_size -= ext_size(n->size, dsize); + t->hregion[r].ext_size -= + ext_size(n->size, dsize); rcu_assign_pointer(hbucket(t, i), NULL); kfree_rcu(n, rcu); continue; } tmp = kzalloc(sizeof(*tmp) + - (n->size - AHASH_INIT_SIZE) * dsize, - GFP_ATOMIC); + (n->size - AHASH_INIT_SIZE) * dsize, + GFP_ATOMIC); if (!tmp) - /* Still try to delete expired elements */ + /* Still try to delete expired elements. */ continue; tmp->size = n->size - AHASH_INIT_SIZE; for (j = 0, d = 0; j < n->pos; j++) { if (!test_bit(j, n->used)) continue; data = ahash_data(n, j, dsize); - memcpy(tmp->value + d * dsize, data, dsize); + memcpy(tmp->value + d * dsize, + data, dsize); set_bit(d, tmp->used); d++; } tmp->pos = d; - set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize); + t->hregion[r].ext_size -= + ext_size(AHASH_INIT_SIZE, dsize); rcu_assign_pointer(hbucket(t, i), tmp); kfree_rcu(n, rcu); } } + spin_unlock_bh(&t->hregion[r].lock); } static void -mtype_gc(GC_ARG) +mtype_gc(struct work_struct *work) { - INIT_GC_VARS(htype, h); + struct htable_gc *gc; + struct ip_set *set; + struct htype *h; + struct htable *t; + u32 r, numof_locks; + unsigned int next_run; + + gc = container_of(work, struct htable_gc, dwork.work); + set = gc->set; + h = set->data; - pr_debug("called\n"); spin_lock_bh(&set->lock); - mtype_expire(set, h); + t = ipset_dereference_set(h->table, set); + atomic_inc(&t->uref); + numof_locks = ahash_numof_locks(t->htable_bits); + r = gc->region++; + if (r >= numof_locks) { + r = gc->region = 0; + } + next_run = (IPSET_GC_PERIOD(set->timeout) * HZ) / numof_locks; + if (next_run < HZ/10) + next_run = HZ/10; spin_unlock_bh(&set->lock); - h->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ; - add_timer(&h->gc); + mtype_gc_do(set, h, t, r); + + if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) { + pr_debug("Table destroy after resize by expire: %p\n", t); + mtype_ahash_destroy(set, t, false); + } + + queue_delayed_work(system_power_efficient_wq, &gc->dwork, next_run); } +static void +mtype_gc_init(struct htable_gc *gc) +{ + INIT_DEFERRABLE_WORK(&gc->dwork, mtype_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); +static int +mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, + struct ip_set_ext *mext, u32 flags); + /* Resize a hash: create a new hash table with doubling the hashsize * and inserting the elements to it. Repeat until we succeed or * fail due to memory pressures. @@ -550,7 +623,7 @@ mtype_resize(struct ip_set *set, bool retried) struct htype *h = set->data; struct htable *t, *orig; u8 htable_bits; - size_t extsize, dsize = set->dsize; + size_t hsize, dsize = set->dsize; #ifdef IP_SET_HASH_WITH_NETS u8 flags; struct mtype_elem *tmp; @@ -558,7 +631,9 @@ mtype_resize(struct ip_set *set, bool retried) struct mtype_elem *data; struct mtype_elem *d; struct hbucket *n, *m; - u32 i, j, key; + struct list_head *l, *lt; + struct mtype_resize_ad *x; + u32 i, j, r, nr, key; int ret; #ifdef IP_SET_HASH_WITH_NETS @@ -566,108 +641,140 @@ mtype_resize(struct ip_set *set, bool retried) if (!tmp) return -ENOMEM; #endif - rcu_read_lock_bh(); - orig = rcu_dereference_bh_nfnl(h->table); + orig = ipset_dereference_bh_nfnl(h->table); htable_bits = orig->htable_bits; - rcu_read_unlock_bh(); retry: ret = 0; htable_bits++; - if (!htable_bits) { - /* In case we have plenty of memory :-) */ - pr_warn("Cannot increase the hashsize of set %s further\n", - set->name); - ret = -IPSET_ERR_HASH_FULL; + if (!htable_bits) + goto hbwarn; + hsize = htable_size(htable_bits); + if (!hsize) + goto hbwarn; + t = ip_set_alloc(hsize); + if (!t) { + ret = -ENOMEM; goto out; } - t = ip_set_alloc(htable_size(htable_bits)); - if (!t) { + t->hregion = ip_set_alloc(ahash_sizeof_regions(htable_bits)); + if (!t->hregion) { + ip_set_free(t); ret = -ENOMEM; goto out; } t->htable_bits = htable_bits; + t->maxelem = h->maxelem / ahash_numof_locks(htable_bits); + for (i = 0; i < ahash_numof_locks(htable_bits); i++) + spin_lock_init(&t->hregion[i].lock); - spin_lock_bh(&set->lock); - orig = __ipset_dereference_protected(h->table, 1); - /* There can't be another parallel resizing, but dumping is possible */ + /* There can't be another parallel resizing, + * but dumping, gc, kernel side add/del are possible + */ + orig = ipset_dereference_bh_nfnl(h->table); atomic_set(&orig->ref, 1); atomic_inc(&orig->uref); - extsize = 0; pr_debug("attempt to resize set %s from %u to %u, t %p\n", set->name, orig->htable_bits, htable_bits, orig); - for (i = 0; i < jhash_size(orig->htable_bits); i++) { - n = __ipset_dereference_protected(hbucket(orig, i), 1); - if (!n) - continue; - for (j = 0; j < n->pos; j++) { - if (!test_bit(j, n->used)) + for (r = 0; r < ahash_numof_locks(orig->htable_bits); r++) { + /* Expire may replace a hbucket with another one */ + rcu_read_lock_bh(); + for (i = ahash_bucket_start(r, orig->htable_bits); + i < ahash_bucket_end(r, orig->htable_bits); i++) { + n = __ipset_dereference(hbucket(orig, i)); + if (!n) continue; - data = ahash_data(n, j, dsize); + for (j = 0; j < n->pos; j++) { + if (!test_bit(j, n->used)) + continue; + data = ahash_data(n, j, dsize); + if (SET_ELEM_EXPIRED(set, data)) + continue; #ifdef IP_SET_HASH_WITH_NETS - /* We have readers running parallel with us, - * so the live data cannot be modified. - */ - flags = 0; - memcpy(tmp, data, dsize); - data = tmp; - mtype_data_reset_flags(data, &flags); + /* We have readers running parallel with us, + * so the live data cannot be modified. + */ + flags = 0; + memcpy(tmp, data, dsize); + data = tmp; + mtype_data_reset_flags(data, &flags); #endif - key = HKEY(data, h->initval, htable_bits); - m = __ipset_dereference_protected(hbucket(t, key), 1); - if (!m) { - m = kzalloc(sizeof(*m) + + key = HKEY(data, h->initval, htable_bits); + m = __ipset_dereference(hbucket(t, key)); + nr = ahash_region(key, htable_bits); + if (!m) { + m = kzalloc(sizeof(*m) + AHASH_INIT_SIZE * dsize, GFP_ATOMIC); - if (!m) { - ret = -ENOMEM; - goto cleanup; - } - m->size = AHASH_INIT_SIZE; - extsize += ext_size(AHASH_INIT_SIZE, dsize); - RCU_INIT_POINTER(hbucket(t, key), m); - } else if (m->pos >= m->size) { - struct hbucket *ht; - - if (m->size >= AHASH_MAX(h)) { - ret = -EAGAIN; - } else { - ht = kzalloc(sizeof(*ht) + + if (!m) { + ret = -ENOMEM; + goto cleanup; + } + m->size = AHASH_INIT_SIZE; + t->hregion[nr].ext_size += + ext_size(AHASH_INIT_SIZE, + dsize); + RCU_INIT_POINTER(hbucket(t, key), m); + } else if (m->pos >= m->size) { + struct hbucket *ht; + + if (m->size >= AHASH_MAX(h)) { + ret = -EAGAIN; + } else { + ht = kzalloc(sizeof(*ht) + (m->size + AHASH_INIT_SIZE) * dsize, GFP_ATOMIC); - if (!ht) - ret = -ENOMEM; + if (!ht) + ret = -ENOMEM; + } + if (ret < 0) + goto cleanup; + memcpy(ht, m, sizeof(struct hbucket) + + m->size * dsize); + ht->size = m->size + AHASH_INIT_SIZE; + t->hregion[nr].ext_size += + ext_size(AHASH_INIT_SIZE, + dsize); + kfree(m); + m = ht; + RCU_INIT_POINTER(hbucket(t, key), ht); } - if (ret < 0) - goto cleanup; - memcpy(ht, m, sizeof(struct hbucket) + - m->size * dsize); - ht->size = m->size + AHASH_INIT_SIZE; - extsize += ext_size(AHASH_INIT_SIZE, dsize); - kfree(m); - m = ht; - RCU_INIT_POINTER(hbucket(t, key), ht); - } - d = ahash_data(m, m->pos, dsize); - memcpy(d, data, dsize); - set_bit(m->pos++, m->used); + d = ahash_data(m, m->pos, dsize); + memcpy(d, data, dsize); + set_bit(m->pos++, m->used); + t->hregion[nr].elements++; #ifdef IP_SET_HASH_WITH_NETS - mtype_data_reset_flags(d, &flags); + mtype_data_reset_flags(d, &flags); #endif + } } + rcu_read_unlock_bh(); } - rcu_assign_pointer(h->table, t); - set->ext_size = extsize; - spin_unlock_bh(&set->lock); + /* There can't be any other writer. */ + rcu_assign_pointer(h->table, t); /* Give time to other readers of the set */ synchronize_rcu(); pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name, orig->htable_bits, orig, t->htable_bits, t); - /* If there's nobody else dumping the table, destroy it */ + /* Add/delete elements processed by the SET target during resize. + * Kernel-side add cannot trigger a resize and userspace actions + * are serialized by the mutex. + */ + list_for_each_safe(l, lt, &h->ad) { + x = list_entry(l, struct mtype_resize_ad, list); + if (x->ad == IPSET_ADD) { + mtype_add(set, &x->d, &x->ext, &x->mext, x->flags); + } else { + mtype_del(set, &x->d, NULL, NULL, 0); + } + list_del(l); + kfree(l); + } + /* If there's nobody else using the table, destroy it */ if (atomic_dec_and_test(&orig->uref)) { pr_debug("Table destroy by resize %p\n", orig); mtype_ahash_destroy(set, orig, false); @@ -680,13 +787,49 @@ out: return ret; cleanup: + rcu_read_unlock_bh(); atomic_set(&orig->ref, 0); atomic_dec(&orig->uref); - spin_unlock_bh(&set->lock); mtype_ahash_destroy(set, t, false); if (ret == -EAGAIN) goto retry; goto out; + +hbwarn: + /* In case we have plenty of memory :-) */ + pr_warn("Cannot increase the hashsize of set %s further\n", set->name); + ret = -IPSET_ERR_HASH_FULL; + goto out; +} + +/* Get the current number of elements and ext_size in the set */ +static void +mtype_ext_size(struct ip_set *set, u32 *elements, size_t *ext_size) +{ + struct htype *h = set->data; + const struct htable *t; + u32 i, j, r; + struct hbucket *n; + struct mtype_elem *data; + + *elements = 0; + t = rcu_dereference_bh(h->table); + for (r = 0; r < ahash_numof_locks(t->htable_bits); r++) { + for (i = ahash_bucket_start(r, t->htable_bits); + i < ahash_bucket_end(r, t->htable_bits); i++) { + n = rcu_dereference_bh(hbucket(t, i)); + if (!n) + continue; + for (j = 0; j < n->pos; j++) { + if (!test_bit(j, n->used)) + continue; + data = ahash_data(n, j, set->dsize); + if (!SET_ELEM_EXPIRED(set, data)) + (*elements)++; + } + } + *ext_size += t->hregion[r].ext_size; + } } /* Add an element to a hash and update the internal counters when succeeded, @@ -701,32 +844,49 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, const struct mtype_elem *d = value; struct mtype_elem *data; struct hbucket *n, *old = ERR_PTR(-ENOENT); - int i, j = -1; + int i, j = -1, ret; bool flag_exist = flags & IPSET_FLAG_EXIST; bool deleted = false, forceadd = false, reuse = false; - u32 key, multi = 0; + u32 r, key, multi = 0, elements, maxelem; - if (set->elements >= h->maxelem) { - if (SET_WITH_TIMEOUT(set)) - /* FIXME: when set is full, we slow down here */ - mtype_expire(set, h); - if (set->elements >= h->maxelem && SET_WITH_FORCEADD(set)) + rcu_read_lock_bh(); + t = rcu_dereference_bh(h->table); + key = HKEY(value, h->initval, t->htable_bits); + r = ahash_region(key, t->htable_bits); + atomic_inc(&t->uref); + elements = t->hregion[r].elements; + maxelem = t->maxelem; + if (elements >= maxelem) { + u32 e; + if (SET_WITH_TIMEOUT(set)) { + rcu_read_unlock_bh(); + mtype_gc_do(set, h, t, r); + rcu_read_lock_bh(); + } + maxelem = h->maxelem; + elements = 0; + for (e = 0; e < ahash_numof_locks(t->htable_bits); e++) + elements += t->hregion[e].elements; + if (elements >= maxelem && SET_WITH_FORCEADD(set)) forceadd = true; } + rcu_read_unlock_bh(); - t = ipset_dereference_protected(h->table, set); - key = HKEY(value, h->initval, t->htable_bits); - n = __ipset_dereference_protected(hbucket(t, key), 1); + spin_lock_bh(&t->hregion[r].lock); + n = rcu_dereference_bh(hbucket(t, key)); if (!n) { - if (forceadd || set->elements >= h->maxelem) + if (forceadd || elements >= maxelem) goto set_full; old = NULL; n = kzalloc(sizeof(*n) + AHASH_INIT_SIZE * set->dsize, GFP_ATOMIC); - if (!n) - return -ENOMEM; + if (!n) { + ret = -ENOMEM; + goto unlock; + } n->size = AHASH_INIT_SIZE; - set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize); + t->hregion[r].ext_size += + ext_size(AHASH_INIT_SIZE, set->dsize); goto copy_elem; } for (i = 0; i < n->pos; i++) { @@ -740,67 +900,75 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, } data = ahash_data(n, i, set->dsize); if (mtype_data_equal(data, d, &multi)) { - if (flag_exist || - (SET_WITH_TIMEOUT(set) && - ip_set_timeout_expired(ext_timeout(data, set)))) { + if (flag_exist || SET_ELEM_EXPIRED(set, data)) { /* Just the extensions could be overwritten */ j = i; goto overwrite_extensions; } - return -IPSET_ERR_EXIST; + ret = -IPSET_ERR_EXIST; + goto unlock; } /* Reuse first timed out entry */ - if (SET_WITH_TIMEOUT(set) && - ip_set_timeout_expired(ext_timeout(data, set)) && - j == -1) { + if (SET_ELEM_EXPIRED(set, data) && j == -1) { j = i; reuse = true; } } if (reuse || forceadd) { + if (j == -1) + j = 0; data = ahash_data(n, j, set->dsize); if (!deleted) { #ifdef IP_SET_HASH_WITH_NETS for (i = 0; i < IPSET_NET_COUNT; i++) - mtype_del_cidr(h, + mtype_del_cidr(set, h, NCIDR_PUT(DCIDR_GET(data->cidr, i)), i); #endif ip_set_ext_destroy(set, data); - set->elements--; + t->hregion[r].elements--; } goto copy_data; } - if (set->elements >= h->maxelem) + if (elements >= maxelem) goto set_full; /* Create a new slot */ if (n->pos >= n->size) { - TUNE_AHASH_MAX(h, multi); +#ifdef IP_SET_HASH_WITH_MULTI + if (h->bucketsize >= AHASH_MAX_TUNED) + goto set_full; + else if (h->bucketsize <= multi) + h->bucketsize += AHASH_INIT_SIZE; +#endif if (n->size >= AHASH_MAX(h)) { /* Trigger rehashing */ mtype_data_next(&h->next, d); - return -EAGAIN; + ret = -EAGAIN; + goto resize; } old = n; n = kzalloc(sizeof(*n) + (old->size + AHASH_INIT_SIZE) * set->dsize, GFP_ATOMIC); - if (!n) - return -ENOMEM; + if (!n) { + ret = -ENOMEM; + goto unlock; + } memcpy(n, old, sizeof(struct hbucket) + old->size * set->dsize); n->size = old->size + AHASH_INIT_SIZE; - set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize); + t->hregion[r].ext_size += + ext_size(AHASH_INIT_SIZE, set->dsize); } copy_elem: j = n->pos++; data = ahash_data(n, j, set->dsize); copy_data: - set->elements++; + t->hregion[r].elements++; #ifdef IP_SET_HASH_WITH_NETS for (i = 0; i < IPSET_NET_COUNT; i++) - mtype_add_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, i)), i); + mtype_add_cidr(set, h, NCIDR_PUT(DCIDR_GET(d->cidr, i)), i); #endif memcpy(data, d, sizeof(struct mtype_elem)); overwrite_extensions: @@ -823,13 +991,41 @@ overwrite_extensions: if (old) kfree_rcu(old, rcu); } + ret = 0; +resize: + spin_unlock_bh(&t->hregion[r].lock); + if (atomic_read(&t->ref) && ext->target) { + /* Resize is in process and kernel side add, save values */ + struct mtype_resize_ad *x; + + x = kzalloc(sizeof(struct mtype_resize_ad), GFP_ATOMIC); + if (!x) + /* Don't bother */ + goto out; + x->ad = IPSET_ADD; + memcpy(&x->d, value, sizeof(struct mtype_elem)); + memcpy(&x->ext, ext, sizeof(struct ip_set_ext)); + memcpy(&x->mext, mext, sizeof(struct ip_set_ext)); + x->flags = flags; + spin_lock_bh(&set->lock); + list_add_tail(&x->list, &h->ad); + spin_unlock_bh(&set->lock); + } + goto out; - return 0; set_full: if (net_ratelimit()) pr_warn("Set %s is full, maxelem %u reached\n", - set->name, h->maxelem); - return -IPSET_ERR_HASH_FULL; + set->name, maxelem); + ret = -IPSET_ERR_HASH_FULL; +unlock: + spin_unlock_bh(&t->hregion[r].lock); +out: + if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) { + pr_debug("Table destroy after resize by add: %p\n", t); + mtype_ahash_destroy(set, t, false); + } + return ret; } /* Delete an element from the hash and free up space if possible. @@ -843,13 +1039,23 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, const struct mtype_elem *d = value; struct mtype_elem *data; struct hbucket *n; - int i, j, k, ret = -IPSET_ERR_EXIST; + struct mtype_resize_ad *x = NULL; + int i, j, k, r, ret = -IPSET_ERR_EXIST; u32 key, multi = 0; size_t dsize = set->dsize; - t = ipset_dereference_protected(h->table, set); + /* Userspace add and resize is excluded by the mutex. + * Kernespace add does not trigger resize. + */ + rcu_read_lock_bh(); + t = rcu_dereference_bh(h->table); key = HKEY(value, h->initval, t->htable_bits); - n = __ipset_dereference_protected(hbucket(t, key), 1); + r = ahash_region(key, t->htable_bits); + atomic_inc(&t->uref); + rcu_read_unlock_bh(); + + spin_lock_bh(&t->hregion[r].lock); + n = rcu_dereference_bh(hbucket(t, key)); if (!n) goto out; for (i = 0, k = 0; i < n->pos; i++) { @@ -860,8 +1066,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, data = ahash_data(n, i, dsize); if (!mtype_data_equal(data, d, &multi)) continue; - if (SET_WITH_TIMEOUT(set) && - ip_set_timeout_expired(ext_timeout(data, set))) + if (SET_ELEM_EXPIRED(set, data)) goto out; ret = 0; @@ -869,20 +1074,33 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, smp_mb__after_atomic(); if (i + 1 == n->pos) n->pos--; - set->elements--; + t->hregion[r].elements--; #ifdef IP_SET_HASH_WITH_NETS for (j = 0; j < IPSET_NET_COUNT; j++) - mtype_del_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, j)), - j); + mtype_del_cidr(set, h, + NCIDR_PUT(DCIDR_GET(d->cidr, j)), j); #endif ip_set_ext_destroy(set, data); + if (atomic_read(&t->ref) && ext->target) { + /* Resize is in process and kernel side del, + * save values + */ + x = kzalloc(sizeof(struct mtype_resize_ad), + GFP_ATOMIC); + if (x) { + x->ad = IPSET_DEL; + memcpy(&x->d, value, + sizeof(struct mtype_elem)); + x->flags = flags; + } + } for (; i < n->pos; i++) { if (!test_bit(i, n->used)) k++; } if (n->pos == 0 && k == 0) { - set->ext_size -= ext_size(n->size, dsize); + t->hregion[r].ext_size -= ext_size(n->size, dsize); rcu_assign_pointer(hbucket(t, key), NULL); kfree_rcu(n, rcu); } else if (k >= AHASH_INIT_SIZE) { @@ -901,7 +1119,8 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, k++; } tmp->pos = k; - set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize); + t->hregion[r].ext_size -= + ext_size(AHASH_INIT_SIZE, dsize); rcu_assign_pointer(hbucket(t, key), tmp); kfree_rcu(n, rcu); } @@ -909,6 +1128,16 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, } out: + spin_unlock_bh(&t->hregion[r].lock); + if (x) { + spin_lock_bh(&set->lock); + list_add(&x->list, &h->ad); + spin_unlock_bh(&set->lock); + } + if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) { + pr_debug("Table destroy after resize by del: %p\n", t); + mtype_ahash_destroy(set, t, false); + } return ret; } @@ -994,6 +1223,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext, int i, ret = 0; u32 key, multi = 0; + rcu_read_lock_bh(); t = rcu_dereference_bh(h->table); #ifdef IP_SET_HASH_WITH_NETS /* If we test an IP address and not a network address, @@ -1025,6 +1255,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext, goto out; } out: + rcu_read_unlock_bh(); return ret; } @@ -1036,23 +1267,14 @@ mtype_head(struct ip_set *set, struct sk_buff *skb) const struct htable *t; struct nlattr *nested; size_t memsize; + u32 elements = 0; + size_t ext_size = 0; u8 htable_bits; - /* If any members have expired, set->elements will be wrong - * mytype_expire function will update it with the right count. - * we do not hold set->lock here, so grab it first. - * set->elements can still be incorrect in the case of a huge set, - * because elements might time out during the listing. - */ - if (SET_WITH_TIMEOUT(set)) { - spin_lock_bh(&set->lock); - mtype_expire(set, h); - spin_unlock_bh(&set->lock); - } - rcu_read_lock_bh(); - t = rcu_dereference_bh_nfnl(h->table); - memsize = mtype_ahash_memsize(h, t) + set->ext_size; + t = rcu_dereference_bh(h->table); + mtype_ext_size(set, &elements, &ext_size); + memsize = mtype_ahash_memsize(h, t) + ext_size + set->ext_size; htable_bits = t->htable_bits; rcu_read_unlock_bh(); @@ -1063,18 +1285,35 @@ mtype_head(struct ip_set *set, struct sk_buff *skb) htonl(jhash_size(htable_bits))) || nla_put_net32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem))) goto nla_put_failure; +#ifdef IP_SET_HASH_WITH_BITMASK + /* if netmask is set to anything other than HOST_MASK we know that the user supplied netmask + * and not bitmask. These two are mutually exclusive. */ + if (h->netmask == HOST_MASK && !nf_inet_addr_cmp(&onesmask, &h->bitmask)) { + if (set->family == NFPROTO_IPV4) { + if (nla_put_ipaddr4(skb, IPSET_ATTR_BITMASK, h->bitmask.ip)) + goto nla_put_failure; + } else if (set->family == NFPROTO_IPV6) { + if (nla_put_ipaddr6(skb, IPSET_ATTR_BITMASK, &h->bitmask.in6)) + goto nla_put_failure; + } + } +#endif #ifdef IP_SET_HASH_WITH_NETMASK - if (h->netmask != HOST_MASK && - nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask)) + if (h->netmask != HOST_MASK && nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask)) goto nla_put_failure; #endif #ifdef IP_SET_HASH_WITH_MARKMASK if (nla_put_u32(skb, IPSET_ATTR_MARKMASK, h->markmask)) goto nla_put_failure; #endif + if (set->flags & IPSET_CREATE_FLAG_BUCKETSIZE) { + if (nla_put_u8(skb, IPSET_ATTR_BUCKETSIZE, h->bucketsize) || + nla_put_net32(skb, IPSET_ATTR_INITVAL, htonl(h->initval))) + goto nla_put_failure; + } if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) || nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) || - nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(set->elements))) + nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(elements))) goto nla_put_failure; if (unlikely(ip_set_put_flags(skb, set))) goto nla_put_failure; @@ -1094,15 +1333,15 @@ mtype_uref(struct ip_set *set, struct netlink_callback *cb, bool start) if (start) { rcu_read_lock_bh(); - t = rcu_dereference_bh_nfnl(h->table); + t = ipset_dereference_bh_nfnl(h->table); atomic_inc(&t->uref); cb->args[IPSET_CB_PRIVATE] = (unsigned long)t; rcu_read_unlock_bh(); } else if (cb->args[IPSET_CB_PRIVATE]) { t = (struct htable *)cb->args[IPSET_CB_PRIVATE]; if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) { - /* Resizing didn't destroy the hash table */ - pr_debug("Table destroy by dump: %p\n", t); + pr_debug("Table destroy after resize " + " by dump: %p\n", t); mtype_ahash_destroy(set, t, false); } cb->args[IPSET_CB_PRIVATE] = 0; @@ -1144,8 +1383,7 @@ mtype_list(const struct ip_set *set, if (!test_bit(i, n->used)) continue; e = ahash_data(n, i, set->dsize); - if (SET_WITH_TIMEOUT(set) && - ip_set_timeout_expired(ext_timeout(e, set))) + if (SET_ELEM_EXPIRED(set, e)) continue; pr_debug("list hash %lu hbucket %p i %u, data %p\n", cb->args[IPSET_CB_ARG0], n, i, e); @@ -1211,6 +1449,8 @@ 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, }; #ifdef IP_SET_EMIT_CREATE @@ -1223,12 +1463,15 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, u32 markmask; #endif u8 hbits; -#ifdef IP_SET_HASH_WITH_NETMASK - u8 netmask; +#if defined(IP_SET_HASH_WITH_NETMASK) || defined(IP_SET_HASH_WITH_BITMASK) + int ret __attribute__((unused)) = 0; + u8 netmask = set->family == NFPROTO_IPV4 ? 32 : 128; + union nf_inet_addr bitmask = onesmask; #endif size_t hsize; struct htype *h; struct htable *t; + u32 i; pr_debug("Create set %s with family %s\n", set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6"); @@ -1261,7 +1504,6 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, #endif #ifdef IP_SET_HASH_WITH_NETMASK - netmask = set->family == NFPROTO_IPV4 ? 32 : 128; if (tb[IPSET_ATTR_NETMASK]) { netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]); @@ -1269,6 +1511,33 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, (set->family == NFPROTO_IPV6 && netmask > 128) || netmask == 0) return -IPSET_ERR_INVALID_NETMASK; + + /* we convert netmask to bitmask and store it */ + if (set->family == NFPROTO_IPV4) + bitmask.ip = ip_set_netmask(netmask); + else + ip6_netmask(&bitmask, netmask); + } +#endif + +#ifdef IP_SET_HASH_WITH_BITMASK + if (tb[IPSET_ATTR_BITMASK]) { + /* bitmask and netmask do the same thing, allow only one of these options */ + if (tb[IPSET_ATTR_NETMASK]) + return -IPSET_ERR_BITMASK_NETMASK_EXCL; + + if (set->family == NFPROTO_IPV4) { + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_BITMASK], &bitmask.ip); + if (ret || !bitmask.ip) + return -IPSET_ERR_INVALID_NETMASK; + } else if (set->family == NFPROTO_IPV6) { + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_BITMASK], &bitmask); + if (ret || ipv6_addr_any(&bitmask.in6)) + return -IPSET_ERR_INVALID_NETMASK; + } + + if (nf_inet_addr_cmp(&bitmask, &zeromask)) + return -IPSET_ERR_INVALID_NETMASK; } #endif @@ -1286,7 +1555,11 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, if (!h) return -ENOMEM; - hbits = htable_bits(hashsize); + /* Compute htable_bits from the user input parameter hashsize. + * Assume that hashsize == 2^htable_bits, + * otherwise round up to the first 2^n value. + */ + hbits = fls(hashsize - 1); hsize = htable_size(hbits); if (hsize == 0) { kfree(h); @@ -1297,21 +1570,42 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, kfree(h); return -ENOMEM; } + t->hregion = ip_set_alloc(ahash_sizeof_regions(hbits)); + if (!t->hregion) { + ip_set_free(t); + kfree(h); + return -ENOMEM; + } + h->gc.set = set; + for (i = 0; i < ahash_numof_locks(hbits); i++) + spin_lock_init(&t->hregion[i].lock); h->maxelem = maxelem; -#ifdef IP_SET_HASH_WITH_NETMASK +#if defined(IP_SET_HASH_WITH_NETMASK) || defined(IP_SET_HASH_WITH_BITMASK) + h->bitmask = bitmask; h->netmask = netmask; #endif #ifdef IP_SET_HASH_WITH_MARKMASK h->markmask = markmask; #endif - get_random_bytes(&h->initval, sizeof(h->initval)); - + if (tb[IPSET_ATTR_INITVAL]) + h->initval = ntohl(nla_get_be32(tb[IPSET_ATTR_INITVAL])); + else + get_random_bytes(&h->initval, sizeof(h->initval)); + h->bucketsize = AHASH_MAX_SIZE; + if (tb[IPSET_ATTR_BUCKETSIZE]) { + h->bucketsize = nla_get_u8(tb[IPSET_ATTR_BUCKETSIZE]); + if (h->bucketsize < AHASH_INIT_SIZE) + h->bucketsize = AHASH_INIT_SIZE; + else if (h->bucketsize > AHASH_MAX_SIZE) + h->bucketsize = AHASH_MAX_SIZE; + else if (h->bucketsize % 2) + h->bucketsize += 1; + } t->htable_bits = hbits; + t->maxelem = h->maxelem / ahash_numof_locks(hbits); RCU_INIT_POINTER(h->table, t); -#ifdef HAVE_TIMER_SETUP - h->set = set; -#endif + INIT_LIST_HEAD(&h->ad); set->data = h; #ifndef IP_SET_PROTO_UNDEF if (set->family == NFPROTO_IPV4) { @@ -1334,12 +1628,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, #ifndef IP_SET_PROTO_UNDEF if (set->family == NFPROTO_IPV4) #endif - IPSET_TOKEN(HTYPE, 4_gc_init)(set, - IPSET_TOKEN(HTYPE, 4_gc)); + IPSET_TOKEN(HTYPE, 4_gc_init)(&h->gc); #ifndef IP_SET_PROTO_UNDEF else - IPSET_TOKEN(HTYPE, 6_gc_init)(set, - IPSET_TOKEN(HTYPE, 6_gc)); + IPSET_TOKEN(HTYPE, 6_gc_init)(&h->gc); #endif } pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ip.c b/kernel/net/netfilter/ipset/ip_set_hash_ip.c index 41c576f..5a2cb71 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_ip.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_ip.c @@ -24,7 +24,9 @@ /* 1 Counters support */ /* 2 Comments support */ /* 3 Forceadd support */ -#define IPSET_TYPE_REV_MAX 4 /* skbinfo support */ +/* 4 skbinfo support */ +/* 5 bucketsize, initval support */ +#define IPSET_TYPE_REV_MAX 6 /* bitmask support */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>"); @@ -34,6 +36,7 @@ MODULE_ALIAS("ip_set_hash:ip"); /* Type specific function prefix */ #define HTYPE hash_ip #define IP_SET_HASH_WITH_NETMASK +#define IP_SET_HASH_WITH_BITMASK /* IPv4 variant */ @@ -86,7 +89,7 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb, __be32 ip; ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip); - ip &= ip_set_netmask(h->netmask); + ip &= h->bitmask.ip; if (ip == 0) return -EINVAL; @@ -98,11 +101,11 @@ static int hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) { - const struct hash_ip4 *h = set->data; + struct hash_ip4 *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ip4_elem e = { 0 }; struct ip_set_ext ext = IP_SET_INIT_UEXT(set); - u32 ip = 0, ip_to = 0, hosts; + u32 ip = 0, ip_to = 0, hosts, i = 0; int ret = 0; if (tb[IPSET_ATTR_LINENO]) @@ -119,7 +122,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], if (ret) return ret; - ip &= ip_set_hostmask(h->netmask); + ip &= ntohl(h->bitmask.ip); e.ip = htonl(ip); if (e.ip == 0) return -IPSET_ERR_HASH_ELEM; @@ -132,8 +135,11 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; - if (ip > ip_to) + if (ip > ip_to) { + if (ip_to == 0) + return -IPSET_ERR_HASH_ELEM; swap(ip, ip_to); + } } else if (tb[IPSET_ATTR_CIDR]) { u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); @@ -144,18 +150,20 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); - if (retried) { + if (retried) ip = ntohl(h->next.ip); + for (; ip <= ip_to; i++) { e.ip = htonl(ip); - } - for (; ip <= ip_to;) { + if (i > IPSET_MAX_RANGE) { + hash_ip4_data_next(&h->next, &e); + return -ERANGE; + } ret = adtfn(set, &e, &ext, &ext, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; ip += hosts; - e.ip = htonl(ip); - if (e.ip == 0) + if (ip == 0) return 0; ret = 0; @@ -180,12 +188,6 @@ hash_ip6_data_equal(const struct hash_ip6_elem *ip1, return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6); } -static void -hash_ip6_netmask(union nf_inet_addr *ip, u8 prefix) -{ - ip6_netmask(ip, prefix); -} - static bool hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *e) { @@ -222,7 +224,7 @@ hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb, struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); - hash_ip6_netmask(&e.ip, h->netmask); + nf_inet_addr_mask_inplace(&e.ip, &h->bitmask); if (ipv6_addr_any(&e.ip.in6)) return -EINVAL; @@ -261,7 +263,7 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[], if (ret) return ret; - hash_ip6_netmask(&e.ip, h->netmask); + nf_inet_addr_mask_inplace(&e.ip, &h->bitmask); if (ipv6_addr_any(&e.ip.in6)) return -IPSET_ERR_HASH_ELEM; @@ -278,14 +280,17 @@ static struct ip_set_type hash_ip_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_ip_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, + [IPSET_ATTR_BITMASK] = { .type = NLA_NESTED }, [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, }, .adt_policy = { diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipmac.c b/kernel/net/netfilter/ipset/ip_set_hash_ipmac.c index eceb7bc..467c59a 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_ipmac.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_ipmac.c @@ -23,7 +23,7 @@ #include <linux/netfilter/ipset/ip_set_hash.h> #define IPSET_TYPE_REV_MIN 0 -#define IPSET_TYPE_REV_MAX 0 +#define IPSET_TYPE_REV_MAX 1 /* bucketsize, initval support */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tomasz Chilinski <tomasz.chilinski@chilan.com>"); @@ -268,11 +268,13 @@ static struct ip_set_type hash_ipmac_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_ipmac_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipmark.c b/kernel/net/netfilter/ipset/ip_set_hash_ipmark.c index 4ebd21b..ad2a2dc 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_ipmark.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_ipmark.c @@ -23,7 +23,8 @@ #define IPSET_TYPE_REV_MIN 0 /* 1 Forceadd support */ -#define IPSET_TYPE_REV_MAX 2 /* skbinfo support */ +/* 2 skbinfo support */ +#define IPSET_TYPE_REV_MAX 3 /* bucketsize, initval support */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Vytas Dauksa <vytas.dauksa@smoothwall.net>"); @@ -98,11 +99,11 @@ static int hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) { - const struct hash_ipmark4 *h = set->data; + struct hash_ipmark4 *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipmark4_elem e = { }; struct ip_set_ext ext = IP_SET_INIT_UEXT(set); - u32 ip, ip_to = 0; + u32 ip, ip_to = 0, i = 0; int ret; if (tb[IPSET_ATTR_LINENO]) @@ -122,6 +123,8 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[], e.mark = ntohl(nla_get_be32(tb[IPSET_ATTR_MARK])); e.mark &= h->markmask; + if (e.mark == 0 && e.ip == 0) + return -IPSET_ERR_HASH_ELEM; if (adt == IPSET_TEST || !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR])) { @@ -134,8 +137,11 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[], ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; - if (ip > ip_to) + if (ip > ip_to) { + if (e.mark == 0 && ip_to == 0) + return -IPSET_ERR_HASH_ELEM; swap(ip, ip_to); + } } else if (tb[IPSET_ATTR_CIDR]) { u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); @@ -146,8 +152,12 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[], if (retried) ip = ntohl(h->next.ip); - for (; ip <= ip_to; ip++) { + for (; ip <= ip_to; ip++, i++) { e.ip = htonl(ip); + if (i > IPSET_MAX_RANGE) { + hash_ipmark4_data_next(&h->next, &e); + return -ERANGE; + } ret = adtfn(set, &e, &ext, &ext, flags); if (ret && !ip_set_eexist(ret, flags)) @@ -276,12 +286,14 @@ static struct ip_set_type hash_ipmark_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_ipmark_create, .create_policy = { [IPSET_ATTR_MARKMASK] = { .type = NLA_U32 }, [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipport.c b/kernel/net/netfilter/ipset/ip_set_hash_ipport.c index 7e34bc4..46f8bbf 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_ipport.c @@ -26,7 +26,9 @@ /* 2 Counters support added */ /* 3 Comments support added */ /* 4 Forceadd support added */ -#define IPSET_TYPE_REV_MAX 5 /* skbinfo support added */ +/* 5 skbinfo support added */ +/* 6 bucketsize, initval support added */ +#define IPSET_TYPE_REV_MAX 7 /* bitmask support added */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>"); @@ -35,6 +37,8 @@ MODULE_ALIAS("ip_set_hash:ip,port"); /* Type specific function prefix */ #define HTYPE hash_ipport +#define IP_SET_HASH_WITH_NETMASK +#define IP_SET_HASH_WITH_BITMASK /* IPv4 variant */ @@ -92,12 +96,16 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb, ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport4_elem e = { .ip = 0 }; struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); + const struct MTYPE *h = set->data; if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, &e.port, &e.proto)) return -EINVAL; ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip); + e.ip &= h->bitmask.ip; + if (e.ip == 0) + return -EINVAL; return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); } @@ -105,11 +113,11 @@ static int hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) { - const struct hash_ipport4 *h = set->data; + struct hash_ipport4 *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport4_elem e = { .ip = 0 }; struct ip_set_ext ext = IP_SET_INIT_UEXT(set); - u32 ip, ip_to = 0, p = 0, port, port_to; + u32 ip, ip_to = 0, p = 0, port, port_to, i = 0; bool with_ports = false; int ret; @@ -129,6 +137,10 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], if (ret) return ret; + e.ip &= h->bitmask.ip; + if (e.ip == 0) + return -EINVAL; + e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); if (tb[IPSET_ATTR_PROTO]) { @@ -178,9 +190,13 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], for (; ip <= ip_to; ip++) { p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) : port; - for (; p <= port_to; p++) { + for (; p <= port_to; p++, i++) { e.ip = htonl(ip); e.port = htons(p); + if (i > IPSET_MAX_RANGE) { + hash_ipport4_data_next(&h->next, &e); + return -ERANGE; + } ret = adtfn(set, &e, &ext, &ext, flags); if (ret && !ip_set_eexist(ret, flags)) @@ -250,12 +266,17 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb, ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport6_elem e = { .ip = { .all = { 0 } } }; struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); + const struct MTYPE *h = set->data; if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, &e.port, &e.proto)) return -EINVAL; ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); + nf_inet_addr_mask_inplace(&e.ip, &h->bitmask); + if (ipv6_addr_any(&e.ip.in6)) + return -EINVAL; + return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); } @@ -295,6 +316,10 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], if (ret) return ret; + nf_inet_addr_mask_inplace(&e.ip, &h->bitmask); + if (ipv6_addr_any(&e.ip.in6)) + return -EINVAL; + e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); if (tb[IPSET_ATTR_PROTO]) { @@ -342,15 +367,19 @@ static struct ip_set_type hash_ipport_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_ipport_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, + [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, + [IPSET_ATTR_BITMASK] = { .type = NLA_NESTED }, }, .adt_policy = { [IPSET_ATTR_IP] = { .type = NLA_NESTED }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c b/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c index 81ce821..ca5fe9c 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c @@ -26,7 +26,8 @@ /* 2 Counters support added */ /* 3 Comments support added */ /* 4 Forceadd support added */ -#define IPSET_TYPE_REV_MAX 5 /* skbinfo support added */ +/* 5 skbinfo support added */ +#define IPSET_TYPE_REV_MAX 6 /* bucketsize, initval support added */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>"); @@ -108,11 +109,11 @@ static int hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) { - const struct hash_ipportip4 *h = set->data; + struct hash_ipportip4 *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportip4_elem e = { .ip = 0 }; struct ip_set_ext ext = IP_SET_INIT_UEXT(set); - u32 ip, ip_to = 0, p = 0, port, port_to; + u32 ip, ip_to = 0, p = 0, port, port_to, i = 0; bool with_ports = false; int ret; @@ -185,9 +186,13 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], for (; ip <= ip_to; ip++) { p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) : port; - for (; p <= port_to; p++) { + for (; p <= port_to; p++, i++) { e.ip = htonl(ip); e.port = htons(p); + if (i > IPSET_MAX_RANGE) { + hash_ipportip4_data_next(&h->next, &e); + return -ERANGE; + } ret = adtfn(set, &e, &ext, &ext, flags); if (ret && !ip_set_eexist(ret, flags)) @@ -357,11 +362,13 @@ static struct ip_set_type hash_ipportip_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_ipportip_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c b/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c index 4d4d443..8f44644 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c @@ -28,7 +28,8 @@ /* 4 Counters support added */ /* 5 Comments support added */ /* 6 Forceadd support added */ -#define IPSET_TYPE_REV_MAX 7 /* skbinfo support added */ +/* 7 skbinfo support added */ +#define IPSET_TYPE_REV_MAX 8 /* bucketsize, initval support added */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>"); @@ -160,12 +161,12 @@ static int hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) { - const struct hash_ipportnet4 *h = set->data; + struct hash_ipportnet4 *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 }; struct ip_set_ext ext = IP_SET_INIT_UEXT(set); u32 ip = 0, ip_to = 0, p = 0, port, port_to; - u32 ip2_from = 0, ip2_to = 0, ip2; + u32 ip2_from = 0, ip2_to = 0, ip2, i = 0; bool with_ports = false; u8 cidr; int ret; @@ -279,9 +280,15 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], for (; p <= port_to; p++) { e.port = htons(p); do { + i++; e.ip2 = htonl(ip2); ip2 = ip_set_range_to_cidr(ip2, ip2_to, &cidr); e.cidr = cidr - 1; + if (i > IPSET_MAX_RANGE) { + hash_ipportnet4_data_next(&h->next, + &e); + return -ERANGE; + } ret = adtfn(set, &e, &ext, &ext, flags); if (ret && !ip_set_eexist(ret, flags)) @@ -514,11 +521,13 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_ipportnet_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_mac.c b/kernel/net/netfilter/ipset/ip_set_hash_mac.c index 407c158..014bb71 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_mac.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_mac.c @@ -17,7 +17,7 @@ #include <linux/netfilter/ipset/ip_set_hash.h> #define IPSET_TYPE_REV_MIN 0 -#define IPSET_TYPE_REV_MAX 0 +#define IPSET_TYPE_REV_MAX 1 /* bucketsize, initval support */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>"); @@ -126,11 +126,13 @@ static struct ip_set_type hash_mac_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_mac_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_net.c b/kernel/net/netfilter/ipset/ip_set_hash_net.c index 923bffb..8baceea 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_net.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_net.c @@ -25,7 +25,8 @@ /* 3 Counters support added */ /* 4 Comments support added */ /* 5 Forceadd support added */ -#define IPSET_TYPE_REV_MAX 6 /* skbinfo mapping support added */ +/* 6 skbinfo support added */ +#define IPSET_TYPE_REV_MAX 7 /* bucketsize, initval support added */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>"); @@ -136,11 +137,11 @@ static int hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) { - const struct hash_net4 *h = set->data; + struct hash_net4 *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_net4_elem e = { .cidr = HOST_MASK }; struct ip_set_ext ext = IP_SET_INIT_UEXT(set); - u32 ip = 0, ip_to = 0; + u32 ip = 0, ip_to = 0, i = 0; int ret; if (tb[IPSET_ATTR_LINENO]) @@ -188,10 +189,16 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], if (ip + UINT_MAX == ip_to) return -IPSET_ERR_HASH_RANGE; } + if (retried) ip = ntohl(h->next.ip); do { + i++; e.ip = htonl(ip); + if (i > IPSET_MAX_RANGE) { + hash_net4_data_next(&h->next, &e); + return -ERANGE; + } ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr); ret = adtfn(set, &e, &ext, &ext, flags); if (ret && !ip_set_eexist(ret, flags)) @@ -355,11 +362,13 @@ static struct ip_set_type hash_net_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_net_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_netiface.c b/kernel/net/netfilter/ipset/ip_set_hash_netiface.c index 4202dd2..5baa852 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_netiface.c @@ -27,7 +27,8 @@ /* 4 Comments support added */ /* 5 Forceadd support added */ /* 6 skbinfo support added */ -#define IPSET_TYPE_REV_MAX 7 /* interface wildcard support added */ +/* 7 interface wildcard support added */ +#define IPSET_TYPE_REV_MAX 8 /* bucketsize, initval support added */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>"); @@ -40,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 */ @@ -182,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) @@ -202,7 +203,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 }; struct ip_set_ext ext = IP_SET_INIT_UEXT(set); - u32 ip = 0, ip_to = 0; + u32 ip = 0, ip_to = 0, i = 0; int ret; if (tb[IPSET_ATTR_LINENO]) @@ -226,7 +227,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], if (e.cidr > HOST_MASK) return -IPSET_ERR_INVALID_CIDR; } - nla_strlcpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ); + nla_strscpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ); if (tb[IPSET_ATTR_CADT_FLAGS]) { u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); @@ -260,7 +261,12 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], if (retried) ip = ntohl(h->next.ip); do { + i++; e.ip = htonl(ip); + if (i > IPSET_MAX_RANGE) { + hash_netiface4_data_next(&h->next, &e); + return -ERANGE; + } ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr); ret = adtfn(set, &e, &ext, &ext, flags); @@ -395,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) @@ -443,7 +449,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[], ip6_netmask(&e.ip, e.cidr); - nla_strlcpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ); + nla_strscpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ); if (tb[IPSET_ATTR_CADT_FLAGS]) { u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); @@ -471,11 +477,13 @@ static struct ip_set_type hash_netiface_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_netiface_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_netnet.c b/kernel/net/netfilter/ipset/ip_set_hash_netnet.c index da4ef91..8fbe649 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_netnet.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_netnet.c @@ -22,7 +22,9 @@ #define IPSET_TYPE_REV_MIN 0 /* 1 Forceadd support added */ -#define IPSET_TYPE_REV_MAX 2 /* skbinfo support added */ +/* 2 skbinfo support added */ +/* 3 bucketsize, initval support added */ +#define IPSET_TYPE_REV_MAX 4 /* bitmask support added */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>"); @@ -32,6 +34,8 @@ MODULE_ALIAS("ip_set_hash:net,net"); /* Type specific function prefix */ #define HTYPE hash_netnet #define IP_SET_HASH_WITH_NETS +#define IP_SET_HASH_WITH_NETMASK +#define IP_SET_HASH_WITH_BITMASK #define IPSET_NET_COUNT 2 /* IPv4 variants */ @@ -152,8 +156,8 @@ hash_netnet4_kadt(struct ip_set *set, const struct sk_buff *skb, ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0]); ip4addrptr(skb, opt->flags & IPSET_DIM_TWO_SRC, &e.ip[1]); - e.ip[0] &= ip_set_netmask(e.cidr[0]); - e.ip[1] &= ip_set_netmask(e.cidr[1]); + e.ip[0] &= (ip_set_netmask(e.cidr[0]) & h->bitmask.ip); + e.ip[1] &= (ip_set_netmask(e.cidr[1]) & h->bitmask.ip); return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); } @@ -162,12 +166,12 @@ static int hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) { - const struct hash_netnet4 *h = set->data; + struct hash_netnet4 *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netnet4_elem e = { }; struct ip_set_ext ext = IP_SET_INIT_UEXT(set); u32 ip = 0, ip_to = 0; - u32 ip2 = 0, ip2_from = 0, ip2_to = 0; + u32 ip2 = 0, ip2_from = 0, ip2_to = 0, i = 0; int ret; if (tb[IPSET_ATTR_LINENO]) @@ -211,8 +215,8 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], if (adt == IPSET_TEST || !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_IP2_TO])) { - e.ip[0] = htonl(ip & ip_set_hostmask(e.cidr[0])); - e.ip[1] = htonl(ip2_from & ip_set_hostmask(e.cidr[1])); + e.ip[0] = htonl(ip & ntohl(h->bitmask.ip) & ip_set_hostmask(e.cidr[0])); + e.ip[1] = htonl(ip2_from & ntohl(h->bitmask.ip) & ip_set_hostmask(e.cidr[1])); ret = adtfn(set, &e, &ext, &ext, flags); return ip_set_enomatch(ret, flags, adt, set) ? -ret : ip_set_eexist(ret, flags) ? 0 : ret; @@ -255,7 +259,12 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], e.ip[0] = htonl(ip); ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); do { + i++; e.ip[1] = htonl(ip2); + if (i > IPSET_MAX_RANGE) { + hash_netnet4_data_next(&h->next, &e); + return -ERANGE; + } ip2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]); ret = adtfn(set, &e, &ext, &ext, flags); if (ret && !ip_set_eexist(ret, flags)) @@ -389,6 +398,11 @@ hash_netnet6_kadt(struct ip_set *set, const struct sk_buff *skb, ip6_netmask(&e.ip[0], e.cidr[0]); ip6_netmask(&e.ip[1], e.cidr[1]); + nf_inet_addr_mask_inplace(&e.ip[0], &h->bitmask); + nf_inet_addr_mask_inplace(&e.ip[1], &h->bitmask); + if (e.cidr[0] == HOST_MASK && ipv6_addr_any(&e.ip[0].in6)) + return -EINVAL; + return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); } @@ -399,6 +413,7 @@ hash_netnet6_uadt(struct ip_set *set, struct nlattr *tb[], ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netnet6_elem e = { }; struct ip_set_ext ext = IP_SET_INIT_UEXT(set); + const struct hash_netnet6 *h = set->data; int ret; if (tb[IPSET_ATTR_LINENO]) @@ -438,6 +453,11 @@ hash_netnet6_uadt(struct ip_set *set, struct nlattr *tb[], ip6_netmask(&e.ip[0], e.cidr[0]); ip6_netmask(&e.ip[1], e.cidr[1]); + nf_inet_addr_mask_inplace(&e.ip[0], &h->bitmask); + nf_inet_addr_mask_inplace(&e.ip[1], &h->bitmask); + if (e.cidr[0] == HOST_MASK && ipv6_addr_any(&e.ip[0].in6)) + return -IPSET_ERR_HASH_ELEM; + if (tb[IPSET_ATTR_CADT_FLAGS]) { u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); @@ -459,14 +479,18 @@ static struct ip_set_type hash_netnet_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_netnet_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, + [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, + [IPSET_ATTR_BITMASK] = { .type = NLA_NESTED }, }, .adt_policy = { [IPSET_ATTR_IP] = { .type = NLA_NESTED }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_netport.c b/kernel/net/netfilter/ipset/ip_set_hash_netport.c index 48ad1c4..8a2a7c5 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_netport.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_netport.c @@ -27,7 +27,8 @@ /* 4 Counters support added */ /* 5 Comments support added */ /* 6 Forceadd support added */ -#define IPSET_TYPE_REV_MAX 7 /* skbinfo support added */ +/* 7 skbinfo support added */ +#define IPSET_TYPE_REV_MAX 8 /* bucketsize, initval support added */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>"); @@ -154,11 +155,11 @@ static int hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) { - const struct hash_netport4 *h = set->data; + struct hash_netport4 *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 }; struct ip_set_ext ext = IP_SET_INIT_UEXT(set); - u32 port, port_to, p = 0, ip = 0, ip_to = 0; + u32 port, port_to, p = 0, ip = 0, ip_to = 0, i = 0; bool with_ports = false; u8 cidr; int ret; @@ -246,8 +247,12 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], e.ip = htonl(ip); ip = ip_set_range_to_cidr(ip, ip_to, &cidr); e.cidr = cidr - 1; - for (; p <= port_to; p++) { + for (; p <= port_to; p++, i++) { e.port = htons(p); + if (i > IPSET_MAX_RANGE) { + hash_netport4_data_next(&h->next, &e); + return -ERANGE; + } ret = adtfn(set, &e, &ext, &ext, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -461,11 +466,13 @@ static struct ip_set_type hash_netport_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_netport_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c b/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c index 686cbbc..d5774a1 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c @@ -24,7 +24,8 @@ #define IPSET_TYPE_REV_MIN 0 /* 0 Comments support added */ /* 1 Forceadd support added */ -#define IPSET_TYPE_REV_MAX 2 /* skbinfo support added */ +/* 2 skbinfo support added */ +#define IPSET_TYPE_REV_MAX 3 /* bucketsize, initval support added */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>"); @@ -36,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 */ @@ -173,16 +175,26 @@ hash_netportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); } +static u32 +hash_netportnet4_range_to_cidr(u32 from, u32 to, u8 *cidr) +{ + if (from == 0 && to == UINT_MAX) { + *cidr = 0; + return to; + } + return ip_set_range_to_cidr(from, to, cidr); +} + static int hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) { - const struct hash_netportnet4 *h = set->data; + struct hash_netportnet4 *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netportnet4_elem e = { }; struct ip_set_ext ext = IP_SET_INIT_UEXT(set); u32 ip = 0, ip_to = 0, p = 0, port, port_to; - u32 ip2_from = 0, ip2_to = 0, ip2; + u32 ip2_from = 0, ip2_to = 0, ip2, i = 0; bool with_ports = false; int ret; @@ -296,13 +308,19 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], do { e.ip[0] = htonl(ip); - ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); + ip = hash_netportnet4_range_to_cidr(ip, ip_to, &e.cidr[0]); for (; p <= port_to; p++) { e.port = htons(p); do { + i++; e.ip[1] = htonl(ip2); - ip2 = ip_set_range_to_cidr(ip2, ip2_to, - &e.cidr[1]); + if (i > IPSET_MAX_RANGE) { + hash_netportnet4_data_next(&h->next, + &e); + return -ERANGE; + } + ip2 = hash_netportnet4_range_to_cidr(ip2, + ip2_to, &e.cidr[1]); ret = adtfn(set, &e, &ext, &ext, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -559,11 +577,13 @@ static struct ip_set_type hash_netportnet_type __read_mostly = { .family = NFPROTO_UNSPEC, .revision_min = IPSET_TYPE_REV_MIN, .revision_max = IPSET_TYPE_REV_MAX, + .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, .create = hash_netportnet_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, + [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_list_set.c b/kernel/net/netfilter/ipset/ip_set_list_set.c index fe862fb..cc2e5b9 100644 --- a/kernel/net/netfilter/ipset/ip_set_list_set.c +++ b/kernel/net/netfilter/ipset/ip_set_list_set.c @@ -62,7 +62,7 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb, /* Don't lookup sub-counters at all */ opt->cmdflags &= ~IPSET_FLAG_MATCH_COUNTERS; if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE) - opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE; + opt->cmdflags |= IPSET_FLAG_SKIP_COUNTER_UPDATE; list_for_each_entry_rcu(e, &map->members, list) { ret = ip_set_test(e->id, skb, par, opt); if (ret <= 0) @@ -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/kernel/net/netfilter/ipset/pfxlen.c b/kernel/net/netfilter/ipset/pfxlen.c index 59f6e72..1e264c7 100644 --- a/kernel/net/netfilter/ipset/pfxlen.c +++ b/kernel/net/netfilter/ipset/pfxlen.c @@ -1,6 +1,4 @@ #include <linux/version.h> -#define IP_SET_COMPAT_HEADERS -#include <linux/netfilter/ipset/ip_set_compat.h> #include <linux/netfilter/ipset/pfxlen.h> /* Prefixlen maps for fast conversions, by Jan Engelhardt. */ diff --git a/kernel/net/netfilter/xt_set.c b/kernel/net/netfilter/xt_set.c index c2735c4..95efb3a 100644 --- a/kernel/net/netfilter/xt_set.c +++ b/kernel/net/netfilter/xt_set.c @@ -39,7 +39,7 @@ MODULE_ALIAS("ip6t_SET"); #ifdef HAVE_XT_MTCHK_PARAM_STRUCT_NET #define XT_PAR_NET(par) ((par)->net) #else -#define XT_PAR_NET(par) NULL +#define XT_PAR_NET(par) (&(init_net)) #endif static inline int diff --git a/kernel/net/sched/em_ipset.c b/kernel/net/sched/em_ipset.c index 96fd4a3..5428f8d 100644 --- a/kernel/net/sched/em_ipset.c +++ b/kernel/net/sched/em_ipset.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * net/sched/em_ipset.c ipset ematch * * Copyright (c) 2012 Florian Westphal <fw@strlen.de> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. */ #include <linux/gfp.h> @@ -87,7 +84,7 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em, #else #define ACPAR_FAMILY(f) acpar.family = f #endif - switch (tc_skb_protocol(skb)) { + switch (skb_protocol(skb, true)) { case htons(ETH_P_IP): ACPAR_FAMILY(NFPROTO_IPV4); if (!pskb_network_may_pull(skb, sizeof(struct iphdr))) diff --git a/lib/Makefile.am b/lib/Makefile.am index 3a82417..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 = $(libdir)/pkgconfig pkgconfig_DATA = libipset.pc dist_man_MANS = libipset.3 @@ -284,6 +284,30 @@ static const struct ipset_arg ipset_args[] = { .print = ipset_print_number, .help = "[skbqueue VALUE]", }, + [IPSET_ARG_BUCKETSIZE] = { + .name = { "bucketsize", NULL }, + .has_arg = IPSET_MANDATORY_ARG, + .opt = IPSET_OPT_BUCKETSIZE, + .parse = ipset_parse_uint8, + .print = ipset_print_number, + .help = "[bucketsize VALUE]", + }, + [IPSET_ARG_INITVAL] = { + .name = { "initval", NULL }, + .has_arg = IPSET_MANDATORY_ARG, + .opt = IPSET_OPT_INITVAL, + .parse = ipset_parse_uint32, + .print = ipset_print_hexnumber, + .help = "[initval VALUE]", + }, + [IPSET_ARG_BITMASK] = { + .name = { "bitmask", NULL }, + .has_arg = IPSET_MANDATORY_ARG, + .opt = IPSET_OPT_BITMASK, + .parse = ipset_parse_bitmask, + .print = ipset_print_ip, + .help = "[bitmask bitmask]", + }, }; const struct ipset_arg * @@ -50,13 +50,14 @@ struct ipset_data { char setname2[IPSET_MAXNAMELEN]; /* CREATE/LIST/SAVE */ struct { - uint8_t probes; + uint8_t bucketsize; uint8_t resize; uint8_t netmask; + union nf_inet_addr bitmask; uint32_t hashsize; uint32_t maxelem; uint32_t markmask; - uint32_t gc; + uint32_t initval; uint32_t size; /* Filled out by kernel */ uint32_t references; @@ -110,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'; } @@ -286,8 +287,8 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value) data->index = *(const uint16_t *) value; break; /* Create-specific options */ - case IPSET_OPT_GC: - data->create.gc = *(const uint32_t *) value; + case IPSET_OPT_INITVAL: + data->create.initval = *(const uint32_t *) value; break; case IPSET_OPT_HASHSIZE: data->create.hashsize = *(const uint32_t *) value; @@ -301,8 +302,14 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value) case IPSET_OPT_NETMASK: data->create.netmask = *(const uint8_t *) value; break; - case IPSET_OPT_PROBES: - data->create.probes = *(const uint8_t *) value; + case IPSET_OPT_BITMASK: + if (!(data->family == NFPROTO_IPV4 || + data->family == NFPROTO_IPV6)) + return -1; + copy_addr(data->family, &data->create.bitmask, value); + break; + case IPSET_OPT_BUCKETSIZE: + data->create.bucketsize = *(const uint8_t *) value; break; case IPSET_OPT_RESIZE: data->create.resize = *(const uint8_t *) value; @@ -498,8 +505,8 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt) case IPSET_OPT_INDEX: return &data->index; /* Create-specific options */ - case IPSET_OPT_GC: - return &data->create.gc; + case IPSET_OPT_INITVAL: + return &data->create.initval; case IPSET_OPT_HASHSIZE: return &data->create.hashsize; case IPSET_OPT_MAXELEM: @@ -508,8 +515,10 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt) return &data->create.markmask; case IPSET_OPT_NETMASK: return &data->create.netmask; - case IPSET_OPT_PROBES: - return &data->create.probes; + case IPSET_OPT_BITMASK: + return &data->create.bitmask; + case IPSET_OPT_BUCKETSIZE: + return &data->create.bucketsize; case IPSET_OPT_RESIZE: return &data->create.resize; case IPSET_OPT_SIZE: @@ -594,6 +603,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family) case IPSET_OPT_IP_TO: case IPSET_OPT_IP2: case IPSET_OPT_IP2_TO: + case IPSET_OPT_BITMASK: return family == NFPROTO_IPV4 ? sizeof(uint32_t) : sizeof(struct in6_addr); case IPSET_OPT_MARK: @@ -608,7 +618,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family) case IPSET_OPT_NAMEREF: return IPSET_MAXNAMELEN; case IPSET_OPT_TIMEOUT: - case IPSET_OPT_GC: + case IPSET_OPT_INITVAL: case IPSET_OPT_HASHSIZE: case IPSET_OPT_MAXELEM: case IPSET_OPT_MARKMASK: @@ -625,7 +635,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family) case IPSET_OPT_CIDR: case IPSET_OPT_CIDR2: case IPSET_OPT_NETMASK: - case IPSET_OPT_PROBES: + case IPSET_OPT_BUCKETSIZE: case IPSET_OPT_RESIZE: case IPSET_OPT_PROTO: return sizeof(uint8_t); diff --git a/lib/debug.c b/lib/debug.c index 6b3ead2..dbc5cfb 100644 --- a/lib/debug.c +++ b/lib/debug.c @@ -35,12 +35,13 @@ static const struct ipset_attrname createattr2name[] = { [IPSET_ATTR_PROTO] = { .name = "PROTO" }, [IPSET_ATTR_CADT_FLAGS] = { .name = "CADT_FLAGS" }, [IPSET_ATTR_CADT_LINENO] = { .name = "CADT_LINENO" }, - [IPSET_ATTR_GC] = { .name = "GC" }, + [IPSET_ATTR_INITVAL] = { .name = "INITVAL" }, [IPSET_ATTR_HASHSIZE] = { .name = "HASHSIZE" }, [IPSET_ATTR_MAXELEM] = { .name = "MAXELEM" }, [IPSET_ATTR_MARKMASK] = { .name = "MARKMASK" }, [IPSET_ATTR_NETMASK] = { .name = "NETMASK" }, - [IPSET_ATTR_PROBES] = { .name = "PROBES" }, + [IPSET_ATTR_BITMASK] = { .name = "BITMASK" }, + [IPSET_ATTR_BUCKETSIZE] = { .name = "BUCKETSIZE" }, [IPSET_ATTR_RESIZE] = { .name = "RESIZE" }, [IPSET_ATTR_SIZE] = { .name = "SIZE" }, [IPSET_ATTR_ELEMENTS] = { .name = "ELEMENTS" }, diff --git a/lib/errcode.c b/lib/errcode.c index b38f95e..49c97a1 100644 --- a/lib/errcode.c +++ b/lib/errcode.c @@ -25,6 +25,8 @@ static const struct ipset_errcode_table core_errcode_table[] = { "The set with the given name does not exist" }, { EMSGSIZE, 0, "Kernel error received: message could not be created" }, + { ERANGE, 0, + "The specified range is too large, split it up into smaller ranges" }, { IPSET_ERR_PROTOCOL, 0, "Kernel error received: ipset protocol error" }, @@ -42,6 +44,8 @@ static const struct ipset_errcode_table core_errcode_table[] = { "The value of the markmask parameter is invalid" }, { IPSET_ERR_INVALID_FAMILY, 0, "Protocol family not supported by the set type" }, + { IPSET_ERR_BITMASK_NETMASK_EXCL, 0, + "netmask and bitmask options are mutually exclusive, provide only one" }, /* DESTROY specific error codes */ { IPSET_ERR_BUSY, IPSET_CMD_DESTROY, diff --git a/lib/ipset.c b/lib/ipset.c index 8633491..c910d88 100644 --- a/lib/ipset.c +++ b/lib/ipset.c @@ -13,6 +13,7 @@ #include <stdio.h> /* printf */ #include <stdlib.h> /* exit */ #include <string.h> /* str* */ +#include <inttypes.h> /* PRIu64 */ #include <config.h> @@ -27,6 +28,9 @@ #include <libipset/print.h> /* ipset_print_family */ #include <libipset/utils.h> /* STREQ */ #include <libipset/ipset.h> /* prototypes */ +#include <libipset/ip_set_compiler.h> /* compiler attributes */ +#include <libipset/list_sort.h> /* lists */ +#include <libipset/xlate.h> /* ipset_xlate_argv */ static char program_name[] = PACKAGE; static char program_version[] = PACKAGE_VERSION; @@ -49,6 +53,17 @@ struct ipset { char *newargv[MAX_ARGS]; int newargc; const char *filename; /* Input/output filename */ + bool xlate; + struct list_head xlate_sets; +}; + +struct ipset_xlate_set { + struct list_head list; + char name[IPSET_MAXNAMELEN]; + uint8_t netmask; + uint8_t family; + bool interval; + const struct ipset_type *type; }; /* Commands and environment options */ @@ -220,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\".", @@ -414,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); @@ -922,20 +939,21 @@ static const char *cmd_prefix[] = { [IPSET_TEST] = "test SETNAME", }; -/* Workhorses */ +static struct ipset_xlate_set * +ipset_xlate_set_get(struct ipset *ipset, const char *name) +{ + struct ipset_xlate_set *set; -/** - * ipset_parse_argv - parse and argv array and execute the command - * @ipset: ipset structure - * @argc: length of the array - * @argv: array of strings - * - * Parse an array of strings and execute the ipset command. - * - * Returns 0 on success or a negative error code. - */ -int -ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) + list_for_each_entry(set, &ipset->xlate_sets, list) { + if (!strcmp(set->name, name)) + return set; + } + + return NULL; +} + +static int +ipset_parser(struct ipset *ipset, int oargc, char *oargv[]) { int ret = 0; enum ipset_cmd cmd = IPSET_CMD_NONE; @@ -943,12 +961,17 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) char *arg0 = NULL, *arg1 = NULL; const struct ipset_envopts *opt; const struct ipset_commands *command; - const struct ipset_type *type; + const struct ipset_type *type = NULL; struct ipset_session *session = ipset->session; void *p = ipset_session_printf_private(session); int argc = oargc; char *argv[MAX_ARGS] = {}; + if (argc > MAX_ARGS) + return ipset->custom_error(ipset, + p, IPSET_PARAMETER_PROBLEM, + "Line is too long to parse."); + /* We need a local copy because of ipset_shift_argv */ memcpy(argv, oargv, sizeof(char *) * argc); @@ -1107,6 +1130,7 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) if (arg0) { const struct ipset_arg *arg; int k; + enum ipset_adt c; /* Type-specific help, without kernel checking */ type = type_find(arg0); @@ -1116,11 +1140,11 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) "Unknown settype: `%s'", arg0); printf("\n%s type specific options:\n\n", type->name); for (i = 0; cmd_help_order[i] != IPSET_CADT_MAX; i++) { - cmd = cmd_help_order[i]; + c = cmd_help_order[i]; printf("%s %s %s\n", - cmd_prefix[cmd], type->name, type->cmd[cmd].help); - for (k = 0; type->cmd[cmd].args[k] != IPSET_ARG_NONE; k++) { - arg = ipset_keyword(type->cmd[cmd].args[k]); + cmd_prefix[c], type->name, type->cmd[c].help); + for (k = 0; type->cmd[c].args[k] != IPSET_ARG_NONE; k++) { + arg = ipset_keyword(type->cmd[c].args[k]); if (!arg->help || arg->help[0] == '\0') continue; printf(" %s\n", arg->help); @@ -1208,6 +1232,7 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) return ret; } /* Fall through to parse optional setname */ + fallthrough; case IPSET_CMD_DESTROY: case IPSET_CMD_FLUSH: /* Args: [setname] */ @@ -1236,7 +1261,7 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) return ipset->custom_error(ipset, p, IPSET_PARAMETER_PROBLEM, "Unknown argument %s", argv[1]); - return restore(ipset); + return IPSET_CMD_RESTORE; case IPSET_CMD_ADD: case IPSET_CMD_DEL: case IPSET_CMD_TEST: @@ -1246,7 +1271,20 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) if (ret < 0) return ipset->standard_error(ipset, p); - type = ipset_type_get(session, cmd); + if (!ipset->xlate) { + type = ipset_type_get(session, cmd); + } else { + const struct ipset_xlate_set *xlate_set; + + xlate_set = ipset_xlate_set_get(ipset, arg0); + if (xlate_set) { + ipset_session_data_set(session, IPSET_OPT_TYPE, + xlate_set->type); + ipset_session_data_set(session, IPSET_OPT_FAMILY, + &xlate_set->family); + type = xlate_set->type; + } + } if (type == NULL) return ipset->standard_error(ipset, p); @@ -1273,6 +1311,37 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) if (argc > 1) return ipset->custom_error(ipset, p, IPSET_PARAMETER_PROBLEM, "Unknown argument %s", argv[1]); + + return cmd; +} + +/* Workhorses */ + +/** + * ipset_parse_argv - parse and argv array and execute the command + * @ipset: ipset structure + * @argc: length of the array + * @argv: array of strings + * + * Parse an array of strings and execute the ipset command. + * + * Returns 0 on success or a negative error code. + */ +int +ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) +{ + struct ipset_session *session = ipset->session; + void *p = ipset_session_printf_private(session); + enum ipset_cmd cmd; + int ret; + + cmd = ipset_parser(ipset, oargc, oargv); + if (cmd < 0) + return cmd; + + if (cmd == IPSET_CMD_RESTORE) + return restore(ipset); + ret = ipset_cmd(session, cmd, ipset->restore_line); D("ret %d", ret); /* In the case of warning, the return code is success */ @@ -1448,6 +1517,9 @@ ipset_init(void) return NULL; } ipset_custom_printf(ipset, NULL, NULL, NULL, NULL); + + INIT_LIST_HEAD(&ipset->xlate_sets); + return ipset; } @@ -1462,6 +1534,8 @@ ipset_init(void) int ipset_fini(struct ipset *ipset) { + struct ipset_xlate_set *xlate_set, *next; + assert(ipset); if (ipset->session) @@ -1470,6 +1544,498 @@ ipset_fini(struct ipset *ipset) if (ipset->newargv[0]) free(ipset->newargv[0]); + list_for_each_entry_safe(xlate_set, next, &ipset->xlate_sets, list) + free(xlate_set); + free(ipset); return 0; } + +/* Ignore the set family, use inet. */ +static const char *ipset_xlate_family(uint8_t family UNUSED) +{ + return "inet"; +} + +enum ipset_xlate_set_type { + IPSET_XLATE_TYPE_UNKNOWN = 0, + IPSET_XLATE_TYPE_HASH_MAC, + IPSET_XLATE_TYPE_HASH_IP, + IPSET_XLATE_TYPE_HASH_IP_MAC, + IPSET_XLATE_TYPE_HASH_NET_IFACE, + IPSET_XLATE_TYPE_HASH_NET_PORT, + IPSET_XLATE_TYPE_HASH_NET_PORT_NET, + IPSET_XLATE_TYPE_HASH_NET_NET, + IPSET_XLATE_TYPE_HASH_NET, + IPSET_XLATE_TYPE_HASH_IP_PORT_NET, + IPSET_XLATE_TYPE_HASH_IP_PORT_IP, + IPSET_XLATE_TYPE_HASH_IP_MARK, + IPSET_XLATE_TYPE_HASH_IP_PORT, + IPSET_XLATE_TYPE_BITMAP_PORT, + IPSET_XLATE_TYPE_BITMAP_IP_MAC, + IPSET_XLATE_TYPE_BITMAP_IP, +}; + +static enum ipset_xlate_set_type ipset_xlate_set_type(const char *typename) +{ + if (!strcmp(typename, "hash:mac")) + return IPSET_XLATE_TYPE_HASH_MAC; + else if (!strcmp(typename, "hash:ip")) + return IPSET_XLATE_TYPE_HASH_IP; + else if (!strcmp(typename, "hash:ip,mac")) + return IPSET_XLATE_TYPE_HASH_IP_MAC; + else if (!strcmp(typename, "hash:net,iface")) + return IPSET_XLATE_TYPE_HASH_NET_IFACE; + else if (!strcmp(typename, "hash:net,port")) + return IPSET_XLATE_TYPE_HASH_NET_PORT; + else if (!strcmp(typename, "hash:net,port,net")) + return IPSET_XLATE_TYPE_HASH_NET_PORT_NET; + else if (!strcmp(typename, "hash:net,net")) + return IPSET_XLATE_TYPE_HASH_NET_NET; + else if (!strcmp(typename, "hash:net")) + return IPSET_XLATE_TYPE_HASH_NET; + else if (!strcmp(typename, "hash:ip,port,net")) + return IPSET_XLATE_TYPE_HASH_IP_PORT_NET; + else if (!strcmp(typename, "hash:ip,port,ip")) + return IPSET_XLATE_TYPE_HASH_IP_PORT_IP; + else if (!strcmp(typename, "hash:ip,mark")) + return IPSET_XLATE_TYPE_HASH_IP_MARK; + else if (!strcmp(typename, "hash:ip,port")) + return IPSET_XLATE_TYPE_HASH_IP_PORT; + else if (!strcmp(typename, "hash:ip")) + return IPSET_XLATE_TYPE_HASH_IP; + else if (!strcmp(typename, "bitmap:port")) + return IPSET_XLATE_TYPE_BITMAP_PORT; + else if (!strcmp(typename, "bitmap:ip,mac")) + return IPSET_XLATE_TYPE_BITMAP_IP_MAC; + else if (!strcmp(typename, "bitmap:ip")) + return IPSET_XLATE_TYPE_BITMAP_IP; + + return IPSET_XLATE_TYPE_UNKNOWN; +} + +#define NFT_SET_INTERVAL (1 << 0) + +static const char * +ipset_xlate_type_to_nftables(int family, enum ipset_xlate_set_type type, + uint32_t *flags) +{ + switch (type) { + case IPSET_XLATE_TYPE_HASH_MAC: + return "ether_addr"; + case IPSET_XLATE_TYPE_HASH_IP: + if (family == AF_INET) + return "ipv4_addr"; + else if (family == AF_INET6) + return "ipv6_addr"; + break; + case IPSET_XLATE_TYPE_HASH_IP_MAC: + if (family == AF_INET) + return "ipv4_addr . ether_addr"; + else if (family == AF_INET6) + return "ipv6_addr . ether_addr"; + break; + case IPSET_XLATE_TYPE_HASH_NET_IFACE: + *flags |= NFT_SET_INTERVAL; + if (family == AF_INET) + return "ipv4_addr . ifname"; + else if (family == AF_INET6) + return "ipv6_addr . ifname"; + break; + case IPSET_XLATE_TYPE_HASH_NET_PORT: + *flags |= NFT_SET_INTERVAL; + if (family == AF_INET) + return "ipv4_addr . inet_proto . inet_service"; + else if (family == AF_INET6) + return "ipv6_addr . inet_proto . inet_service"; + break; + case IPSET_XLATE_TYPE_HASH_NET_PORT_NET: + *flags |= NFT_SET_INTERVAL; + if (family == AF_INET) + return "ipv4_addr . inet_proto . inet_service . ipv4_addr"; + else if (family == AF_INET6) + return "ipv6_addr . inet_proto . inet_service . ipv6_addr"; + break; + case IPSET_XLATE_TYPE_HASH_NET_NET: + *flags |= NFT_SET_INTERVAL; + if (family == AF_INET) + return "ipv4_addr . ipv4_addr"; + else if (family == AF_INET6) + return "ipv6_addr . ipv6_addr"; + break; + case IPSET_XLATE_TYPE_HASH_NET: + *flags |= NFT_SET_INTERVAL; + if (family == AF_INET) + return "ipv4_addr"; + else if (family == AF_INET6) + return "ipv6_addr"; + break; + case IPSET_XLATE_TYPE_HASH_IP_PORT_NET: + *flags |= NFT_SET_INTERVAL; + if (family == AF_INET) + return "ipv4_addr . inet_proto . inet_service . ipv4_addr"; + else if (family == AF_INET6) + return "ipv6_addr . inet_proto . inet_service . ipv6_addr"; + break; + case IPSET_XLATE_TYPE_HASH_IP_PORT_IP: + if (family == AF_INET) + return "ipv4_addr . inet_proto . inet_service . ipv4_addr"; + else if (family == AF_INET6) + return "ipv6_addr . inet_proto . inet_service . ipv6_addr"; + break; + case IPSET_XLATE_TYPE_HASH_IP_MARK: + if (family == AF_INET) + return "ipv4_addr . mark"; + else if (family == AF_INET6) + return "ipv6_addr . mark"; + break; + case IPSET_XLATE_TYPE_HASH_IP_PORT: + if (family == AF_INET) + return "ipv4_addr . inet_proto . inet_service"; + else if (family == AF_INET6) + return "ipv6_addr . inet_proto . inet_service"; + break; + case IPSET_XLATE_TYPE_BITMAP_PORT: + return "inet_service"; + case IPSET_XLATE_TYPE_BITMAP_IP_MAC: + if (family == AF_INET) + return "ipv4_addr . ether_addr"; + else if (family == AF_INET6) + return "ipv6_addr . ether_addr"; + break; + case IPSET_XLATE_TYPE_BITMAP_IP: + if (family == AF_INET) + return "ipv4_addr"; + else if (family == AF_INET6) + return "ipv6_addr"; + break; + case IPSET_XLATE_TYPE_UNKNOWN: + break; + default: + break; + } + /* This should not ever happen. */ + return "unknown"; +} + +static int ipset_xlate(struct ipset *ipset, enum ipset_cmd cmd, + const char *table) +{ + const char *set, *typename, *nft_type; + const struct ipset_type *ipset_type; + struct ipset_xlate_set *xlate_set; + enum ipset_xlate_set_type type; + struct ipset_session *session; + const uint32_t *cadt_flags; + const uint32_t *timeout; + const uint32_t *maxelem; + struct ipset_data *data; + const uint8_t *netmask; + const char *comment; + uint32_t flags = 0; + uint8_t family; + char buf[64]; + bool concat; + char *term; + + session = ipset_session(ipset); + data = ipset_session_data(session); + + set = ipset_data_get(data, IPSET_SETNAME); + family = ipset_data_family(data); + + switch (cmd) { + case IPSET_CMD_CREATE: + /* Not supported. */ + if (ipset_data_test(data, IPSET_OPT_MARKMASK)) { + printf("# %s", ipset->cmdline); + break; + } + cadt_flags = ipset_data_get(data, IPSET_OPT_CADT_FLAGS); + + /* Ignore: + * - IPSET_FLAG_WITH_COMMENT + * - IPSET_FLAG_WITH_FORCEADD + */ + if (cadt_flags && + (*cadt_flags & (IPSET_FLAG_BEFORE | + IPSET_FLAG_PHYSDEV | + IPSET_FLAG_NOMATCH | + IPSET_FLAG_WITH_SKBINFO | + IPSET_FLAG_IFACE_WILDCARD))) { + printf("# %s", ipset->cmdline); + break; + } + + typename = ipset_data_get(data, IPSET_OPT_TYPENAME); + type = ipset_xlate_set_type(typename); + nft_type = ipset_xlate_type_to_nftables(family, type, &flags); + + printf("add set %s %s %s { type %s; ", + ipset_xlate_family(family), table, set, nft_type); + if (cadt_flags) { + if (*cadt_flags & IPSET_FLAG_WITH_COUNTERS) + printf("counter; "); + } + timeout = ipset_data_get(data, IPSET_OPT_TIMEOUT); + if (timeout) + printf("timeout %us; ", *timeout); + maxelem = ipset_data_get(data, IPSET_OPT_MAXELEM); + if (maxelem) + printf("size %u; ", *maxelem); + + netmask = ipset_data_get(data, IPSET_OPT_NETMASK); + if (netmask && + ((family == AF_INET && *netmask < 32) || + (family == AF_INET6 && *netmask < 128))) + flags |= NFT_SET_INTERVAL; + + if (flags & NFT_SET_INTERVAL) + printf("flags interval; "); + + /* These create-specific options are safe to be ignored: + * - IPSET_OPT_GC + * - IPSET_OPT_HASHSIZE + * - IPSET_OPT_PROBES + * - IPSET_OPT_RESIZE + * - IPSET_OPT_SIZE + * - IPSET_OPT_FORCEADD + * + * Ranges and CIDR are safe to be ignored too: + * - IPSET_OPT_IP_FROM + * - IPSET_OPT_IP_TO + * - IPSET_OPT_PORT_FROM + * - IPSET_OPT_PORT_TO + */ + + printf("}\n"); + + xlate_set = calloc(1, sizeof(*xlate_set)); + if (!xlate_set) + return -1; + + snprintf(xlate_set->name, sizeof(xlate_set->name), "%s", set); + ipset_type = ipset_types(); + while (ipset_type) { + if (!strcmp(ipset_type->name, typename)) + break; + ipset_type = ipset_type->next; + } + + xlate_set->family = family; + xlate_set->type = ipset_type; + if (netmask) { + xlate_set->netmask = *netmask; + xlate_set->interval = true; + } + list_add_tail(&xlate_set->list, &ipset->xlate_sets); + break; + case IPSET_CMD_DESTROY: + printf("del set %s %s %s\n", + ipset_xlate_family(family), table, set); + break; + case IPSET_CMD_FLUSH: + if (!set) { + printf("# %s", ipset->cmdline); + } else { + printf("flush set %s %s %s\n", + ipset_xlate_family(family), table, set); + } + break; + case IPSET_CMD_RENAME: + printf("# %s", ipset->cmdline); + return -1; + case IPSET_CMD_SWAP: + printf("# %s", ipset->cmdline); + return -1; + case IPSET_CMD_LIST: + if (!set) { + printf("list sets %s %s\n", + ipset_xlate_family(family), table); + } else { + printf("list set %s %s %s\n", + ipset_xlate_family(family), table, set); + } + break; + case IPSET_CMD_SAVE: + printf("# %s", ipset->cmdline); + return -1; + case IPSET_CMD_ADD: + case IPSET_CMD_DEL: + case IPSET_CMD_TEST: + /* Not supported. */ + if (ipset_data_test(data, IPSET_OPT_NOMATCH) || + ipset_data_test(data, IPSET_OPT_SKBINFO) || + ipset_data_test(data, IPSET_OPT_SKBMARK) || + ipset_data_test(data, IPSET_OPT_SKBPRIO) || + ipset_data_test(data, IPSET_OPT_SKBQUEUE) || + ipset_data_test(data, IPSET_OPT_IFACE_WILDCARD)) { + printf("# %s", ipset->cmdline); + break; + } + printf("%s element %s %s %s { ", + cmd == IPSET_CMD_ADD ? "add" : + cmd == IPSET_CMD_DEL ? "delete" : "get", + ipset_xlate_family(family), table, set); + + xlate_set = (struct ipset_xlate_set *) + ipset_xlate_set_get(ipset, set); + if (xlate_set && xlate_set->interval) + netmask = &xlate_set->netmask; + else + netmask = NULL; + + concat = false; + if (ipset_data_test(data, IPSET_OPT_IP)) { + ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_IP, 0); + printf("%s", buf); + if (netmask) + printf("/%u ", *netmask); + else + printf(" "); + + concat = true; + } + if (ipset_data_test(data, IPSET_OPT_MARK)) { + ipset_print_mark(buf, sizeof(buf), data, IPSET_OPT_MARK, 0); + printf("%s%s ", concat ? ". " : "", buf); + } + if (ipset_data_test(data, IPSET_OPT_IFACE)) { + ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_IFACE, 0); + printf("%s%s ", concat ? ". " : "", buf); + } + if (ipset_data_test(data, IPSET_OPT_ETHER)) { + ipset_print_ether(buf, sizeof(buf), data, IPSET_OPT_ETHER, 0); + size_t i; + + for (i = 0; i < strlen(buf); i++) + buf[i] = tolower(buf[i]); + + printf("%s%s ", concat ? ". " : "", buf); + concat = true; + } + if (ipset_data_test(data, IPSET_OPT_PORT)) { + ipset_print_proto_port(buf, sizeof(buf), data, IPSET_OPT_PORT, 0); + term = strchr(buf, ':'); + if (term) { + *term = '\0'; + printf("%s%s ", concat ? ". " : "", buf); + } + ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_PORT, 0); + printf("%s%s ", concat ? ". " : "", buf); + } + if (ipset_data_test(data, IPSET_OPT_IP2)) { + ipset_print_ip(buf, sizeof(buf), data, IPSET_OPT_IP2, 0); + printf("%s%s", concat ? ". " : "", buf); + if (netmask) + printf("/%u ", *netmask); + else + printf(" "); + } + if (ipset_data_test(data, IPSET_OPT_PACKETS) && + ipset_data_test(data, IPSET_OPT_BYTES)) { + const uint64_t *pkts, *bytes; + + pkts = ipset_data_get(data, IPSET_OPT_PACKETS); + bytes = ipset_data_get(data, IPSET_OPT_BYTES); + + printf("counter packets %" PRIu64 " bytes %" PRIu64 " ", + *pkts, *bytes); + } + timeout = ipset_data_get(data, IPSET_OPT_TIMEOUT); + if (timeout) + printf("timeout %us ", *timeout); + + comment = ipset_data_get(data, IPSET_OPT_ADT_COMMENT); + if (comment) + printf("comment \"%s\" ", comment); + + printf("}\n"); + break; + case IPSET_CMD_GET_BYNAME: + printf("# %s", ipset->cmdline); + return -1; + case IPSET_CMD_GET_BYINDEX: + printf("# %s", ipset->cmdline); + return -1; + default: + break; + } + + return 0; +} + +static int ipset_xlate_restore(struct ipset *ipset) +{ + struct ipset_session *session = ipset_session(ipset); + struct ipset_data *data = ipset_session_data(session); + void *p = ipset_session_printf_private(session); + enum ipset_cmd cmd; + FILE *f = stdin; + int ret = 0; + char *c; + + if (ipset->filename) { + f = fopen(ipset->filename, "r"); + if (!f) { + fprintf(stderr, "cannot open file `%s'\n", ipset->filename); + return -1; + } + } + + /* TODO: Allow to specify the table name other than 'global'. */ + printf("add table inet global\n"); + + while (fgets(ipset->cmdline, sizeof(ipset->cmdline), f)) { + ipset->restore_line++; + c = ipset->cmdline; + while (isspace(c[0])) + c++; + if (c[0] == '\0' || c[0] == '#') + continue; + else if (STREQ(c, "COMMIT\n") || STREQ(c, "COMMIT\r\n")) + continue; + + ret = build_argv(ipset, c); + if (ret < 0) + break; + + cmd = ipset_parser(ipset, ipset->newargc, ipset->newargv); + if (cmd < 0) + ipset->standard_error(ipset, p); + + /* TODO: Allow to specify the table name other than 'global'. */ + ret = ipset_xlate(ipset, cmd, "global"); + if (ret < 0) + break; + + ipset_data_reset(data); + } + + if (ipset->filename) + fclose(f); + + return ret; +} + +int ipset_xlate_argv(struct ipset *ipset, int argc, char *argv[]) +{ + enum ipset_cmd cmd; + int ret; + + ipset->xlate = true; + + cmd = ipset_parser(ipset, argc, argv); + if (cmd < 0) + return cmd; + + if (cmd == IPSET_CMD_RESTORE) { + ret = ipset_xlate_restore(ipset); + } else { + fprintf(stderr, "This command is not supported, " + "use `ipset-translate restore < file'\n"); + ret = -1; + } + + return ret; +} diff --git a/lib/ipset_hash_ip.c b/lib/ipset_hash_ip.c index 2ef1af3..4f96ebb 100644 --- a/lib/ipset_hash_ip.c +++ b/lib/ipset_hash_ip.c @@ -393,6 +393,175 @@ static struct ipset_type ipset_hash_ip4 = { .description = "skbinfo support", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_ip5 = { + .name = "hash:ip", + .alias = { "iphash", NULL }, + .revision = 5, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_ONE, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_single6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_NETMASK, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + /* Ignored options: backward compatibilty */ + IPSET_ARG_PROBES, + IPSET_ARG_RESIZE, + IPSET_ARG_GC, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO), + .help = "IP", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO), + .help = "IP", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO), + .help = "IP", + }, + }, + .usage = "where depending on the INET family\n" + " IP is a valid IPv4 or IPv6 address (or hostname),\n" + " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" + " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" + " is supported for IPv4.", + .description = "bucketsize, initval support", +}; + +/* bitmask support */ +static struct ipset_type ipset_hash_ip6 = { + .name = "hash:ip", + .alias = { "iphash", NULL }, + .revision = 6, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_ONE, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_single6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_NETMASK, + IPSET_ARG_BITMASK, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + /* Ignored options: backward compatibilty */ + IPSET_ARG_PROBES, + IPSET_ARG_RESIZE, + IPSET_ARG_GC, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO), + .help = "IP", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO), + .help = "IP", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO), + .help = "IP", + }, + }, + .usage = "where depending on the INET family\n" + " IP is a valid IPv4 or IPv6 address (or hostname),\n" + " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" + " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" + " is supported for IPv4.", + .description = "bitmask support", +}; + void _init(void); void _init(void) { @@ -401,4 +570,6 @@ void _init(void) ipset_type_add(&ipset_hash_ip2); ipset_type_add(&ipset_hash_ip3); ipset_type_add(&ipset_hash_ip4); + ipset_type_add(&ipset_hash_ip5); + ipset_type_add(&ipset_hash_ip6); } diff --git a/lib/ipset_hash_ipmac.c b/lib/ipset_hash_ipmac.c index c64e1be..c15897b 100644 --- a/lib/ipset_hash_ipmac.c +++ b/lib/ipset_hash_ipmac.c @@ -91,8 +91,93 @@ static struct ipset_type ipset_hash_ipmac0 = { .description = "Initial revision", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_ipmac1 = { + .name = "hash:ip,mac", + .alias = { "ipmachash", NULL }, + .revision = 1, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_TWO, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_single6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_ether, + .print = ipset_print_ether, + .opt = IPSET_OPT_ETHER + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_ETHER), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_ETHER), + .help = "IP,MAC", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_ETHER), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_ETHER), + .help = "IP,MAC", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_ETHER), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_ETHER), + .help = "IP,MAC", + }, + }, + .usage = "where depending on the INET family\n" + " IP is a valid IPv4 or IPv6 address (or hostname),\n" + " MAC is a MAC address.", + .description = "bucketsize, initval support", +}; + void _init(void); void _init(void) { ipset_type_add(&ipset_hash_ipmac0); + ipset_type_add(&ipset_hash_ipmac1); } diff --git a/lib/ipset_hash_ipmark.c b/lib/ipset_hash_ipmark.c index 42b1979..7d6d977 100644 --- a/lib/ipset_hash_ipmark.c +++ b/lib/ipset_hash_ipmark.c @@ -289,10 +289,109 @@ static struct ipset_type ipset_hash_ipmark2 = { .description = "skbinfo support", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_ipmark3 = { + .name = "hash:ip,mark", + .alias = { "ipmarkhash", NULL }, + .revision = 3, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_TWO, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_single6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_mark, + .print = ipset_print_mark, + .opt = IPSET_OPT_MARK + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_MARKMASK, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + /* Ignored options: backward compatibilty */ + IPSET_ARG_PROBES, + IPSET_ARG_RESIZE, + IPSET_ARG_IGNORED_FROM, + IPSET_ARG_IGNORED_TO, + IPSET_ARG_IGNORED_NETWORK, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_MARK), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_MARK), + .help = "IP,MARK", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_MARK), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_MARK), + .help = "IP,MARK", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_MARK), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_MARK), + .help = "IP,MARK", + }, + }, + .usage = "where depending on the INET family\n" + " IP is a valid IPv4 or IPv6 address (or hostname).\n" + " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" + " is supported for IPv4.\n" + " Adding/deleting single mark element\n" + " is supported both for IPv4 and IPv6.", + .description = "bucketsize, initval support", +}; + void _init(void); void _init(void) { ipset_type_add(&ipset_hash_ipmark0); ipset_type_add(&ipset_hash_ipmark1); ipset_type_add(&ipset_hash_ipmark2); + ipset_type_add(&ipset_hash_ipmark3); } diff --git a/lib/ipset_hash_ipport.c b/lib/ipset_hash_ipport.c index b48cac2..2fa8abd 100644 --- a/lib/ipset_hash_ipport.c +++ b/lib/ipset_hash_ipport.c @@ -499,6 +499,218 @@ static struct ipset_type ipset_hash_ipport5 = { .description = "skbinfo support", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_ipport6 = { + .name = "hash:ip,port", + .alias = { "ipporthash", NULL }, + .revision = 6, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_TWO, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_single6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_proto_port, + .print = ipset_print_proto_port, + .opt = IPSET_OPT_PORT + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + /* Ignored options: backward compatibilty */ + IPSET_ARG_PROBES, + IPSET_ARG_RESIZE, + IPSET_ARG_IGNORED_FROM, + IPSET_ARG_IGNORED_TO, + IPSET_ARG_IGNORED_NETWORK, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO), + .help = "IP,[PROTO:]PORT", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO), + .help = "IP,[PROTO:]PORT", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT), + .help = "IP,[PROTO:]PORT", + }, + }, + .usage = "where depending on the INET family\n" + " IP is a valid IPv4 or IPv6 address (or hostname).\n" + " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" + " is supported for IPv4.\n" + " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" + " port range is supported both for IPv4 and IPv6.", + .usagefn = ipset_port_usage, + .description = "bucketsize, initval support", +}; + +/* bitmask support */ +static struct ipset_type ipset_hash_ipport7 = { + .name = "hash:ip,port", + .alias = { "ipporthash", NULL }, + .revision = 7, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_TWO, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_single6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_proto_port, + .print = ipset_print_proto_port, + .opt = IPSET_OPT_PORT + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + IPSET_ARG_NETMASK, + IPSET_ARG_BITMASK, + /* Ignored options: backward compatibilty */ + IPSET_ARG_PROBES, + IPSET_ARG_RESIZE, + IPSET_ARG_IGNORED_FROM, + IPSET_ARG_IGNORED_TO, + IPSET_ARG_IGNORED_NETWORK, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO), + .help = "IP,[PROTO:]PORT", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO), + .help = "IP,[PROTO:]PORT", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT), + .help = "IP,[PROTO:]PORT", + }, + }, + .usage = "where depending on the INET family\n" + " IP is a valid IPv4 or IPv6 address (or hostname).\n" + " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" + " is supported for IPv4.\n" + " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" + " port range is supported both for IPv4 and IPv6.", + .usagefn = ipset_port_usage, + .description = "netmask and bitmask support", +}; + void _init(void); void _init(void) { @@ -507,4 +719,6 @@ void _init(void) ipset_type_add(&ipset_hash_ipport3); ipset_type_add(&ipset_hash_ipport4); ipset_type_add(&ipset_hash_ipport5); + ipset_type_add(&ipset_hash_ipport6); + ipset_type_add(&ipset_hash_ipport7); } diff --git a/lib/ipset_hash_ipportip.c b/lib/ipset_hash_ipportip.c index 545e50c..6b2e92e 100644 --- a/lib/ipset_hash_ipportip.c +++ b/lib/ipset_hash_ipportip.c @@ -554,6 +554,122 @@ static struct ipset_type ipset_hash_ipportip5 = { .description = "skbinfo support", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_ipportip6 = { + .name = "hash:ip,port,ip", + .alias = { "ipportiphash", NULL }, + .revision = 6, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_THREE, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_single6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_proto_port, + .print = ipset_print_proto_port, + .opt = IPSET_OPT_PORT + }, + [IPSET_DIM_THREE - 1] = { + .parse = ipset_parse_single_ip, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP2 + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + /* Ignored options: backward compatibilty */ + IPSET_ARG_PROBES, + IPSET_ARG_RESIZE, + IPSET_ARG_IGNORED_FROM, + IPSET_ARG_IGNORED_TO, + IPSET_ARG_IGNORED_NETWORK, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO) + | IPSET_FLAG(IPSET_OPT_IP2), + .help = "IP,[PROTO:]PORT,IP", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO) + | IPSET_FLAG(IPSET_OPT_IP2), + .help = "IP,[PROTO:]PORT,IP", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_IP2), + .help = "IP,[PROTO:]PORT,IP", + }, + }, + .usage = "where depending on the INET family\n" + " IP is a valid IPv4 or IPv6 address (or hostname).\n" + " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" + " in the first IP component is supported for IPv4.\n" + " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" + " port range is supported both for IPv4 and IPv6.", + .usagefn = ipset_port_usage, + .description = "bucketsize, initval support", +}; + void _init(void); void _init(void) { @@ -562,4 +678,5 @@ void _init(void) ipset_type_add(&ipset_hash_ipportip3); ipset_type_add(&ipset_hash_ipportip4); ipset_type_add(&ipset_hash_ipportip5); + ipset_type_add(&ipset_hash_ipportip6); } diff --git a/lib/ipset_hash_ipportnet.c b/lib/ipset_hash_ipportnet.c index 94a680e..2552cdb 100644 --- a/lib/ipset_hash_ipportnet.c +++ b/lib/ipset_hash_ipportnet.c @@ -812,6 +812,130 @@ static struct ipset_type ipset_hash_ipportnet7 = { .description = "skbinfo support", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_ipportnet8 = { + .name = "hash:ip,port,net", + .alias = { "ipportnethash", NULL }, + .revision = 8, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_THREE, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_single6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_proto_port, + .print = ipset_print_proto_port, + .opt = IPSET_OPT_PORT + }, + [IPSET_DIM_THREE - 1] = { + .parse = ipset_parse_ip4_net6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP2 + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + /* Ignored options: backward compatibilty */ + IPSET_ARG_PROBES, + IPSET_ARG_RESIZE, + IPSET_ARG_IGNORED_FROM, + IPSET_ARG_IGNORED_TO, + IPSET_ARG_IGNORED_NETWORK, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_NOMATCH, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2) + | IPSET_FLAG(IPSET_OPT_IP2_TO), + .help = "IP,[PROTO:]PORT,IP[/CIDR]", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2) + | IPSET_FLAG(IPSET_OPT_IP2_TO), + .help = "IP,[PROTO:]PORT,IP[/CIDR]", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NOMATCH, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2), + .help = "IP,[PROTO:]PORT,IP[/CIDR]", + }, + }, + .usage = "where depending on the INET family\n" + " IP are valid IPv4 or IPv6 addresses (or hostnames),\n" + " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" + " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" + " in the first IP component is supported for IPv4.\n" + " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" + " port range is supported both for IPv4 and IPv6.", + .usagefn = ipset_port_usage, + .description = "bucketsize, initval support", +}; + void _init(void); void _init(void) { @@ -822,4 +946,5 @@ void _init(void) ipset_type_add(&ipset_hash_ipportnet5); ipset_type_add(&ipset_hash_ipportnet6); ipset_type_add(&ipset_hash_ipportnet7); + ipset_type_add(&ipset_hash_ipportnet8); } diff --git a/lib/ipset_hash_mac.c b/lib/ipset_hash_mac.c index 426c384..4b20247 100644 --- a/lib/ipset_hash_mac.c +++ b/lib/ipset_hash_mac.c @@ -75,8 +75,77 @@ static struct ipset_type ipset_hash_mac0 = { .description = "Initial revision", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_mac1 = { + .name = "hash:mac", + .alias = { "machash", NULL }, + .revision = 1, + .family = NFPROTO_UNSPEC, + .dimension = IPSET_DIM_ONE, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ether, + .print = ipset_print_ether, + .opt = IPSET_OPT_ETHER + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_ETHER), + .full = IPSET_FLAG(IPSET_OPT_ETHER), + .help = "MAC", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_ETHER), + .full = IPSET_FLAG(IPSET_OPT_ETHER), + .help = "MAC", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_ETHER), + .full = IPSET_FLAG(IPSET_OPT_ETHER), + .help = "MAC", + }, + }, + .usage = "", + .description = "bucketsize, initval support", +}; + void _init(void); void _init(void) { ipset_type_add(&ipset_hash_mac0); + ipset_type_add(&ipset_hash_mac1); } diff --git a/lib/ipset_hash_net.c b/lib/ipset_hash_net.c index ef9e19c..1da95bf 100644 --- a/lib/ipset_hash_net.c +++ b/lib/ipset_hash_net.c @@ -531,6 +531,90 @@ static struct ipset_type ipset_hash_net6 = { .description = "skbinfo support", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_net7 = { + .name = "hash:net", + .alias = { "nethash", NULL }, + .revision = 7, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_ONE, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_net6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + /* Ignored options: backward compatibilty */ + IPSET_ARG_PROBES, + IPSET_ARG_RESIZE, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_NOMATCH, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO), + .help = "IP[/CIDR]", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO), + .help = "IP[/CIDR]", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NOMATCH, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR), + .help = "IP[/CIDR]", + }, + }, + .usage = "where depending on the INET family\n" + " IP is an IPv4 or IPv6 address (or hostname),\n" + " CIDR is a valid IPv4 or IPv6 CIDR prefix.", + .description = "bucketsize, initval support", +}; + void _init(void); void _init(void) { @@ -541,4 +625,5 @@ void _init(void) ipset_type_add(&ipset_hash_net4); ipset_type_add(&ipset_hash_net5); ipset_type_add(&ipset_hash_net6); + ipset_type_add(&ipset_hash_net7); } diff --git a/lib/ipset_hash_netiface.c b/lib/ipset_hash_netiface.c index 6755782..172c2a9 100644 --- a/lib/ipset_hash_netiface.c +++ b/lib/ipset_hash_netiface.c @@ -619,6 +619,7 @@ static struct ipset_type ipset_hash_netiface6 = { " Adding/deleting multiple elements with IPv4 is supported.", .description = "skbinfo support", }; + /* interface wildcard support */ static struct ipset_type ipset_hash_netiface7 = { .name = "hash:net,iface", @@ -714,6 +715,103 @@ static struct ipset_type ipset_hash_netiface7 = { .description = "skbinfo and wildcard support", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_netiface8 = { + .name = "hash:net,iface", + .alias = { "netifacehash", NULL }, + .revision = 8, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_TWO, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_net6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_iface, + .print = ipset_print_iface, + .opt = IPSET_OPT_IFACE + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_NOMATCH, + IPSET_ARG_IFACE_WILDCARD, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IFACE), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_IFACE) + | IPSET_FLAG(IPSET_OPT_PHYSDEV), + .help = "IP[/CIDR]|FROM-TO,[physdev:]IFACE", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IFACE), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_IFACE) + | IPSET_FLAG(IPSET_OPT_PHYSDEV), + .help = "IP[/CIDR]|FROM-TO,[physdev:]IFACE", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NOMATCH, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IFACE), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IFACE) + | IPSET_FLAG(IPSET_OPT_PHYSDEV), + .help = "IP[/CIDR],[physdev:]IFACE", + }, + }, + .usage = "where depending on the INET family\n" + " IP is a valid IPv4 or IPv6 address (or hostname),\n" + " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" + " Adding/deleting multiple elements with IPv4 is supported.", + .description = "bucketsize, initval support", +}; + void _init(void); void _init(void) { @@ -725,4 +823,5 @@ void _init(void) ipset_type_add(&ipset_hash_netiface5); ipset_type_add(&ipset_hash_netiface6); ipset_type_add(&ipset_hash_netiface7); + ipset_type_add(&ipset_hash_netiface8); } diff --git a/lib/ipset_hash_netnet.c b/lib/ipset_hash_netnet.c index 9918b47..0e176e3 100644 --- a/lib/ipset_hash_netnet.c +++ b/lib/ipset_hash_netnet.c @@ -289,10 +289,210 @@ static struct ipset_type ipset_hash_netnet2 = { .description = "skbinfo support", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_netnet3 = { + .name = "hash:net,net", + .alias = { "netnethash", NULL }, + .revision = 3, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_TWO, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_net6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_ip4_net6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP2 + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_NOMATCH, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2) + | IPSET_FLAG(IPSET_OPT_IP2_TO), + .help = "IP[/CIDR]|FROM-TO,IP[/CIDR]|FROM-TO", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2) + | IPSET_FLAG(IPSET_OPT_IP2_TO), + .help = "IP[/CIDR]|FROM-TO,IP[/CIDR]|FROM-TO", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NOMATCH, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2), + .help = "IP[/CIDR],IP[/CIDR]", + }, + }, + .usage = "where depending on the INET family\n" + " IP is an IPv4 or IPv6 address (or hostname),\n" + " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" + " IP range is not supported with IPv6.", + .description = "bucketsize, initval support", +}; + +/* bitmask support */ +static struct ipset_type ipset_hash_netnet4 = { + .name = "hash:net,net", + .alias = { "netnethash", NULL }, + .revision = 4, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_TWO, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_net6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_ip4_net6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP2 + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + IPSET_ARG_BITMASK, + IPSET_ARG_NETMASK, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_NOMATCH, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2) + | IPSET_FLAG(IPSET_OPT_IP2_TO), + .help = "IP[/CIDR]|FROM-TO,IP[/CIDR]|FROM-TO", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2) + | IPSET_FLAG(IPSET_OPT_IP2_TO), + .help = "IP[/CIDR]|FROM-TO,IP[/CIDR]|FROM-TO", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NOMATCH, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2), + .help = "IP[/CIDR],IP[/CIDR]", + }, + }, + .usage = "where depending on the INET family\n" + " IP is an IPv4 or IPv6 address (or hostname),\n" + " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" + " IP range is not supported with IPv6.", + .description = "netmask and bitmask support", +}; + void _init(void); void _init(void) { ipset_type_add(&ipset_hash_netnet0); ipset_type_add(&ipset_hash_netnet1); ipset_type_add(&ipset_hash_netnet2); + ipset_type_add(&ipset_hash_netnet3); + ipset_type_add(&ipset_hash_netnet4); } diff --git a/lib/ipset_hash_netport.c b/lib/ipset_hash_netport.c index 48501ce..f09de83 100644 --- a/lib/ipset_hash_netport.c +++ b/lib/ipset_hash_netport.c @@ -665,6 +665,109 @@ static struct ipset_type ipset_hash_netport7 = { .description = "skbinfo support", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_netport8 = { + .name = "hash:net,port", + .alias = { "netporthash", NULL }, + .revision = 8, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_TWO, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_net6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_proto_port, + .print = ipset_print_proto_port, + .opt = IPSET_OPT_PORT + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_NOMATCH, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO), + .help = "IP[/CIDR]|FROM-TO,[PROTO:]PORT", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO), + .help = "IP[/CIDR]|FROM-TO,[PROTO:]PORT", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NOMATCH, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_CIDR), + .help = "IP[/CIDR],[PROTO:]PORT", + }, + }, + .usage = "where depending on the INET family\n" + " IP is a valid IPv4 or IPv6 address (or hostname),\n" + " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" + " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" + " port range is supported both for IPv4 and IPv6.", + .usagefn = ipset_port_usage, + .description = "bucketsize, initval support", +}; + void _init(void); void _init(void) { @@ -675,4 +778,5 @@ void _init(void) ipset_type_add(&ipset_hash_netport5); ipset_type_add(&ipset_hash_netport6); ipset_type_add(&ipset_hash_netport7); + ipset_type_add(&ipset_hash_netport8); } diff --git a/lib/ipset_hash_netportnet.c b/lib/ipset_hash_netportnet.c index 0b36bd5..a4a7240 100644 --- a/lib/ipset_hash_netportnet.c +++ b/lib/ipset_hash_netportnet.c @@ -358,10 +358,132 @@ static struct ipset_type ipset_hash_netportnet2 = { .description = "skbinfo support", }; +/* bucketsize support */ +static struct ipset_type ipset_hash_netportnet3 = { + .name = "hash:net,port,net", + .alias = { "netportnethash", NULL }, + .revision = 3, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_THREE, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_net6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_proto_port, + .print = ipset_print_proto_port, + .opt = IPSET_OPT_PORT + }, + [IPSET_DIM_THREE - 1] = { + .parse = ipset_parse_ip4_net6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP2 + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_NOMATCH, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2) + | IPSET_FLAG(IPSET_OPT_IP2_TO), + .help = "IP[/CIDR],[PROTO:]PORT,IP[/CIDR]", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_PORT_TO) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2) + | IPSET_FLAG(IPSET_OPT_IP2_TO), + .help = "IP[/CIDR],[PROTO:]PORT,IP[/CIDR]", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NOMATCH, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_IP2), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_PROTO) + | IPSET_FLAG(IPSET_OPT_PORT) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP2) + | IPSET_FLAG(IPSET_OPT_CIDR2), + .help = "IP[/CIDR],[PROTO:]PORT,IP[/CIDR]", + }, + }, + .usage = "where depending on the INET family\n" + " IP are valid IPv4 or IPv6 addresses (or hostnames),\n" + " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" + " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" + " in both IP components are supported for IPv4.\n" + " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" + " port range is supported both for IPv4 and IPv6.", + .usagefn = ipset_port_usage, + .description = "bucketsize, initval support", +}; + void _init(void); void _init(void) { ipset_type_add(&ipset_hash_netportnet0); ipset_type_add(&ipset_hash_netportnet1); ipset_type_add(&ipset_hash_netportnet2); + ipset_type_add(&ipset_hash_netportnet3); } diff --git a/lib/libipset.map b/lib/libipset.map index 7a4a33c..c69b738 100644 --- a/lib/libipset.map +++ b/lib/libipset.map @@ -202,3 +202,18 @@ global: ipset_session_report_msg; ipset_session_report_type; } LIBIPSET_4.8; + +LIBIPSET_4.10 { +global: + ipset_print_hexnumber; +} LIBIPSET_4.9; + +LIBIPSET_4.11 { +global: + ipset_xlate_argv; +} LIBIPSET_4.10; + +LIBIPSET_4.12 { +global: + ipset_parse_bitmask; +} LIBIPSET_4.10; @@ -34,7 +34,7 @@ struct ipset_handle { static const uint16_t cmdflags[] = { [IPSET_CMD_CREATE-1] = NLM_F_REQUEST|NLM_F_ACK| NLM_F_CREATE|NLM_F_EXCL, - [IPSET_CMD_DESTROY-1] = NLM_F_REQUEST|NLM_F_ACK, + [IPSET_CMD_DESTROY-1] = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL, [IPSET_CMD_FLUSH-1] = NLM_F_REQUEST|NLM_F_ACK, [IPSET_CMD_RENAME-1] = NLM_F_REQUEST|NLM_F_ACK, [IPSET_CMD_SWAP-1] = NLM_F_REQUEST|NLM_F_ACK, diff --git a/lib/parse.c b/lib/parse.c index 31a619d..4d2d8b3 100644 --- a/lib/parse.c +++ b/lib/parse.c @@ -41,6 +41,9 @@ #define syntax_err(fmt, args...) \ ipset_err(session, "Syntax error: " fmt , ## args) +#define syntax_err_ll(errtype, fmt, args...) \ + ipset_session_report(session, errtype, "Syntax error: " fmt , ## args) + static char * ipset_strchr(const char *str, const char *sep) { @@ -87,7 +90,8 @@ string_to_number_ll(struct ipset_session *session, const char *str, unsigned long long min, unsigned long long max, - unsigned long long *ret) + unsigned long long *ret, + enum ipset_err_type errtype) { unsigned long long number = 0; char *end; @@ -104,23 +108,24 @@ string_to_number_ll(struct ipset_session *session, errno = ERANGE; } if (errno == ERANGE && max) - return syntax_err("'%s' is out of range %llu-%llu", - str, min, max); + return syntax_err_ll(errtype, "'%s' is out of range %llu-%llu", + str, min, max); else if (errno == ERANGE) - return syntax_err("'%s' is out of range %llu-%llu", - str, min, ULLONG_MAX); + return syntax_err_ll(errtype, "'%s' is out of range %llu-%llu", + str, min, ULLONG_MAX); else - return syntax_err("'%s' is invalid as number", str); + return syntax_err_ll(errtype, "'%s' is invalid as number", str); } static int string_to_u8(struct ipset_session *session, - const char *str, uint8_t *ret) + const char *str, uint8_t *ret, + enum ipset_err_type errtype) { int err; unsigned long long num = 0; - err = string_to_number_ll(session, str, 0, 255, &num); + err = string_to_number_ll(session, str, 0, 255, &num, errtype); *ret = num; return err; @@ -130,7 +135,7 @@ static int string_to_cidr(struct ipset_session *session, const char *str, uint8_t min, uint8_t max, uint8_t *ret) { - int err = string_to_u8(session, str, ret); + int err = string_to_u8(session, str, ret, IPSET_ERROR); if (!err && (*ret < min || *ret > max)) return syntax_err("'%s' is out of range %u-%u", @@ -141,12 +146,13 @@ string_to_cidr(struct ipset_session *session, static int string_to_u16(struct ipset_session *session, - const char *str, uint16_t *ret) + const char *str, uint16_t *ret, + enum ipset_err_type errtype) { int err; unsigned long long num = 0; - err = string_to_number_ll(session, str, 0, USHRT_MAX, &num); + err = string_to_number_ll(session, str, 0, USHRT_MAX, &num, errtype); *ret = num; return err; @@ -159,7 +165,8 @@ string_to_u32(struct ipset_session *session, int err; unsigned long long num = 0; - err = string_to_number_ll(session, str, 0, UINT_MAX, &num); + err = string_to_number_ll(session, str, 0, UINT_MAX, &num, + IPSET_ERROR); *ret = num; return err; @@ -274,7 +281,10 @@ parse_portname(struct ipset_session *session, const char *str, uint16_t *port, const char *proto) { char *saved, *tmp; + const char *protoname; + const struct protoent *protoent; struct servent *service; + uint8_t protonum = 0; saved = tmp = ipset_strdup(session, str); if (tmp == NULL) @@ -283,7 +293,15 @@ parse_portname(struct ipset_session *session, const char *str, if (tmp == NULL) goto error; - service = getservbyname(tmp, proto); + protoname = proto; + if (string_to_u8(session, proto, &protonum, IPSET_WARNING) == 0) { + protoent = getprotobynumber(protonum); + if (protoent == NULL) + goto error; + protoname = protoent->p_name; + } + + service = getservbyname(tmp, protoname); if (service != NULL) { *port = ntohs((uint16_t) service->s_port); free(saved); @@ -319,11 +337,11 @@ ipset_parse_port(struct ipset_session *session, assert(opt == IPSET_OPT_PORT || opt == IPSET_OPT_PORT_TO); assert(str); - if (parse_portname(session, str, &port, proto) == 0) { + if (string_to_u16(session, str, &port, IPSET_WARNING) == 0) { return ipset_session_data_set(session, opt, &port); } /* Error is stored as warning in session report */ - if (string_to_u16(session, str, &port) == 0) { + if (parse_portname(session, str, &port, proto) == 0) { /* No error, so reset false error messages */ ipset_session_report_reset(session); return ipset_session_data_set(session, opt, &port); @@ -469,21 +487,23 @@ ipset_parse_proto(struct ipset_session *session, { const struct protoent *protoent; uint8_t proto = 0; + uint8_t protonum = 0; assert(session); assert(opt == IPSET_OPT_PROTO); assert(str); + if (string_to_u8(session, str, &protonum, IPSET_WARNING) == 0) + return ipset_session_data_set(session, opt, &protonum); + + /* No error, so reset false error messages */ + ipset_session_report_reset(session); protoent = getprotobyname(strcasecmp(str, "icmpv6") == 0 ? "ipv6-icmp" : str); - if (protoent == NULL) { - uint8_t protonum = 0; - if (string_to_u8(session, str, &protonum) || - (protoent = getprotobynumber(protonum)) == NULL) - return syntax_err("cannot parse '%s' " - "as a protocol", str); - } + if (protoent == NULL) + return syntax_err("cannot parse '%s' " + "as a protocol", str); proto = protoent->p_proto; if (!proto) return syntax_err("Unsupported protocol '%s'", str); @@ -513,8 +533,8 @@ parse_icmp_typecode(struct ipset_session *session, str, family); } *a++ = '\0'; - if ((err = string_to_u8(session, tmp, &type)) != 0 || - (err = string_to_u8(session, a, &code)) != 0) + if ((err = string_to_u8(session, tmp, &type, IPSET_ERROR)) != 0 || + (err = string_to_u8(session, a, &code, IPSET_ERROR)) != 0) goto error; typecode = (type << 8) | code; @@ -1335,7 +1355,8 @@ ipset_parse_timeout(struct ipset_session *session, assert(opt == IPSET_OPT_TIMEOUT); assert(str); - err = string_to_number_ll(session, str, 0, (UINT_MAX>>1)/1000, &llnum); + err = string_to_number_ll(session, str, 0, (UINT_MAX>>1)/1000, &llnum, + IPSET_ERROR); if (err == 0) { /* Timeout is expected to be 32bits wide, so we have to convert it here */ @@ -1579,7 +1600,8 @@ ipset_parse_uint64(struct ipset_session *session, assert(session); assert(str); - err = string_to_number_ll(session, str, 0, ULLONG_MAX - 1, &value); + err = string_to_number_ll(session, str, 0, ULLONG_MAX - 1, &value, + IPSET_ERROR); if (err) return err; @@ -1623,7 +1645,7 @@ ipset_parse_uint16(struct ipset_session *session, assert(session); assert(str); - err = string_to_u16(session, str, &value); + err = string_to_u16(session, str, &value, IPSET_ERROR); if (err == 0) return ipset_session_data_set(session, opt, &value); @@ -1651,7 +1673,7 @@ ipset_parse_uint8(struct ipset_session *session, assert(session); assert(str); - if ((err = string_to_u8(session, str, &value)) == 0) + if ((err = string_to_u8(session, str, &value, IPSET_ERROR)) == 0) return ipset_session_data_set(session, opt, &value); return err; @@ -1682,6 +1704,9 @@ ipset_parse_netmask(struct ipset_session *session, assert(str); data = ipset_session_data(session); + if (ipset_data_test(data, IPSET_OPT_BITMASK)) + return syntax_err("bitmask and netmask are mutually exclusive, provide only one"); + family = ipset_data_family(data); if (family == NFPROTO_UNSPEC) { family = NFPROTO_IPV4; @@ -1701,6 +1726,46 @@ ipset_parse_netmask(struct ipset_session *session, } /** + * ipset_parse_bitmask - parse string as a bitmask + * @session: session structure + * @opt: option kind of the data + * @str: string to parse + * + * Parse string as a bitmask value, depending on family type. + * If family is not set yet, INET is assumed. + * The value is stored in the data blob of the session. + * + * Returns 0 on success or a negative error code. + */ +int +ipset_parse_bitmask(struct ipset_session *session, + enum ipset_opt opt, const char *str) +{ + uint8_t family; + struct ipset_data *data; + + assert(session); + assert(opt == IPSET_OPT_BITMASK); + assert(str); + + data = ipset_session_data(session); + if (ipset_data_test(data, IPSET_OPT_NETMASK)) + return syntax_err("bitmask and netmask are mutually exclusive, provide only one"); + + family = ipset_data_family(data); + if (family == NFPROTO_UNSPEC) { + family = NFPROTO_IPV4; + ipset_data_set(data, IPSET_OPT_FAMILY, &family); + } + + if (parse_ipaddr(session, opt, str, family)) + return syntax_err("bitmask is not valid for family = %s", + family == NFPROTO_IPV4 ? "inet" : "inet6"); + + return 0; +} + +/** * ipset_parse_flag - "parse" option flags * @session: session structure * @opt: option kind of the data diff --git a/lib/print.c b/lib/print.c index bafe58f..6ea79cb 100644 --- a/lib/print.c +++ b/lib/print.c @@ -265,7 +265,7 @@ ipset_print_ip(char *buf, unsigned int len, assert(buf); assert(len > 0); assert(data); - assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2); + assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2 || opt == IPSET_OPT_BITMASK); D("len: %u", len); family = ipset_data_family(data); @@ -397,6 +397,51 @@ ipset_print_number(char *buf, unsigned int len, } /** + * ipset_print_hexnumber - print number in hex to string + * @buf: printing buffer + * @len: length of available buffer space + * @data: data blob + * @opt: the option kind + * @env: environment flags + * + * Print number in hex to output buffer. + * + * Return lenght of printed string or error size. + */ +int +ipset_print_hexnumber(char *buf, unsigned int len, + const struct ipset_data *data, enum ipset_opt opt, + uint8_t env) +{ + size_t maxsize; + const void *number; + const char *quoted = env & IPSET_ENV_QUOTED ? "\"" : ""; + + assert(buf); + assert(len > 0); + assert(data); + + number = ipset_data_get(data, opt); + maxsize = ipset_data_sizeof(opt, AF_INET); + D("opt: %u, maxsize %zu", opt, maxsize); + if (maxsize == sizeof(uint8_t)) + return snprintf(buf, len, "%s0x%02"PRIx8"%s", + quoted, *(const uint8_t *) number, quoted); + else if (maxsize == sizeof(uint16_t)) + return snprintf(buf, len, "%s0x%04"PRIx16"%s", + quoted, *(const uint16_t *) number, quoted); + else if (maxsize == sizeof(uint32_t)) + return snprintf(buf, len, "%s0x%08"PRIx32"%s", + quoted, *(const uint32_t *) number, quoted); + else if (maxsize == sizeof(uint64_t)) + return snprintf(buf, len, "%s0x%016"PRIx64"%s", + quoted, *(const uint64_t *) number, quoted); + else + assert(0); + return 0; +} + +/** * ipset_print_name - print setname element string * @buf: printing buffer * @len: length of available buffer space @@ -932,6 +977,7 @@ ipset_print_data(char *buf, unsigned int len, size = ipset_print_elem(buf, len, data, opt, env); break; case IPSET_OPT_IP: + case IPSET_OPT_BITMASK: size = ipset_print_ip(buf, len, data, opt, env); break; case IPSET_OPT_PORT: @@ -940,12 +986,12 @@ ipset_print_data(char *buf, unsigned int len, case IPSET_OPT_IFACE: size = ipset_print_iface(buf, len, data, opt, env); break; - case IPSET_OPT_GC: + case IPSET_OPT_INITVAL: case IPSET_OPT_HASHSIZE: case IPSET_OPT_MAXELEM: case IPSET_OPT_MARKMASK: case IPSET_OPT_NETMASK: - case IPSET_OPT_PROBES: + case IPSET_OPT_BUCKETSIZE: case IPSET_OPT_RESIZE: case IPSET_OPT_TIMEOUT: case IPSET_OPT_REFERENCES: diff --git a/lib/session.c b/lib/session.c index 9e3eae3..f822288 100644 --- a/lib/session.c +++ b/lib/session.c @@ -418,9 +418,9 @@ static const struct ipset_attr_policy create_attrs[] = { .type = MNL_TYPE_U32, .opt = IPSET_OPT_CADT_FLAGS, }, - [IPSET_ATTR_GC] = { + [IPSET_ATTR_INITVAL] = { .type = MNL_TYPE_U32, - .opt = IPSET_OPT_GC, + .opt = IPSET_OPT_INITVAL, }, [IPSET_ATTR_HASHSIZE] = { .type = MNL_TYPE_U32, @@ -438,9 +438,9 @@ static const struct ipset_attr_policy create_attrs[] = { .type = MNL_TYPE_U8, .opt = IPSET_OPT_NETMASK, }, - [IPSET_ATTR_PROBES] = { + [IPSET_ATTR_BUCKETSIZE] = { .type = MNL_TYPE_U8, - .opt = IPSET_OPT_PROBES, + .opt = IPSET_OPT_BUCKETSIZE, }, [IPSET_ATTR_RESIZE] = { .type = MNL_TYPE_U8, @@ -462,6 +462,10 @@ static const struct ipset_attr_policy create_attrs[] = { .type = MNL_TYPE_U32, .opt = IPSET_OPT_MEMSIZE, }, + [IPSET_ATTR_BITMASK] = { + .type = MNL_TYPE_NESTED, + .opt = IPSET_OPT_BITMASK, + }, }; static const struct ipset_attr_policy adt_attrs[] = { @@ -856,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 */ @@ -890,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; @@ -898,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]); @@ -925,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; } @@ -932,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"); @@ -968,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]) { @@ -1003,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; } @@ -1038,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; } @@ -1075,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; } @@ -1210,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; } @@ -1223,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'; @@ -1241,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; @@ -1721,6 +1811,10 @@ rawdata2attr(struct ipset_session *session, struct nlmsghdr *nlh, if (attr->type == MNL_TYPE_NESTED) { /* IP addresses */ struct nlattr *nested; + + if (type == IPSET_ATTR_BITMASK) + family = ipset_data_family(session->data); + int atype = family == NFPROTO_IPV4 ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6; @@ -1982,7 +2076,7 @@ build_msg(struct ipset_session *session, bool aggregate) break; case IPSET_CMD_ADD: case IPSET_CMD_DEL: { - const struct ipset_type *type; + DD(const struct ipset_type *type); if (!aggregate) { /* Setname, type not checked/added yet */ @@ -2007,7 +2101,7 @@ build_msg(struct ipset_session *session, bool aggregate) open_nested(session, nlh, IPSET_ATTR_ADT); } } - type = ipset_data_get(data, IPSET_OPT_TYPE); + DD(type = ipset_data_get(data, IPSET_OPT_TYPE)); D("family: %u, type family %u", ipset_data_family(data), type->family); if (open_nested(session, nlh, IPSET_ATTR_DATA)) { @@ -2027,7 +2121,7 @@ build_msg(struct ipset_session *session, bool aggregate) break; } case IPSET_CMD_TEST: { - const struct ipset_type *type; + DD(const struct ipset_type *type); /* Return codes are not aggregated, so tests cannot be either */ /* Setname, type not checked/added yet */ @@ -2040,7 +2134,7 @@ build_msg(struct ipset_session *session, bool aggregate) return ipset_err(session, "Invalid test command: missing settype"); - type = ipset_data_get(data, IPSET_OPT_TYPE); + DD(type = ipset_data_get(data, IPSET_OPT_TYPE)); D("family: %u, type family %u", ipset_data_family(data), type->family); ADDATTR_SETNAME(session, nlh, data); @@ -2187,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 (session->mode == IPSET_LIST_NONE) - session->mode = IPSET_LIST_PLAIN; - } else if (cmd == IPSET_CMD_SAVE) { + if (cmd == IPSET_CMD_LIST || cmd == IPSET_CMD_SAVE) { + /* Set default output mode */ 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/Makefile.am b/src/Makefile.am index 438fcec..95dea07 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,10 +12,16 @@ AM_LDFLAGS = -static endif endif -dist_man_MANS = ipset.8 +dist_man_MANS = ipset.8 ipset-translate.8 sparse-check: $(ipset_SOURCES:.c=.d) %.d: %.c $(IPSET_AM_V_CHECK)\ $(SPARSE) -I.. $(SPARSE_FLAGS) $(AM_CFLAGS) $(AM_CPPFLAGS) $< || : + +install-exec-hook: + ${LN_S} -f "${sbindir}/ipset" "${DESTDIR}${sbindir}/ipset-translate"; + +uninstall-hook: + rm -f ${DESTDIR}${sbindir}/ipset-translate diff --git a/src/ipset-translate.8 b/src/ipset-translate.8 new file mode 100644 index 0000000..55ce2a9 --- /dev/null +++ b/src/ipset-translate.8 @@ -0,0 +1,91 @@ +.\" +.\" (C) Copyright 2021, Pablo Neira Ayuso <pablo@netfilter.org> +.\" +.\" %%%LICENSE_START(GPLv2+_DOC_FULL) +.\" This is free documentation; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License as +.\" published by the Free Software Foundation; either version 2 of +.\" the License, or (at your option) any later version. +.\" +.\" The GNU General Public License's references to "object code" +.\" and "executables" are to be interpreted as the output of any +.\" document formatting or typesetting system, including +.\" intermediate and printed output. +.\" +.\" This manual is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public +.\" License along with this manual; if not, see +.\" <http://www.gnu.org/licenses/>. +.\" %%%LICENSE_END +.\" +.TH IPSET-TRANSLATE 8 "May 31, 2021" + +.SH NAME +ipset-translate \(em translation tool to migrate from ipset to nftables +.SH DESCRIPTION +This tool allows system administrators to translate a given IP sets file +to \fBnftables(8)\fP. + +The only available command is: + +.IP \[bu] 2 +ipset-translate restore < file.ipt + +.SH USAGE +The \fBipset-translate\fP tool reads an IP sets file in the syntax produced by +\fBipset(8)\fP save. No set modifications occur, this tool is a text converter. + +.SH EXAMPLES +Basic operation examples. + +Single command translation, assuming the original file: + +.nf +create test1 hash:ip,port family inet counters timeout 300 hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5c4be5d +add test1 1.1.1.1,udp:20 +add test1 1.1.1.1,21 +create test2 hash:ip,port family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5c4be5d +.fi + +which results in the following translation: + +.nf +root@machine:~# ipset-translate restore < file.ipt +add set inet global test1 { type ipv4_addr . inet_proto . inet_service; counter; timeout 300s; size 65536; } +add element inet global test1 { 1.1.1.1 . udp . 20 } +add element inet global test1 { 1.1.1.1 . tcp . 21 } +add set inet global test2 { type ipv4_addr . inet_proto . inet_service; size 65536; } +.fi + +.SH LIMITATIONS +A few IP sets options may be not supported because they are not yet implemented +in \fBnftables(8)\fP. + +Contrary to \fBnftables(8)\fP, IP sets are not attached to a specific table. +The translation utility assumes that sets are created in a table whose name +is \fBglobal\fP and family is \fBinet\fP. You might want to update the +resulting translation to use a different table name and family for your sets. + +To get up-to-date information about this, please head to +\fBhttps://wiki.nftables.org/\fP. + +.SH SEE ALSO +\fBnft(8)\fP, \fBipset(8)\fP + +.SH AUTHORS +The nftables framework has been written by the Netfilter Project +(https://www.netfilter.org). + +This manual page was written by Pablo Neira Ayuso +<pablo@netfilter.org>. + +This documentation is free/libre under the terms of the GPLv2+. + +This tool was funded through the NGI0 PET Fund, a fund established by NLnet with +financial support from the European Commission's Next Generation Internet +programme, under the aegis of DG Communications Networks, Content and Technology +under grant agreement No 825310. diff --git a/src/ipset.8 b/src/ipset.8 index 7787d79..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. @@ -333,7 +333,7 @@ are hex without 0x prefix. .IP ipset create foo hash:ip skbinfo .IP -ipset add foo skbmark 0x1111/0xff00ffff skbprio 1:10 skbqueue 10 +ipset add foo 192.168.0.1 skbmark 0x1111/0xff00ffff skbprio 1:10 skbqueue 10 .PP .SS hashsize This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets. @@ -346,10 +346,20 @@ ipset create test hash:ip hashsize 1536 .PP .SS maxelem This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets. -It does define the maximal number of elements which can be stored in the set, default 65536. +It defines the maximal number of elements which can be stored in the set, default 65536. Example: .IP -ipset create test hash:ip maxelem 2048. +ipset create test hash:ip maxelem 2048 +.PP +.SS bucketsize +This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets. +It specifies the maximal number of elements which can be stored in a hash +bucket. Possible values are any even number between 2-14 and the default is +14. Setting the value lower forces ipset to create larger hashes which +consumes more memory but gives more speed at matching in the set. +Example: +.IP +ipset create test hash:ip bucketsize 2 .PP .SS family { inet | inet6 } This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets @@ -514,7 +524,7 @@ The \fBhash:ip\fR set type uses a hash to store IP host addresses (default) or network addresses. Zero valued IP address cannot be stored in a \fBhash:ip\fR type of set. .PP -\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBbitmask\fP \fImask\fP ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fIipaddr\fR .PP @@ -539,11 +549,14 @@ ipset create foo hash:ip netmask 30 ipset add foo 192.168.1.0/24 .IP ipset test foo 192.168.1.2 +.TP +\fBbitmask\fP \fImask\fP +This works similar to \fBnetmask\fP but it will accept any valid IPv4/v6 address. It does not have to be a valid netmask. .SS hash:mac The \fBhash:mac\fR set type uses a hash to store MAC addresses. Zero valued MAC addresses cannot be stored in a \fBhash:mac\fR type of set. For matches on destination MAC addresses, see COMMENTS below. .PP -\fICREATE\-OPTIONS\fR := [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fImacaddr\fR .PP @@ -565,7 +578,7 @@ ipset test foo 01:02:03:04:05:06 The \fBhash:ip,mac\fR set type uses a hash to store IP and a MAC address pairs. Zero valued MAC addresses cannot be stored in a \fBhash:ip,mac\fR type of set. For matches on destination MAC addresses, see COMMENTS below. .PP -\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fIipaddr\fR,\fImacaddr\fR .PP @@ -587,7 +600,7 @@ ipset test foo 1.1.1.1,01:02:03:04:05:06 The \fBhash:net\fR set type uses a hash to store different sized IP network addresses. Network address with zero prefix size cannot be stored in this type of sets. .PP -\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fInetaddr\fR .PP @@ -638,7 +651,7 @@ over the second, so a nomatch entry could be potentially be ineffective if a mor first parameter existed with a suitable second parameter. Network address with zero prefix size cannot be stored in this type of set. .PP -\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBbitmask\fP \fImask\fP ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fInetaddr\fR,\fInetaddr\fR .PP @@ -670,6 +683,18 @@ values added to the first parameter of the set. The number of secondary prefixes further increases this as the list of secondary prefixes is traversed per primary prefix. .PP +Optional \fBcreate\fR options: +.TP +\fBnetmask\fP \fIcidr\fP +When the optional \fBnetmask\fP parameter specified, network addresses will be +stored in the set instead of IP host addresses. The \fIcidr\fP prefix value must be +between 1\-32 for IPv4 and between 1\-128 for IPv6. An IP address will be in the set +if the network address, which is resulted by masking the address with the netmask, +can be found in the set. +.TP +\fBbitmask\fP \fImask\fP +This works similar to \fBnetmask\fP but it will accept any valid IPv4/v6 address. It does not have to be a valid netmask. +.PP Example: .IP ipset create foo hash:net,net @@ -691,7 +716,7 @@ The \fBhash:ip,port\fR set type uses a hash to store IP address and port number The port number is interpreted together with a protocol (default TCP) and zero protocol number cannot be used. .PP -\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBbitmask\fP \fImask\fP ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR .PP @@ -731,6 +756,18 @@ The \fBhash:ip,port\fR type of sets require two \fBsrc\fR/\fBdst\fR parameters of the \fBset\fR match and \fBSET\fR target kernel modules. .PP +Optional \fBcreate\fR options: +.TP +\fBnetmask\fP \fIcidr\fP +When the optional \fBnetmask\fP parameter specified, network addresses will be +stored in the set instead of IP host addresses. The \fIcidr\fP prefix value must be +between 1\-32 for IPv4 and between 1\-128 for IPv6. An IP address will be in the set +if the network address, which is resulted by masking the address with the netmask, +can be found in the set. +.TP +\fBbitmask\fP \fImask\fP +This works similar to \fBnetmask\fP but it will accept any valid IPv4/v6 address. It does not have to be a valid netmask. +.PP Examples: .IP ipset create foo hash:ip,port @@ -748,7 +785,7 @@ address and port pairs. The port number is interpreted together with a protocol (default TCP) and zero protocol number cannot be used. Network address with zero prefix size is not accepted either. .PP -\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fInetaddr\fR,[\fIproto\fR:]\fIport\fR .PP @@ -798,7 +835,7 @@ The \fBhash:ip,port,ip\fR set type uses a hash to store IP address, port number and a second IP address triples. The port number is interpreted together with a protocol (default TCP) and zero protocol number cannot be used. .PP -\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIip\fR .PP @@ -830,7 +867,7 @@ and IP network address triples. The port number is interpreted together with a protocol (default TCP) and zero protocol number cannot be used. Network address with zero prefix size cannot be stored either. .PP -\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fInetaddr\fR .PP @@ -875,7 +912,7 @@ ipset test foo 192.168.1,80.10.0.0/24 .SS hash:ip,mark The \fBhash:ip,mark\fR set type uses a hash to store IP address and packet mark pairs. .PP -\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBmarkmask\fR \fIvalue\fR ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBmarkmask\fR \fIvalue\fR ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fIipaddr\fR,\fImark\fR .PP @@ -913,7 +950,7 @@ The \fBhash:net,port,net\fR set type behaves similarly to hash:ip,port,net but a cidr value for both the first and last parameter. Either subnet is permitted to be a /0 should you wish to match port between all destinations. .PP -\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fInetaddr\fR,[\fIproto\fR:]\fIport\fR,\fInetaddr\fR .PP @@ -960,7 +997,7 @@ ipset test foo 192.168.1.1,80,10.0.0.1 The \fBhash:net,iface\fR set type uses a hash to store different sized IP network address and interface name pairs. .PP -\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ] .PP \fIADD\-ENTRY\fR := \fInetaddr\fR,[\fBphysdev\fR:]\fIiface\fR .PP diff --git a/src/ipset.c b/src/ipset.c index ee36a06..162f477 100644 --- a/src/ipset.c +++ b/src/ipset.c @@ -6,12 +6,15 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#define _GNU_SOURCE #include <assert.h> /* assert */ #include <stdio.h> /* fprintf */ #include <stdlib.h> /* exit */ +#include <string.h> /* strcmp */ #include <config.h> #include <libipset/ipset.h> /* ipset library */ +#include <libipset/xlate.h> /* translate to nftables */ int main(int argc, char *argv[]) @@ -29,7 +32,11 @@ main(int argc, char *argv[]) exit(1); } - ret = ipset_parse_argv(ipset, argc, argv); + if (!strcmp(basename(argv[0]), "ipset-translate")) { + ret = ipset_xlate_argv(ipset, argc, argv); + } else { + ret = ipset_parse_argv(ipset, argc, argv); + } ipset_fini(ipset); @@ -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/bitmap:ip.t b/tests/bitmap:ip.t index 88d399a..a0ca22f 100644 --- a/tests/bitmap:ip.t +++ b/tests/bitmap:ip.t @@ -35,15 +35,15 @@ # Range: Add a range of elements 0 ipset -A test 2.0.0.128-2.0.0.131 timeout 4 # Range: List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo +0 ipset list test > .foo # Range: Check listing -0 diff -u -I 'Size in memory.*' .foo bitmap:ip.t.list4 +0 ./diff.sh .foo bitmap:ip.t.list4 # Sleep 5s so that entries can time out 0 sleep 5s # Range: List set after timeout -0 ipset list test | grep -v Revision: > .foo +0 ipset list test > .foo # Range: Check listing -0 diff -u -I 'Size in memory.*' .foo bitmap:ip.t.list0 +0 ./diff.sh .foo bitmap:ip.t.list0 # Range: Flush test set 0 ipset flush test # Range: Delete test set @@ -77,15 +77,15 @@ # Network: Delete the same element 0 ipset -D test 2.0.0.128 # Network: List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo +0 ipset list test > .foo # Network: Check listing -0 diff -u -I 'Size in memory.*' .foo bitmap:ip.t.list5 +0 ./diff.sh .foo bitmap:ip.t.list5 # Sleep 5s so that entries can time out 0 sleep 5s # Network: List set -0 ipset list test | grep -v Revision: > .foo +0 ipset list test > .foo # Network: Check listing -0 diff -u -I 'Size in memory.*' .foo bitmap:ip.t.list1 +0 ./diff.sh .foo bitmap:ip.t.list1 # Network: Flush test set 0 ipset flush test # Network: Delete test set @@ -119,15 +119,15 @@ # Subnets: Add a subnet of subnets 0 ipset -A test 10.8.0.0/16 timeout 4 # Subnets: List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo +0 ipset list test > .foo # Subnets: Check listing -0 diff -u -I 'Size in memory.*' .foo bitmap:ip.t.list6 +0 ./diff.sh .foo bitmap:ip.t.list6 # Sleep 5s so that entries can time out 0 sleep 5s # Subnets: List set -0 ipset list test | grep -v Revision: > .foo +0 ipset list test > .foo # Subnets: Check listing -0 diff -u -I 'Size in memory.*' .foo bitmap:ip.t.list2 +0 ./diff.sh .foo bitmap:ip.t.list2 # Subnets: Flush test set 0 ipset flush test # Subnets: Delete test set @@ -145,9 +145,9 @@ # Full: Test element not added to the set 1 ipset test test 0.1.0.0 # Full: List set -0 ipset list test | grep -v Revision: > .foo +0 ipset list test > .foo # Full: Check listing -0 diff -u -I 'Size in memory.*' .foo bitmap:ip.t.list3 +0 ./diff.sh .foo bitmap:ip.t.list3 # Full: flush set 0 ipset flush test # Full: add element with 1s timeout diff --git a/tests/bitmap:ip.t.list4 b/tests/bitmap:ip.t.list4 index 7148a8d..a26266b 100644 --- a/tests/bitmap:ip.t.list4 +++ b/tests/bitmap:ip.t.list4 @@ -1,13 +1,14 @@ Name: test Type: bitmap:ip -Header: range 2.0.0.1-2.1.0.0 timeout x -Size in memory: 532640 +Revision: 3 +Header: range 2.0.0.1-2.1.0.0 timeout 5 +Size in memory: 532608 References: 0 Number of entries: 6 Members: -2.0.0.1 timeout x -2.0.0.128 timeout x -2.0.0.129 timeout x -2.0.0.130 timeout x -2.0.0.131 timeout x -2.1.0.0 timeout x +2.0.0.1 timeout 3 +2.0.0.128 timeout 3 +2.0.0.129 timeout 3 +2.0.0.130 timeout 3 +2.0.0.131 timeout 3 +2.1.0.0 timeout 0 diff --git a/tests/bitmap:ip.t.list5 b/tests/bitmap:ip.t.list5 index 1d22665..79fe97a 100644 --- a/tests/bitmap:ip.t.list5 +++ b/tests/bitmap:ip.t.list5 @@ -1,9 +1,10 @@ Name: test Type: bitmap:ip -Header: range 2.0.0.0-2.0.255.255 timeout x -Size in memory: 532640 +Revision: 3 +Header: range 2.0.0.0-2.0.255.255 timeout 5 +Size in memory: 532608 References: 0 Number of entries: 2 Members: -2.0.0.0 timeout x -2.0.255.255 timeout x +2.0.0.0 timeout 0 +2.0.255.255 timeout 3 diff --git a/tests/bitmap:ip.t.list6 b/tests/bitmap:ip.t.list6 index c3eb347..a771148 100644 --- a/tests/bitmap:ip.t.list6 +++ b/tests/bitmap:ip.t.list6 @@ -1,265 +1,266 @@ Name: test Type: bitmap:ip -Header: range 10.0.0.0-10.255.255.255 netmask 24 timeout x -Size in memory: 532640 +Revision: 3 +Header: range 10.0.0.0-10.255.255.255 netmask 24 timeout 5 +Size in memory: 532608 References: 0 Number of entries: 258 Members: -10.0.0.0 timeout x -10.8.0.0 timeout x -10.8.1.0 timeout x -10.8.2.0 timeout x -10.8.3.0 timeout x -10.8.4.0 timeout x -10.8.5.0 timeout x -10.8.6.0 timeout x -10.8.7.0 timeout x -10.8.8.0 timeout x -10.8.9.0 timeout x -10.8.10.0 timeout x -10.8.11.0 timeout x -10.8.12.0 timeout x -10.8.13.0 timeout x -10.8.14.0 timeout x -10.8.15.0 timeout x -10.8.16.0 timeout x -10.8.17.0 timeout x -10.8.18.0 timeout x -10.8.19.0 timeout x -10.8.20.0 timeout x -10.8.21.0 timeout x -10.8.22.0 timeout x -10.8.23.0 timeout x -10.8.24.0 timeout x -10.8.25.0 timeout x -10.8.26.0 timeout x -10.8.27.0 timeout x -10.8.28.0 timeout x -10.8.29.0 timeout x -10.8.30.0 timeout x -10.8.31.0 timeout x -10.8.32.0 timeout x -10.8.33.0 timeout x -10.8.34.0 timeout x -10.8.35.0 timeout x -10.8.36.0 timeout x -10.8.37.0 timeout x -10.8.38.0 timeout x -10.8.39.0 timeout x -10.8.40.0 timeout x -10.8.41.0 timeout x -10.8.42.0 timeout x -10.8.43.0 timeout x -10.8.44.0 timeout x -10.8.45.0 timeout x -10.8.46.0 timeout x -10.8.47.0 timeout x -10.8.48.0 timeout x -10.8.49.0 timeout x -10.8.50.0 timeout x -10.8.51.0 timeout x -10.8.52.0 timeout x -10.8.53.0 timeout x -10.8.54.0 timeout x -10.8.55.0 timeout x -10.8.56.0 timeout x -10.8.57.0 timeout x -10.8.58.0 timeout x -10.8.59.0 timeout x -10.8.60.0 timeout x -10.8.61.0 timeout x -10.8.62.0 timeout x -10.8.63.0 timeout x -10.8.64.0 timeout x -10.8.65.0 timeout x -10.8.66.0 timeout x -10.8.67.0 timeout x -10.8.68.0 timeout x -10.8.69.0 timeout x -10.8.70.0 timeout x -10.8.71.0 timeout x -10.8.72.0 timeout x -10.8.73.0 timeout x -10.8.74.0 timeout x -10.8.75.0 timeout x -10.8.76.0 timeout x -10.8.77.0 timeout x -10.8.78.0 timeout x -10.8.79.0 timeout x -10.8.80.0 timeout x -10.8.81.0 timeout x -10.8.82.0 timeout x -10.8.83.0 timeout x -10.8.84.0 timeout x -10.8.85.0 timeout x -10.8.86.0 timeout x -10.8.87.0 timeout x -10.8.88.0 timeout x -10.8.89.0 timeout x -10.8.90.0 timeout x -10.8.91.0 timeout x -10.8.92.0 timeout x -10.8.93.0 timeout x -10.8.94.0 timeout x -10.8.95.0 timeout x -10.8.96.0 timeout x -10.8.97.0 timeout x -10.8.98.0 timeout x -10.8.99.0 timeout x -10.8.100.0 timeout x -10.8.101.0 timeout x -10.8.102.0 timeout x -10.8.103.0 timeout x -10.8.104.0 timeout x -10.8.105.0 timeout x -10.8.106.0 timeout x -10.8.107.0 timeout x -10.8.108.0 timeout x -10.8.109.0 timeout x -10.8.110.0 timeout x -10.8.111.0 timeout x -10.8.112.0 timeout x -10.8.113.0 timeout x -10.8.114.0 timeout x -10.8.115.0 timeout x -10.8.116.0 timeout x -10.8.117.0 timeout x -10.8.118.0 timeout x -10.8.119.0 timeout x -10.8.120.0 timeout x -10.8.121.0 timeout x -10.8.122.0 timeout x -10.8.123.0 timeout x -10.8.124.0 timeout x -10.8.125.0 timeout x -10.8.126.0 timeout x -10.8.127.0 timeout x -10.8.128.0 timeout x -10.8.129.0 timeout x -10.8.130.0 timeout x -10.8.131.0 timeout x -10.8.132.0 timeout x -10.8.133.0 timeout x -10.8.134.0 timeout x -10.8.135.0 timeout x -10.8.136.0 timeout x -10.8.137.0 timeout x -10.8.138.0 timeout x -10.8.139.0 timeout x -10.8.140.0 timeout x -10.8.141.0 timeout x -10.8.142.0 timeout x -10.8.143.0 timeout x -10.8.144.0 timeout x -10.8.145.0 timeout x -10.8.146.0 timeout x -10.8.147.0 timeout x -10.8.148.0 timeout x -10.8.149.0 timeout x -10.8.150.0 timeout x -10.8.151.0 timeout x -10.8.152.0 timeout x -10.8.153.0 timeout x -10.8.154.0 timeout x -10.8.155.0 timeout x -10.8.156.0 timeout x -10.8.157.0 timeout x -10.8.158.0 timeout x -10.8.159.0 timeout x -10.8.160.0 timeout x -10.8.161.0 timeout x -10.8.162.0 timeout x -10.8.163.0 timeout x -10.8.164.0 timeout x -10.8.165.0 timeout x -10.8.166.0 timeout x -10.8.167.0 timeout x -10.8.168.0 timeout x -10.8.169.0 timeout x -10.8.170.0 timeout x -10.8.171.0 timeout x -10.8.172.0 timeout x -10.8.173.0 timeout x -10.8.174.0 timeout x -10.8.175.0 timeout x -10.8.176.0 timeout x -10.8.177.0 timeout x -10.8.178.0 timeout x -10.8.179.0 timeout x -10.8.180.0 timeout x -10.8.181.0 timeout x -10.8.182.0 timeout x -10.8.183.0 timeout x -10.8.184.0 timeout x -10.8.185.0 timeout x -10.8.186.0 timeout x -10.8.187.0 timeout x -10.8.188.0 timeout x -10.8.189.0 timeout x -10.8.190.0 timeout x -10.8.191.0 timeout x -10.8.192.0 timeout x -10.8.193.0 timeout x -10.8.194.0 timeout x -10.8.195.0 timeout x -10.8.196.0 timeout x -10.8.197.0 timeout x -10.8.198.0 timeout x -10.8.199.0 timeout x -10.8.200.0 timeout x -10.8.201.0 timeout x -10.8.202.0 timeout x -10.8.203.0 timeout x -10.8.204.0 timeout x -10.8.205.0 timeout x -10.8.206.0 timeout x -10.8.207.0 timeout x -10.8.208.0 timeout x -10.8.209.0 timeout x -10.8.210.0 timeout x -10.8.211.0 timeout x -10.8.212.0 timeout x -10.8.213.0 timeout x -10.8.214.0 timeout x -10.8.215.0 timeout x -10.8.216.0 timeout x -10.8.217.0 timeout x -10.8.218.0 timeout x -10.8.219.0 timeout x -10.8.220.0 timeout x -10.8.221.0 timeout x -10.8.222.0 timeout x -10.8.223.0 timeout x -10.8.224.0 timeout x -10.8.225.0 timeout x -10.8.226.0 timeout x -10.8.227.0 timeout x -10.8.228.0 timeout x -10.8.229.0 timeout x -10.8.230.0 timeout x -10.8.231.0 timeout x -10.8.232.0 timeout x -10.8.233.0 timeout x -10.8.234.0 timeout x -10.8.235.0 timeout x -10.8.236.0 timeout x -10.8.237.0 timeout x -10.8.238.0 timeout x -10.8.239.0 timeout x -10.8.240.0 timeout x -10.8.241.0 timeout x -10.8.242.0 timeout x -10.8.243.0 timeout x -10.8.244.0 timeout x -10.8.245.0 timeout x -10.8.246.0 timeout x -10.8.247.0 timeout x -10.8.248.0 timeout x -10.8.249.0 timeout x -10.8.250.0 timeout x -10.8.251.0 timeout x -10.8.252.0 timeout x -10.8.253.0 timeout x -10.8.254.0 timeout x -10.8.255.0 timeout x -10.255.255.0 timeout x +10.0.0.0 timeout 3 +10.8.0.0 timeout 3 +10.8.1.0 timeout 3 +10.8.2.0 timeout 3 +10.8.3.0 timeout 3 +10.8.4.0 timeout 3 +10.8.5.0 timeout 3 +10.8.6.0 timeout 3 +10.8.7.0 timeout 3 +10.8.8.0 timeout 3 +10.8.9.0 timeout 3 +10.8.10.0 timeout 3 +10.8.11.0 timeout 3 +10.8.12.0 timeout 3 +10.8.13.0 timeout 3 +10.8.14.0 timeout 3 +10.8.15.0 timeout 3 +10.8.16.0 timeout 3 +10.8.17.0 timeout 3 +10.8.18.0 timeout 3 +10.8.19.0 timeout 3 +10.8.20.0 timeout 3 +10.8.21.0 timeout 3 +10.8.22.0 timeout 3 +10.8.23.0 timeout 3 +10.8.24.0 timeout 3 +10.8.25.0 timeout 3 +10.8.26.0 timeout 3 +10.8.27.0 timeout 3 +10.8.28.0 timeout 3 +10.8.29.0 timeout 3 +10.8.30.0 timeout 3 +10.8.31.0 timeout 3 +10.8.32.0 timeout 3 +10.8.33.0 timeout 3 +10.8.34.0 timeout 3 +10.8.35.0 timeout 3 +10.8.36.0 timeout 3 +10.8.37.0 timeout 3 +10.8.38.0 timeout 3 +10.8.39.0 timeout 3 +10.8.40.0 timeout 3 +10.8.41.0 timeout 3 +10.8.42.0 timeout 3 +10.8.43.0 timeout 3 +10.8.44.0 timeout 3 +10.8.45.0 timeout 3 +10.8.46.0 timeout 3 +10.8.47.0 timeout 3 +10.8.48.0 timeout 3 +10.8.49.0 timeout 3 +10.8.50.0 timeout 3 +10.8.51.0 timeout 3 +10.8.52.0 timeout 3 +10.8.53.0 timeout 3 +10.8.54.0 timeout 3 +10.8.55.0 timeout 3 +10.8.56.0 timeout 3 +10.8.57.0 timeout 3 +10.8.58.0 timeout 3 +10.8.59.0 timeout 3 +10.8.60.0 timeout 3 +10.8.61.0 timeout 3 +10.8.62.0 timeout 3 +10.8.63.0 timeout 3 +10.8.64.0 timeout 3 +10.8.65.0 timeout 3 +10.8.66.0 timeout 3 +10.8.67.0 timeout 3 +10.8.68.0 timeout 3 +10.8.69.0 timeout 3 +10.8.70.0 timeout 3 +10.8.71.0 timeout 3 +10.8.72.0 timeout 3 +10.8.73.0 timeout 3 +10.8.74.0 timeout 3 +10.8.75.0 timeout 3 +10.8.76.0 timeout 3 +10.8.77.0 timeout 3 +10.8.78.0 timeout 3 +10.8.79.0 timeout 3 +10.8.80.0 timeout 3 +10.8.81.0 timeout 3 +10.8.82.0 timeout 3 +10.8.83.0 timeout 3 +10.8.84.0 timeout 3 +10.8.85.0 timeout 3 +10.8.86.0 timeout 3 +10.8.87.0 timeout 3 +10.8.88.0 timeout 3 +10.8.89.0 timeout 3 +10.8.90.0 timeout 3 +10.8.91.0 timeout 3 +10.8.92.0 timeout 3 +10.8.93.0 timeout 3 +10.8.94.0 timeout 3 +10.8.95.0 timeout 3 +10.8.96.0 timeout 3 +10.8.97.0 timeout 3 +10.8.98.0 timeout 3 +10.8.99.0 timeout 3 +10.8.100.0 timeout 3 +10.8.101.0 timeout 3 +10.8.102.0 timeout 3 +10.8.103.0 timeout 3 +10.8.104.0 timeout 3 +10.8.105.0 timeout 3 +10.8.106.0 timeout 3 +10.8.107.0 timeout 3 +10.8.108.0 timeout 3 +10.8.109.0 timeout 3 +10.8.110.0 timeout 3 +10.8.111.0 timeout 3 +10.8.112.0 timeout 3 +10.8.113.0 timeout 3 +10.8.114.0 timeout 3 +10.8.115.0 timeout 3 +10.8.116.0 timeout 3 +10.8.117.0 timeout 3 +10.8.118.0 timeout 3 +10.8.119.0 timeout 3 +10.8.120.0 timeout 3 +10.8.121.0 timeout 3 +10.8.122.0 timeout 3 +10.8.123.0 timeout 3 +10.8.124.0 timeout 3 +10.8.125.0 timeout 3 +10.8.126.0 timeout 3 +10.8.127.0 timeout 3 +10.8.128.0 timeout 3 +10.8.129.0 timeout 3 +10.8.130.0 timeout 3 +10.8.131.0 timeout 3 +10.8.132.0 timeout 3 +10.8.133.0 timeout 3 +10.8.134.0 timeout 3 +10.8.135.0 timeout 3 +10.8.136.0 timeout 3 +10.8.137.0 timeout 3 +10.8.138.0 timeout 3 +10.8.139.0 timeout 3 +10.8.140.0 timeout 3 +10.8.141.0 timeout 3 +10.8.142.0 timeout 3 +10.8.143.0 timeout 3 +10.8.144.0 timeout 3 +10.8.145.0 timeout 3 +10.8.146.0 timeout 3 +10.8.147.0 timeout 3 +10.8.148.0 timeout 3 +10.8.149.0 timeout 3 +10.8.150.0 timeout 3 +10.8.151.0 timeout 3 +10.8.152.0 timeout 3 +10.8.153.0 timeout 3 +10.8.154.0 timeout 3 +10.8.155.0 timeout 3 +10.8.156.0 timeout 3 +10.8.157.0 timeout 3 +10.8.158.0 timeout 3 +10.8.159.0 timeout 3 +10.8.160.0 timeout 3 +10.8.161.0 timeout 3 +10.8.162.0 timeout 3 +10.8.163.0 timeout 3 +10.8.164.0 timeout 3 +10.8.165.0 timeout 3 +10.8.166.0 timeout 3 +10.8.167.0 timeout 3 +10.8.168.0 timeout 3 +10.8.169.0 timeout 3 +10.8.170.0 timeout 3 +10.8.171.0 timeout 3 +10.8.172.0 timeout 3 +10.8.173.0 timeout 3 +10.8.174.0 timeout 3 +10.8.175.0 timeout 3 +10.8.176.0 timeout 3 +10.8.177.0 timeout 3 +10.8.178.0 timeout 3 +10.8.179.0 timeout 3 +10.8.180.0 timeout 3 +10.8.181.0 timeout 3 +10.8.182.0 timeout 3 +10.8.183.0 timeout 3 +10.8.184.0 timeout 3 +10.8.185.0 timeout 3 +10.8.186.0 timeout 3 +10.8.187.0 timeout 3 +10.8.188.0 timeout 3 +10.8.189.0 timeout 3 +10.8.190.0 timeout 3 +10.8.191.0 timeout 3 +10.8.192.0 timeout 3 +10.8.193.0 timeout 3 +10.8.194.0 timeout 3 +10.8.195.0 timeout 3 +10.8.196.0 timeout 3 +10.8.197.0 timeout 3 +10.8.198.0 timeout 3 +10.8.199.0 timeout 3 +10.8.200.0 timeout 3 +10.8.201.0 timeout 3 +10.8.202.0 timeout 3 +10.8.203.0 timeout 3 +10.8.204.0 timeout 3 +10.8.205.0 timeout 3 +10.8.206.0 timeout 3 +10.8.207.0 timeout 3 +10.8.208.0 timeout 3 +10.8.209.0 timeout 3 +10.8.210.0 timeout 3 +10.8.211.0 timeout 3 +10.8.212.0 timeout 3 +10.8.213.0 timeout 3 +10.8.214.0 timeout 3 +10.8.215.0 timeout 3 +10.8.216.0 timeout 3 +10.8.217.0 timeout 3 +10.8.218.0 timeout 3 +10.8.219.0 timeout 3 +10.8.220.0 timeout 3 +10.8.221.0 timeout 3 +10.8.222.0 timeout 3 +10.8.223.0 timeout 3 +10.8.224.0 timeout 3 +10.8.225.0 timeout 3 +10.8.226.0 timeout 3 +10.8.227.0 timeout 3 +10.8.228.0 timeout 3 +10.8.229.0 timeout 3 +10.8.230.0 timeout 3 +10.8.231.0 timeout 3 +10.8.232.0 timeout 3 +10.8.233.0 timeout 3 +10.8.234.0 timeout 3 +10.8.235.0 timeout 3 +10.8.236.0 timeout 3 +10.8.237.0 timeout 3 +10.8.238.0 timeout 3 +10.8.239.0 timeout 3 +10.8.240.0 timeout 3 +10.8.241.0 timeout 3 +10.8.242.0 timeout 3 +10.8.243.0 timeout 3 +10.8.244.0 timeout 3 +10.8.245.0 timeout 3 +10.8.246.0 timeout 3 +10.8.247.0 timeout 3 +10.8.248.0 timeout 3 +10.8.249.0 timeout 3 +10.8.250.0 timeout 3 +10.8.251.0 timeout 3 +10.8.252.0 timeout 3 +10.8.253.0 timeout 3 +10.8.254.0 timeout 3 +10.8.255.0 timeout 3 +10.255.255.0 timeout 0 diff --git a/tests/cidr.sh b/tests/cidr.sh index b7d695a..2c4d939 100755 --- a/tests/cidr.sh +++ b/tests/cidr.sh @@ -37,6 +37,30 @@ NETS="0.0.0.0/1 ipset="../src/ipset" +if which netmask >/dev/null 2>&1; then + net_first_addr() { + netmask -r $1 | cut -d - -f 1 + } + net_last_addr() { + netmask -r $1 | cut -d - -f 2 | cut -d ' ' -f 1 + } +elif which ipcalc >/dev/null 2>&1; then + net_first_addr() { + ipcalc $1 | awk '/^Address:/{print $2}' + } + net_last_addr() { + # Netmask tool prints broadcast address as last one, so + # prefer that instead of HostMax. Also fix for /31 and /32 + # being recognized as special by ipcalc. + ipcalc $1 | awk '/^(Hostroute|HostMax):/{out=$2} + /^Broadcast:/{out=$2} + END{print out}' + } +else + echo "need either netmask or ipcalc tools" + exit 1 +fi + case "$1" in net) $ipset n test hash:net @@ -46,9 +70,9 @@ net) done <<<"$NETS" while IFS= read x; do - first=`netmask -r $x | cut -d - -f 1` + first=`net_first_addr $x` $ipset test test $first >/dev/null 2>&1 - last=`netmask -r $x | cut -d - -f 2 | cut -d ' ' -f 1` + last=`net_last_addr $x` $ipset test test $last >/dev/null 2>&1 done <<<"$NETS" @@ -67,9 +91,9 @@ net,port) n=1 while IFS= read x; do - first=`netmask -r $x | cut -d - -f 1` + first=`net_first_addr $x` $ipset test test $first,$n >/dev/null 2>&1 - last=`netmask -r $x | cut -d - -f 2 | cut -d ' ' -f 1` + last=`net_last_addr $x` $ipset test test $last,$n >/dev/null 2>&1 n=$((n+1)) done <<<"$NETS" diff --git a/tests/comment.t b/tests/comment.t index b12609b..8f57919 100644 --- a/tests/comment.t +++ b/tests/comment.t @@ -9,9 +9,9 @@ # Bitmap comment: Test element with comment 0 ipset test test 2.0.0.1 # Bitmap comment: List set -0 ipset list test | grep -v Revision: > .foo +0 ipset list test > .foo # Bitmap comment: Check listing -0 diff -u -I 'Size in memory.*' .foo comment.t.list0 +0 ./diff.sh .foo comment.t.list0 # Bitmap comment: Delete element with comment 0 ipset del test 2.0.0.1 # Bitmap comment: Test deleted element @@ -31,9 +31,9 @@ # Bitmap comment: Add multiple elements with comment 0 for x in `seq 1 255`; do echo "add test 2.0.0.$x comment \\\"text message $x\\\""; done | ipset restore # Bitmap comment: List set -0 ipset list test | grep -v Revision: > .foo +0 ipset list test > .foo # Bitmap comment: Check listing -0 diff -u -I 'Size in memory.*' .foo comment.t.list1 +0 ./diff.sh .foo comment.t.list1 # Bitmap comment: Delete test set 0 ipset destroy test # Bitmap comment: create set with timeout @@ -43,15 +43,15 @@ # Bitmap comment: Add multiple elements with zero timeout 0 for x in `seq 1 255`; do echo "add test 2.0.1.$x timeout 0 comment \\\"text message $x\\\""; done | ipset restore # Bitmap comment: List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo +0 ipset list test > .foo # Bitmap comment: Check listing -0 diff -u -I 'Size in memory.*' .foo comment.t.list11 +0 ./diff.sh .foo comment.t.list11 # Sleep 5s so that entries can time out 0 sleep 5s # Bitmap comment: List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo +0 ipset list test > .foo # Bitmap comment: Check listing -0 diff -u -I 'Size in memory.*' -I 'Number of entries' .foo comment.t.list12 +0 ./diff.sh .foo comment.t.list12 # Bitmap comment: Flush set 0 ipset flush test # Bitmap comment: Delete test set @@ -87,9 +87,9 @@ # Hash comment: Try to add IP address 0 ipset add test 2.0.0.1,2.0.0.2 # Hash comment: List set -0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Hash comment: Check listing -0 diff -u -I 'Size in memory.*' .foo comment.t.list2 +0 ./diff.sh .foo comment.t.list2 # Hash comment: Update element with comment 0 ipset -! add test 2.0.0.1,2.0.0.2 comment "text 2.0.0.1,2.0.0.2" # Hash comment: Check updated element @@ -113,7 +113,7 @@ # Hash comment: Stress test with comments and timeout 0 ./netnetgen.sh comment timeout | ipset restore # Hash comment: List set and check the number of elements -0 n=`ipset -L test|grep '^10.'|wc -l` && test $n -eq 87040 +0 n=`ipset save test|grep 'add test 10.'|wc -l` && test $n -eq 87040 # Hash comment: Destroy test set 0 ipset destroy test # Hash comment: create set with timeout @@ -123,15 +123,15 @@ # Hash comment: Add multiple elements with zero timeout 0 for x in `seq 0 255`; do echo "add test 2.0.1.$x timeout 0 comment \\\"text message $x\\\""; done | ipset restore # Hash comment: List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Hash comment: Check listing -0 diff -u -I 'Size in memory.*' .foo comment.t.list21 +0 ./diff.sh .foo comment.t.list21 # Sleep 5s so that entries can time out 0 sleep 5s # Hash comment: List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Hash comment: Check listing -0 diff -u -I 'Size in memory.*' .foo comment.t.list22 +0 ./diff.sh .foo comment.t.list22 # Hash comment: Flush set 0 ipset flush test # Hash comment: Delete test set @@ -147,9 +147,9 @@ # List comment: Add b set with comment 0 ipset a test b after a comment "b set comment" # List comment: List sets -0 ipset list | grep -v Revision: > .foo +0 ipset list > .foo # List comment: Check listing -0 diff -u -I 'Size in memory.*' .foo comment.t.list3 +0 ./diff.sh .foo comment.t.list3 # Flush sets 0 ipset f # Destroy sets diff --git a/tests/comment.t.list11 b/tests/comment.t.list11 index 7d6990f..498ba5f 100644 --- a/tests/comment.t.list11 +++ b/tests/comment.t.list11 @@ -1,517 +1,518 @@ Name: test Type: bitmap:ip -Header: range 2.0.0.1-2.1.0.0 timeout x comment -Size in memory: 1056928 +Revision: 3 +Header: range 2.0.0.1-2.1.0.0 timeout 3 comment +Size in memory: 1073510 References: 0 Number of entries: 510 Members: -2.0.0.1 timeout x comment "text message 1" -2.0.0.2 timeout x comment "text message 2" -2.0.0.3 timeout x comment "text message 3" -2.0.0.4 timeout x comment "text message 4" -2.0.0.5 timeout x comment "text message 5" -2.0.0.6 timeout x comment "text message 6" -2.0.0.7 timeout x comment "text message 7" -2.0.0.8 timeout x comment "text message 8" -2.0.0.9 timeout x comment "text message 9" -2.0.0.10 timeout x comment "text message 10" -2.0.0.11 timeout x comment "text message 11" -2.0.0.12 timeout x comment "text message 12" -2.0.0.13 timeout x comment "text message 13" -2.0.0.14 timeout x comment "text message 14" -2.0.0.15 timeout x comment "text message 15" -2.0.0.16 timeout x comment "text message 16" -2.0.0.17 timeout x comment "text message 17" -2.0.0.18 timeout x comment "text message 18" -2.0.0.19 timeout x comment "text message 19" -2.0.0.20 timeout x comment "text message 20" -2.0.0.21 timeout x comment "text message 21" -2.0.0.22 timeout x comment "text message 22" -2.0.0.23 timeout x comment "text message 23" -2.0.0.24 timeout x comment "text message 24" -2.0.0.25 timeout x comment "text message 25" -2.0.0.26 timeout x comment "text message 26" -2.0.0.27 timeout x comment "text message 27" -2.0.0.28 timeout x comment "text message 28" -2.0.0.29 timeout x comment "text message 29" -2.0.0.30 timeout x comment "text message 30" -2.0.0.31 timeout x comment "text message 31" -2.0.0.32 timeout x comment "text message 32" -2.0.0.33 timeout x comment "text message 33" -2.0.0.34 timeout x comment "text message 34" -2.0.0.35 timeout x comment "text message 35" -2.0.0.36 timeout x comment "text message 36" -2.0.0.37 timeout x comment "text message 37" -2.0.0.38 timeout x comment "text message 38" -2.0.0.39 timeout x comment "text message 39" -2.0.0.40 timeout x comment "text message 40" -2.0.0.41 timeout x comment "text message 41" -2.0.0.42 timeout x comment "text message 42" -2.0.0.43 timeout x comment "text message 43" -2.0.0.44 timeout x comment "text message 44" -2.0.0.45 timeout x comment "text message 45" -2.0.0.46 timeout x comment "text message 46" -2.0.0.47 timeout x comment "text message 47" -2.0.0.48 timeout x comment "text message 48" -2.0.0.49 timeout x comment "text message 49" -2.0.0.50 timeout x comment "text message 50" -2.0.0.51 timeout x comment "text message 51" -2.0.0.52 timeout x comment "text message 52" -2.0.0.53 timeout x comment "text message 53" -2.0.0.54 timeout x comment "text message 54" -2.0.0.55 timeout x comment "text message 55" -2.0.0.56 timeout x comment "text message 56" -2.0.0.57 timeout x comment "text message 57" -2.0.0.58 timeout x comment "text message 58" -2.0.0.59 timeout x comment "text message 59" -2.0.0.60 timeout x comment "text message 60" -2.0.0.61 timeout x comment "text message 61" -2.0.0.62 timeout x comment "text message 62" -2.0.0.63 timeout x comment "text message 63" -2.0.0.64 timeout x comment "text message 64" -2.0.0.65 timeout x comment "text message 65" -2.0.0.66 timeout x comment "text message 66" -2.0.0.67 timeout x comment "text message 67" -2.0.0.68 timeout x comment "text message 68" -2.0.0.69 timeout x comment "text message 69" -2.0.0.70 timeout x comment "text message 70" -2.0.0.71 timeout x comment "text message 71" -2.0.0.72 timeout x comment "text message 72" -2.0.0.73 timeout x comment "text message 73" -2.0.0.74 timeout x comment "text message 74" -2.0.0.75 timeout x comment "text message 75" -2.0.0.76 timeout x comment "text message 76" -2.0.0.77 timeout x comment "text message 77" -2.0.0.78 timeout x comment "text message 78" -2.0.0.79 timeout x comment "text message 79" -2.0.0.80 timeout x comment "text message 80" -2.0.0.81 timeout x comment "text message 81" -2.0.0.82 timeout x comment "text message 82" -2.0.0.83 timeout x comment "text message 83" -2.0.0.84 timeout x comment "text message 84" -2.0.0.85 timeout x comment "text message 85" -2.0.0.86 timeout x comment "text message 86" -2.0.0.87 timeout x comment "text message 87" -2.0.0.88 timeout x comment "text message 88" -2.0.0.89 timeout x comment "text message 89" -2.0.0.90 timeout x comment "text message 90" -2.0.0.91 timeout x comment "text message 91" -2.0.0.92 timeout x comment "text message 92" -2.0.0.93 timeout x comment "text message 93" -2.0.0.94 timeout x comment "text message 94" -2.0.0.95 timeout x comment "text message 95" -2.0.0.96 timeout x comment "text message 96" -2.0.0.97 timeout x comment "text message 97" -2.0.0.98 timeout x comment "text message 98" -2.0.0.99 timeout x comment "text message 99" -2.0.0.100 timeout x comment "text message 100" -2.0.0.101 timeout x comment "text message 101" -2.0.0.102 timeout x comment "text message 102" -2.0.0.103 timeout x comment "text message 103" -2.0.0.104 timeout x comment "text message 104" -2.0.0.105 timeout x comment "text message 105" -2.0.0.106 timeout x comment "text message 106" -2.0.0.107 timeout x comment "text message 107" -2.0.0.108 timeout x comment "text message 108" -2.0.0.109 timeout x comment "text message 109" -2.0.0.110 timeout x comment "text message 110" -2.0.0.111 timeout x comment "text message 111" -2.0.0.112 timeout x comment "text message 112" -2.0.0.113 timeout x comment "text message 113" -2.0.0.114 timeout x comment "text message 114" -2.0.0.115 timeout x comment "text message 115" -2.0.0.116 timeout x comment "text message 116" -2.0.0.117 timeout x comment "text message 117" -2.0.0.118 timeout x comment "text message 118" -2.0.0.119 timeout x comment "text message 119" -2.0.0.120 timeout x comment "text message 120" -2.0.0.121 timeout x comment "text message 121" -2.0.0.122 timeout x comment "text message 122" -2.0.0.123 timeout x comment "text message 123" -2.0.0.124 timeout x comment "text message 124" -2.0.0.125 timeout x comment "text message 125" -2.0.0.126 timeout x comment "text message 126" -2.0.0.127 timeout x comment "text message 127" -2.0.0.128 timeout x comment "text message 128" -2.0.0.129 timeout x comment "text message 129" -2.0.0.130 timeout x comment "text message 130" -2.0.0.131 timeout x comment "text message 131" -2.0.0.132 timeout x comment "text message 132" -2.0.0.133 timeout x comment "text message 133" -2.0.0.134 timeout x comment "text message 134" -2.0.0.135 timeout x comment "text message 135" -2.0.0.136 timeout x comment "text message 136" -2.0.0.137 timeout x comment "text message 137" -2.0.0.138 timeout x comment "text message 138" -2.0.0.139 timeout x comment "text message 139" -2.0.0.140 timeout x comment "text message 140" -2.0.0.141 timeout x comment "text message 141" -2.0.0.142 timeout x comment "text message 142" -2.0.0.143 timeout x comment "text message 143" -2.0.0.144 timeout x comment "text message 144" -2.0.0.145 timeout x comment "text message 145" -2.0.0.146 timeout x comment "text message 146" -2.0.0.147 timeout x comment "text message 147" -2.0.0.148 timeout x comment "text message 148" -2.0.0.149 timeout x comment "text message 149" -2.0.0.150 timeout x comment "text message 150" -2.0.0.151 timeout x comment "text message 151" -2.0.0.152 timeout x comment "text message 152" -2.0.0.153 timeout x comment "text message 153" -2.0.0.154 timeout x comment "text message 154" -2.0.0.155 timeout x comment "text message 155" -2.0.0.156 timeout x comment "text message 156" -2.0.0.157 timeout x comment "text message 157" -2.0.0.158 timeout x comment "text message 158" -2.0.0.159 timeout x comment "text message 159" -2.0.0.160 timeout x comment "text message 160" -2.0.0.161 timeout x comment "text message 161" -2.0.0.162 timeout x comment "text message 162" -2.0.0.163 timeout x comment "text message 163" -2.0.0.164 timeout x comment "text message 164" -2.0.0.165 timeout x comment "text message 165" -2.0.0.166 timeout x comment "text message 166" -2.0.0.167 timeout x comment "text message 167" -2.0.0.168 timeout x comment "text message 168" -2.0.0.169 timeout x comment "text message 169" -2.0.0.170 timeout x comment "text message 170" -2.0.0.171 timeout x comment "text message 171" -2.0.0.172 timeout x comment "text message 172" -2.0.0.173 timeout x comment "text message 173" -2.0.0.174 timeout x comment "text message 174" -2.0.0.175 timeout x comment "text message 175" -2.0.0.176 timeout x comment "text message 176" -2.0.0.177 timeout x comment "text message 177" -2.0.0.178 timeout x comment "text message 178" -2.0.0.179 timeout x comment "text message 179" -2.0.0.180 timeout x comment "text message 180" -2.0.0.181 timeout x comment "text message 181" -2.0.0.182 timeout x comment "text message 182" -2.0.0.183 timeout x comment "text message 183" -2.0.0.184 timeout x comment "text message 184" -2.0.0.185 timeout x comment "text message 185" -2.0.0.186 timeout x comment "text message 186" -2.0.0.187 timeout x comment "text message 187" -2.0.0.188 timeout x comment "text message 188" -2.0.0.189 timeout x comment "text message 189" -2.0.0.190 timeout x comment "text message 190" -2.0.0.191 timeout x comment "text message 191" -2.0.0.192 timeout x comment "text message 192" -2.0.0.193 timeout x comment "text message 193" -2.0.0.194 timeout x comment "text message 194" -2.0.0.195 timeout x comment "text message 195" -2.0.0.196 timeout x comment "text message 196" -2.0.0.197 timeout x comment "text message 197" -2.0.0.198 timeout x comment "text message 198" -2.0.0.199 timeout x comment "text message 199" -2.0.0.200 timeout x comment "text message 200" -2.0.0.201 timeout x comment "text message 201" -2.0.0.202 timeout x comment "text message 202" -2.0.0.203 timeout x comment "text message 203" -2.0.0.204 timeout x comment "text message 204" -2.0.0.205 timeout x comment "text message 205" -2.0.0.206 timeout x comment "text message 206" -2.0.0.207 timeout x comment "text message 207" -2.0.0.208 timeout x comment "text message 208" -2.0.0.209 timeout x comment "text message 209" -2.0.0.210 timeout x comment "text message 210" -2.0.0.211 timeout x comment "text message 211" -2.0.0.212 timeout x comment "text message 212" -2.0.0.213 timeout x comment "text message 213" -2.0.0.214 timeout x comment "text message 214" -2.0.0.215 timeout x comment "text message 215" -2.0.0.216 timeout x comment "text message 216" -2.0.0.217 timeout x comment "text message 217" -2.0.0.218 timeout x comment "text message 218" -2.0.0.219 timeout x comment "text message 219" -2.0.0.220 timeout x comment "text message 220" -2.0.0.221 timeout x comment "text message 221" -2.0.0.222 timeout x comment "text message 222" -2.0.0.223 timeout x comment "text message 223" -2.0.0.224 timeout x comment "text message 224" -2.0.0.225 timeout x comment "text message 225" -2.0.0.226 timeout x comment "text message 226" -2.0.0.227 timeout x comment "text message 227" -2.0.0.228 timeout x comment "text message 228" -2.0.0.229 timeout x comment "text message 229" -2.0.0.230 timeout x comment "text message 230" -2.0.0.231 timeout x comment "text message 231" -2.0.0.232 timeout x comment "text message 232" -2.0.0.233 timeout x comment "text message 233" -2.0.0.234 timeout x comment "text message 234" -2.0.0.235 timeout x comment "text message 235" -2.0.0.236 timeout x comment "text message 236" -2.0.0.237 timeout x comment "text message 237" -2.0.0.238 timeout x comment "text message 238" -2.0.0.239 timeout x comment "text message 239" -2.0.0.240 timeout x comment "text message 240" -2.0.0.241 timeout x comment "text message 241" -2.0.0.242 timeout x comment "text message 242" -2.0.0.243 timeout x comment "text message 243" -2.0.0.244 timeout x comment "text message 244" -2.0.0.245 timeout x comment "text message 245" -2.0.0.246 timeout x comment "text message 246" -2.0.0.247 timeout x comment "text message 247" -2.0.0.248 timeout x comment "text message 248" -2.0.0.249 timeout x comment "text message 249" -2.0.0.250 timeout x comment "text message 250" -2.0.0.251 timeout x comment "text message 251" -2.0.0.252 timeout x comment "text message 252" -2.0.0.253 timeout x comment "text message 253" -2.0.0.254 timeout x comment "text message 254" -2.0.0.255 timeout x comment "text message 255" -2.0.1.1 timeout x comment "text message 1" -2.0.1.2 timeout x comment "text message 2" -2.0.1.3 timeout x comment "text message 3" -2.0.1.4 timeout x comment "text message 4" -2.0.1.5 timeout x comment "text message 5" -2.0.1.6 timeout x comment "text message 6" -2.0.1.7 timeout x comment "text message 7" -2.0.1.8 timeout x comment "text message 8" -2.0.1.9 timeout x comment "text message 9" -2.0.1.10 timeout x comment "text message 10" -2.0.1.11 timeout x comment "text message 11" -2.0.1.12 timeout x comment "text message 12" -2.0.1.13 timeout x comment "text message 13" -2.0.1.14 timeout x comment "text message 14" -2.0.1.15 timeout x comment "text message 15" -2.0.1.16 timeout x comment "text message 16" -2.0.1.17 timeout x comment "text message 17" -2.0.1.18 timeout x comment "text message 18" -2.0.1.19 timeout x comment "text message 19" -2.0.1.20 timeout x comment "text message 20" -2.0.1.21 timeout x comment "text message 21" -2.0.1.22 timeout x comment "text message 22" -2.0.1.23 timeout x comment "text message 23" -2.0.1.24 timeout x comment "text message 24" -2.0.1.25 timeout x comment "text message 25" -2.0.1.26 timeout x comment "text message 26" -2.0.1.27 timeout x comment "text message 27" -2.0.1.28 timeout x comment "text message 28" -2.0.1.29 timeout x comment "text message 29" -2.0.1.30 timeout x comment "text message 30" -2.0.1.31 timeout x comment "text message 31" -2.0.1.32 timeout x comment "text message 32" -2.0.1.33 timeout x comment "text message 33" -2.0.1.34 timeout x comment "text message 34" -2.0.1.35 timeout x comment "text message 35" -2.0.1.36 timeout x comment "text message 36" -2.0.1.37 timeout x comment "text message 37" -2.0.1.38 timeout x comment "text message 38" -2.0.1.39 timeout x comment "text message 39" -2.0.1.40 timeout x comment "text message 40" -2.0.1.41 timeout x comment "text message 41" -2.0.1.42 timeout x comment "text message 42" -2.0.1.43 timeout x comment "text message 43" -2.0.1.44 timeout x comment "text message 44" -2.0.1.45 timeout x comment "text message 45" -2.0.1.46 timeout x comment "text message 46" -2.0.1.47 timeout x comment "text message 47" -2.0.1.48 timeout x comment "text message 48" -2.0.1.49 timeout x comment "text message 49" -2.0.1.50 timeout x comment "text message 50" -2.0.1.51 timeout x comment "text message 51" -2.0.1.52 timeout x comment "text message 52" -2.0.1.53 timeout x comment "text message 53" -2.0.1.54 timeout x comment "text message 54" -2.0.1.55 timeout x comment "text message 55" -2.0.1.56 timeout x comment "text message 56" -2.0.1.57 timeout x comment "text message 57" -2.0.1.58 timeout x comment "text message 58" -2.0.1.59 timeout x comment "text message 59" -2.0.1.60 timeout x comment "text message 60" -2.0.1.61 timeout x comment "text message 61" -2.0.1.62 timeout x comment "text message 62" -2.0.1.63 timeout x comment "text message 63" -2.0.1.64 timeout x comment "text message 64" -2.0.1.65 timeout x comment "text message 65" -2.0.1.66 timeout x comment "text message 66" -2.0.1.67 timeout x comment "text message 67" -2.0.1.68 timeout x comment "text message 68" -2.0.1.69 timeout x comment "text message 69" -2.0.1.70 timeout x comment "text message 70" -2.0.1.71 timeout x comment "text message 71" -2.0.1.72 timeout x comment "text message 72" -2.0.1.73 timeout x comment "text message 73" -2.0.1.74 timeout x comment "text message 74" -2.0.1.75 timeout x comment "text message 75" -2.0.1.76 timeout x comment "text message 76" -2.0.1.77 timeout x comment "text message 77" -2.0.1.78 timeout x comment "text message 78" -2.0.1.79 timeout x comment "text message 79" -2.0.1.80 timeout x comment "text message 80" -2.0.1.81 timeout x comment "text message 81" -2.0.1.82 timeout x comment "text message 82" -2.0.1.83 timeout x comment "text message 83" -2.0.1.84 timeout x comment "text message 84" -2.0.1.85 timeout x comment "text message 85" -2.0.1.86 timeout x comment "text message 86" -2.0.1.87 timeout x comment "text message 87" -2.0.1.88 timeout x comment "text message 88" -2.0.1.89 timeout x comment "text message 89" -2.0.1.90 timeout x comment "text message 90" -2.0.1.91 timeout x comment "text message 91" -2.0.1.92 timeout x comment "text message 92" -2.0.1.93 timeout x comment "text message 93" -2.0.1.94 timeout x comment "text message 94" -2.0.1.95 timeout x comment "text message 95" -2.0.1.96 timeout x comment "text message 96" -2.0.1.97 timeout x comment "text message 97" -2.0.1.98 timeout x comment "text message 98" -2.0.1.99 timeout x comment "text message 99" -2.0.1.100 timeout x comment "text message 100" -2.0.1.101 timeout x comment "text message 101" -2.0.1.102 timeout x comment "text message 102" -2.0.1.103 timeout x comment "text message 103" -2.0.1.104 timeout x comment "text message 104" -2.0.1.105 timeout x comment "text message 105" -2.0.1.106 timeout x comment "text message 106" -2.0.1.107 timeout x comment "text message 107" -2.0.1.108 timeout x comment "text message 108" -2.0.1.109 timeout x comment "text message 109" -2.0.1.110 timeout x comment "text message 110" -2.0.1.111 timeout x comment "text message 111" -2.0.1.112 timeout x comment "text message 112" -2.0.1.113 timeout x comment "text message 113" -2.0.1.114 timeout x comment "text message 114" -2.0.1.115 timeout x comment "text message 115" -2.0.1.116 timeout x comment "text message 116" -2.0.1.117 timeout x comment "text message 117" -2.0.1.118 timeout x comment "text message 118" -2.0.1.119 timeout x comment "text message 119" -2.0.1.120 timeout x comment "text message 120" -2.0.1.121 timeout x comment "text message 121" -2.0.1.122 timeout x comment "text message 122" -2.0.1.123 timeout x comment "text message 123" -2.0.1.124 timeout x comment "text message 124" -2.0.1.125 timeout x comment "text message 125" -2.0.1.126 timeout x comment "text message 126" -2.0.1.127 timeout x comment "text message 127" -2.0.1.128 timeout x comment "text message 128" -2.0.1.129 timeout x comment "text message 129" -2.0.1.130 timeout x comment "text message 130" -2.0.1.131 timeout x comment "text message 131" -2.0.1.132 timeout x comment "text message 132" -2.0.1.133 timeout x comment "text message 133" -2.0.1.134 timeout x comment "text message 134" -2.0.1.135 timeout x comment "text message 135" -2.0.1.136 timeout x comment "text message 136" -2.0.1.137 timeout x comment "text message 137" -2.0.1.138 timeout x comment "text message 138" -2.0.1.139 timeout x comment "text message 139" -2.0.1.140 timeout x comment "text message 140" -2.0.1.141 timeout x comment "text message 141" -2.0.1.142 timeout x comment "text message 142" -2.0.1.143 timeout x comment "text message 143" -2.0.1.144 timeout x comment "text message 144" -2.0.1.145 timeout x comment "text message 145" -2.0.1.146 timeout x comment "text message 146" -2.0.1.147 timeout x comment "text message 147" -2.0.1.148 timeout x comment "text message 148" -2.0.1.149 timeout x comment "text message 149" -2.0.1.150 timeout x comment "text message 150" -2.0.1.151 timeout x comment "text message 151" -2.0.1.152 timeout x comment "text message 152" -2.0.1.153 timeout x comment "text message 153" -2.0.1.154 timeout x comment "text message 154" -2.0.1.155 timeout x comment "text message 155" -2.0.1.156 timeout x comment "text message 156" -2.0.1.157 timeout x comment "text message 157" -2.0.1.158 timeout x comment "text message 158" -2.0.1.159 timeout x comment "text message 159" -2.0.1.160 timeout x comment "text message 160" -2.0.1.161 timeout x comment "text message 161" -2.0.1.162 timeout x comment "text message 162" -2.0.1.163 timeout x comment "text message 163" -2.0.1.164 timeout x comment "text message 164" -2.0.1.165 timeout x comment "text message 165" -2.0.1.166 timeout x comment "text message 166" -2.0.1.167 timeout x comment "text message 167" -2.0.1.168 timeout x comment "text message 168" -2.0.1.169 timeout x comment "text message 169" -2.0.1.170 timeout x comment "text message 170" -2.0.1.171 timeout x comment "text message 171" -2.0.1.172 timeout x comment "text message 172" -2.0.1.173 timeout x comment "text message 173" -2.0.1.174 timeout x comment "text message 174" -2.0.1.175 timeout x comment "text message 175" -2.0.1.176 timeout x comment "text message 176" -2.0.1.177 timeout x comment "text message 177" -2.0.1.178 timeout x comment "text message 178" -2.0.1.179 timeout x comment "text message 179" -2.0.1.180 timeout x comment "text message 180" -2.0.1.181 timeout x comment "text message 181" -2.0.1.182 timeout x comment "text message 182" -2.0.1.183 timeout x comment "text message 183" -2.0.1.184 timeout x comment "text message 184" -2.0.1.185 timeout x comment "text message 185" -2.0.1.186 timeout x comment "text message 186" -2.0.1.187 timeout x comment "text message 187" -2.0.1.188 timeout x comment "text message 188" -2.0.1.189 timeout x comment "text message 189" -2.0.1.190 timeout x comment "text message 190" -2.0.1.191 timeout x comment "text message 191" -2.0.1.192 timeout x comment "text message 192" -2.0.1.193 timeout x comment "text message 193" -2.0.1.194 timeout x comment "text message 194" -2.0.1.195 timeout x comment "text message 195" -2.0.1.196 timeout x comment "text message 196" -2.0.1.197 timeout x comment "text message 197" -2.0.1.198 timeout x comment "text message 198" -2.0.1.199 timeout x comment "text message 199" -2.0.1.200 timeout x comment "text message 200" -2.0.1.201 timeout x comment "text message 201" -2.0.1.202 timeout x comment "text message 202" -2.0.1.203 timeout x comment "text message 203" -2.0.1.204 timeout x comment "text message 204" -2.0.1.205 timeout x comment "text message 205" -2.0.1.206 timeout x comment "text message 206" -2.0.1.207 timeout x comment "text message 207" -2.0.1.208 timeout x comment "text message 208" -2.0.1.209 timeout x comment "text message 209" -2.0.1.210 timeout x comment "text message 210" -2.0.1.211 timeout x comment "text message 211" -2.0.1.212 timeout x comment "text message 212" -2.0.1.213 timeout x comment "text message 213" -2.0.1.214 timeout x comment "text message 214" -2.0.1.215 timeout x comment "text message 215" -2.0.1.216 timeout x comment "text message 216" -2.0.1.217 timeout x comment "text message 217" -2.0.1.218 timeout x comment "text message 218" -2.0.1.219 timeout x comment "text message 219" -2.0.1.220 timeout x comment "text message 220" -2.0.1.221 timeout x comment "text message 221" -2.0.1.222 timeout x comment "text message 222" -2.0.1.223 timeout x comment "text message 223" -2.0.1.224 timeout x comment "text message 224" -2.0.1.225 timeout x comment "text message 225" -2.0.1.226 timeout x comment "text message 226" -2.0.1.227 timeout x comment "text message 227" -2.0.1.228 timeout x comment "text message 228" -2.0.1.229 timeout x comment "text message 229" -2.0.1.230 timeout x comment "text message 230" -2.0.1.231 timeout x comment "text message 231" -2.0.1.232 timeout x comment "text message 232" -2.0.1.233 timeout x comment "text message 233" -2.0.1.234 timeout x comment "text message 234" -2.0.1.235 timeout x comment "text message 235" -2.0.1.236 timeout x comment "text message 236" -2.0.1.237 timeout x comment "text message 237" -2.0.1.238 timeout x comment "text message 238" -2.0.1.239 timeout x comment "text message 239" -2.0.1.240 timeout x comment "text message 240" -2.0.1.241 timeout x comment "text message 241" -2.0.1.242 timeout x comment "text message 242" -2.0.1.243 timeout x comment "text message 243" -2.0.1.244 timeout x comment "text message 244" -2.0.1.245 timeout x comment "text message 245" -2.0.1.246 timeout x comment "text message 246" -2.0.1.247 timeout x comment "text message 247" -2.0.1.248 timeout x comment "text message 248" -2.0.1.249 timeout x comment "text message 249" -2.0.1.250 timeout x comment "text message 250" -2.0.1.251 timeout x comment "text message 251" -2.0.1.252 timeout x comment "text message 252" -2.0.1.253 timeout x comment "text message 253" -2.0.1.254 timeout x comment "text message 254" -2.0.1.255 timeout x comment "text message 255" +2.0.0.1 timeout 2 comment "text message 1" +2.0.0.2 timeout 2 comment "text message 2" +2.0.0.3 timeout 2 comment "text message 3" +2.0.0.4 timeout 2 comment "text message 4" +2.0.0.5 timeout 2 comment "text message 5" +2.0.0.6 timeout 2 comment "text message 6" +2.0.0.7 timeout 2 comment "text message 7" +2.0.0.8 timeout 2 comment "text message 8" +2.0.0.9 timeout 2 comment "text message 9" +2.0.0.10 timeout 2 comment "text message 10" +2.0.0.11 timeout 2 comment "text message 11" +2.0.0.12 timeout 2 comment "text message 12" +2.0.0.13 timeout 2 comment "text message 13" +2.0.0.14 timeout 2 comment "text message 14" +2.0.0.15 timeout 2 comment "text message 15" +2.0.0.16 timeout 2 comment "text message 16" +2.0.0.17 timeout 2 comment "text message 17" +2.0.0.18 timeout 2 comment "text message 18" +2.0.0.19 timeout 2 comment "text message 19" +2.0.0.20 timeout 2 comment "text message 20" +2.0.0.21 timeout 2 comment "text message 21" +2.0.0.22 timeout 2 comment "text message 22" +2.0.0.23 timeout 2 comment "text message 23" +2.0.0.24 timeout 2 comment "text message 24" +2.0.0.25 timeout 2 comment "text message 25" +2.0.0.26 timeout 2 comment "text message 26" +2.0.0.27 timeout 2 comment "text message 27" +2.0.0.28 timeout 2 comment "text message 28" +2.0.0.29 timeout 2 comment "text message 29" +2.0.0.30 timeout 2 comment "text message 30" +2.0.0.31 timeout 2 comment "text message 31" +2.0.0.32 timeout 2 comment "text message 32" +2.0.0.33 timeout 2 comment "text message 33" +2.0.0.34 timeout 2 comment "text message 34" +2.0.0.35 timeout 2 comment "text message 35" +2.0.0.36 timeout 2 comment "text message 36" +2.0.0.37 timeout 2 comment "text message 37" +2.0.0.38 timeout 2 comment "text message 38" +2.0.0.39 timeout 2 comment "text message 39" +2.0.0.40 timeout 2 comment "text message 40" +2.0.0.41 timeout 2 comment "text message 41" +2.0.0.42 timeout 2 comment "text message 42" +2.0.0.43 timeout 2 comment "text message 43" +2.0.0.44 timeout 2 comment "text message 44" +2.0.0.45 timeout 2 comment "text message 45" +2.0.0.46 timeout 2 comment "text message 46" +2.0.0.47 timeout 2 comment "text message 47" +2.0.0.48 timeout 2 comment "text message 48" +2.0.0.49 timeout 2 comment "text message 49" +2.0.0.50 timeout 2 comment "text message 50" +2.0.0.51 timeout 2 comment "text message 51" +2.0.0.52 timeout 2 comment "text message 52" +2.0.0.53 timeout 2 comment "text message 53" +2.0.0.54 timeout 2 comment "text message 54" +2.0.0.55 timeout 2 comment "text message 55" +2.0.0.56 timeout 2 comment "text message 56" +2.0.0.57 timeout 2 comment "text message 57" +2.0.0.58 timeout 2 comment "text message 58" +2.0.0.59 timeout 2 comment "text message 59" +2.0.0.60 timeout 2 comment "text message 60" +2.0.0.61 timeout 2 comment "text message 61" +2.0.0.62 timeout 2 comment "text message 62" +2.0.0.63 timeout 2 comment "text message 63" +2.0.0.64 timeout 2 comment "text message 64" +2.0.0.65 timeout 2 comment "text message 65" +2.0.0.66 timeout 2 comment "text message 66" +2.0.0.67 timeout 2 comment "text message 67" +2.0.0.68 timeout 2 comment "text message 68" +2.0.0.69 timeout 2 comment "text message 69" +2.0.0.70 timeout 2 comment "text message 70" +2.0.0.71 timeout 2 comment "text message 71" +2.0.0.72 timeout 2 comment "text message 72" +2.0.0.73 timeout 2 comment "text message 73" +2.0.0.74 timeout 2 comment "text message 74" +2.0.0.75 timeout 2 comment "text message 75" +2.0.0.76 timeout 2 comment "text message 76" +2.0.0.77 timeout 2 comment "text message 77" +2.0.0.78 timeout 2 comment "text message 78" +2.0.0.79 timeout 2 comment "text message 79" +2.0.0.80 timeout 2 comment "text message 80" +2.0.0.81 timeout 2 comment "text message 81" +2.0.0.82 timeout 2 comment "text message 82" +2.0.0.83 timeout 2 comment "text message 83" +2.0.0.84 timeout 2 comment "text message 84" +2.0.0.85 timeout 2 comment "text message 85" +2.0.0.86 timeout 2 comment "text message 86" +2.0.0.87 timeout 2 comment "text message 87" +2.0.0.88 timeout 2 comment "text message 88" +2.0.0.89 timeout 2 comment "text message 89" +2.0.0.90 timeout 2 comment "text message 90" +2.0.0.91 timeout 2 comment "text message 91" +2.0.0.92 timeout 2 comment "text message 92" +2.0.0.93 timeout 2 comment "text message 93" +2.0.0.94 timeout 2 comment "text message 94" +2.0.0.95 timeout 2 comment "text message 95" +2.0.0.96 timeout 2 comment "text message 96" +2.0.0.97 timeout 2 comment "text message 97" +2.0.0.98 timeout 2 comment "text message 98" +2.0.0.99 timeout 2 comment "text message 99" +2.0.0.100 timeout 2 comment "text message 100" +2.0.0.101 timeout 2 comment "text message 101" +2.0.0.102 timeout 2 comment "text message 102" +2.0.0.103 timeout 2 comment "text message 103" +2.0.0.104 timeout 2 comment "text message 104" +2.0.0.105 timeout 2 comment "text message 105" +2.0.0.106 timeout 2 comment "text message 106" +2.0.0.107 timeout 2 comment "text message 107" +2.0.0.108 timeout 2 comment "text message 108" +2.0.0.109 timeout 2 comment "text message 109" +2.0.0.110 timeout 2 comment "text message 110" +2.0.0.111 timeout 2 comment "text message 111" +2.0.0.112 timeout 2 comment "text message 112" +2.0.0.113 timeout 2 comment "text message 113" +2.0.0.114 timeout 2 comment "text message 114" +2.0.0.115 timeout 2 comment "text message 115" +2.0.0.116 timeout 2 comment "text message 116" +2.0.0.117 timeout 2 comment "text message 117" +2.0.0.118 timeout 2 comment "text message 118" +2.0.0.119 timeout 2 comment "text message 119" +2.0.0.120 timeout 2 comment "text message 120" +2.0.0.121 timeout 2 comment "text message 121" +2.0.0.122 timeout 2 comment "text message 122" +2.0.0.123 timeout 2 comment "text message 123" +2.0.0.124 timeout 2 comment "text message 124" +2.0.0.125 timeout 2 comment "text message 125" +2.0.0.126 timeout 2 comment "text message 126" +2.0.0.127 timeout 2 comment "text message 127" +2.0.0.128 timeout 2 comment "text message 128" +2.0.0.129 timeout 2 comment "text message 129" +2.0.0.130 timeout 2 comment "text message 130" +2.0.0.131 timeout 2 comment "text message 131" +2.0.0.132 timeout 2 comment "text message 132" +2.0.0.133 timeout 2 comment "text message 133" +2.0.0.134 timeout 2 comment "text message 134" +2.0.0.135 timeout 2 comment "text message 135" +2.0.0.136 timeout 2 comment "text message 136" +2.0.0.137 timeout 2 comment "text message 137" +2.0.0.138 timeout 2 comment "text message 138" +2.0.0.139 timeout 2 comment "text message 139" +2.0.0.140 timeout 2 comment "text message 140" +2.0.0.141 timeout 2 comment "text message 141" +2.0.0.142 timeout 2 comment "text message 142" +2.0.0.143 timeout 2 comment "text message 143" +2.0.0.144 timeout 2 comment "text message 144" +2.0.0.145 timeout 2 comment "text message 145" +2.0.0.146 timeout 2 comment "text message 146" +2.0.0.147 timeout 2 comment "text message 147" +2.0.0.148 timeout 2 comment "text message 148" +2.0.0.149 timeout 2 comment "text message 149" +2.0.0.150 timeout 2 comment "text message 150" +2.0.0.151 timeout 2 comment "text message 151" +2.0.0.152 timeout 2 comment "text message 152" +2.0.0.153 timeout 2 comment "text message 153" +2.0.0.154 timeout 2 comment "text message 154" +2.0.0.155 timeout 2 comment "text message 155" +2.0.0.156 timeout 2 comment "text message 156" +2.0.0.157 timeout 2 comment "text message 157" +2.0.0.158 timeout 2 comment "text message 158" +2.0.0.159 timeout 2 comment "text message 159" +2.0.0.160 timeout 2 comment "text message 160" +2.0.0.161 timeout 2 comment "text message 161" +2.0.0.162 timeout 2 comment "text message 162" +2.0.0.163 timeout 2 comment "text message 163" +2.0.0.164 timeout 2 comment "text message 164" +2.0.0.165 timeout 2 comment "text message 165" +2.0.0.166 timeout 2 comment "text message 166" +2.0.0.167 timeout 2 comment "text message 167" +2.0.0.168 timeout 2 comment "text message 168" +2.0.0.169 timeout 2 comment "text message 169" +2.0.0.170 timeout 2 comment "text message 170" +2.0.0.171 timeout 2 comment "text message 171" +2.0.0.172 timeout 2 comment "text message 172" +2.0.0.173 timeout 2 comment "text message 173" +2.0.0.174 timeout 2 comment "text message 174" +2.0.0.175 timeout 2 comment "text message 175" +2.0.0.176 timeout 2 comment "text message 176" +2.0.0.177 timeout 2 comment "text message 177" +2.0.0.178 timeout 2 comment "text message 178" +2.0.0.179 timeout 2 comment "text message 179" +2.0.0.180 timeout 2 comment "text message 180" +2.0.0.181 timeout 2 comment "text message 181" +2.0.0.182 timeout 2 comment "text message 182" +2.0.0.183 timeout 2 comment "text message 183" +2.0.0.184 timeout 2 comment "text message 184" +2.0.0.185 timeout 2 comment "text message 185" +2.0.0.186 timeout 2 comment "text message 186" +2.0.0.187 timeout 2 comment "text message 187" +2.0.0.188 timeout 2 comment "text message 188" +2.0.0.189 timeout 2 comment "text message 189" +2.0.0.190 timeout 2 comment "text message 190" +2.0.0.191 timeout 2 comment "text message 191" +2.0.0.192 timeout 2 comment "text message 192" +2.0.0.193 timeout 2 comment "text message 193" +2.0.0.194 timeout 2 comment "text message 194" +2.0.0.195 timeout 2 comment "text message 195" +2.0.0.196 timeout 2 comment "text message 196" +2.0.0.197 timeout 2 comment "text message 197" +2.0.0.198 timeout 2 comment "text message 198" +2.0.0.199 timeout 2 comment "text message 199" +2.0.0.200 timeout 2 comment "text message 200" +2.0.0.201 timeout 2 comment "text message 201" +2.0.0.202 timeout 2 comment "text message 202" +2.0.0.203 timeout 2 comment "text message 203" +2.0.0.204 timeout 2 comment "text message 204" +2.0.0.205 timeout 2 comment "text message 205" +2.0.0.206 timeout 2 comment "text message 206" +2.0.0.207 timeout 2 comment "text message 207" +2.0.0.208 timeout 2 comment "text message 208" +2.0.0.209 timeout 2 comment "text message 209" +2.0.0.210 timeout 2 comment "text message 210" +2.0.0.211 timeout 2 comment "text message 211" +2.0.0.212 timeout 2 comment "text message 212" +2.0.0.213 timeout 2 comment "text message 213" +2.0.0.214 timeout 2 comment "text message 214" +2.0.0.215 timeout 2 comment "text message 215" +2.0.0.216 timeout 2 comment "text message 216" +2.0.0.217 timeout 2 comment "text message 217" +2.0.0.218 timeout 2 comment "text message 218" +2.0.0.219 timeout 2 comment "text message 219" +2.0.0.220 timeout 2 comment "text message 220" +2.0.0.221 timeout 2 comment "text message 221" +2.0.0.222 timeout 2 comment "text message 222" +2.0.0.223 timeout 2 comment "text message 223" +2.0.0.224 timeout 2 comment "text message 224" +2.0.0.225 timeout 2 comment "text message 225" +2.0.0.226 timeout 2 comment "text message 226" +2.0.0.227 timeout 2 comment "text message 227" +2.0.0.228 timeout 2 comment "text message 228" +2.0.0.229 timeout 2 comment "text message 229" +2.0.0.230 timeout 2 comment "text message 230" +2.0.0.231 timeout 2 comment "text message 231" +2.0.0.232 timeout 2 comment "text message 232" +2.0.0.233 timeout 2 comment "text message 233" +2.0.0.234 timeout 2 comment "text message 234" +2.0.0.235 timeout 2 comment "text message 235" +2.0.0.236 timeout 2 comment "text message 236" +2.0.0.237 timeout 2 comment "text message 237" +2.0.0.238 timeout 2 comment "text message 238" +2.0.0.239 timeout 2 comment "text message 239" +2.0.0.240 timeout 2 comment "text message 240" +2.0.0.241 timeout 2 comment "text message 241" +2.0.0.242 timeout 2 comment "text message 242" +2.0.0.243 timeout 2 comment "text message 243" +2.0.0.244 timeout 2 comment "text message 244" +2.0.0.245 timeout 2 comment "text message 245" +2.0.0.246 timeout 2 comment "text message 246" +2.0.0.247 timeout 2 comment "text message 247" +2.0.0.248 timeout 2 comment "text message 248" +2.0.0.249 timeout 2 comment "text message 249" +2.0.0.250 timeout 2 comment "text message 250" +2.0.0.251 timeout 2 comment "text message 251" +2.0.0.252 timeout 2 comment "text message 252" +2.0.0.253 timeout 2 comment "text message 253" +2.0.0.254 timeout 2 comment "text message 254" +2.0.0.255 timeout 2 comment "text message 255" +2.0.1.1 timeout 0 comment "text message 1" +2.0.1.2 timeout 0 comment "text message 2" +2.0.1.3 timeout 0 comment "text message 3" +2.0.1.4 timeout 0 comment "text message 4" +2.0.1.5 timeout 0 comment "text message 5" +2.0.1.6 timeout 0 comment "text message 6" +2.0.1.7 timeout 0 comment "text message 7" +2.0.1.8 timeout 0 comment "text message 8" +2.0.1.9 timeout 0 comment "text message 9" +2.0.1.10 timeout 0 comment "text message 10" +2.0.1.11 timeout 0 comment "text message 11" +2.0.1.12 timeout 0 comment "text message 12" +2.0.1.13 timeout 0 comment "text message 13" +2.0.1.14 timeout 0 comment "text message 14" +2.0.1.15 timeout 0 comment "text message 15" +2.0.1.16 timeout 0 comment "text message 16" +2.0.1.17 timeout 0 comment "text message 17" +2.0.1.18 timeout 0 comment "text message 18" +2.0.1.19 timeout 0 comment "text message 19" +2.0.1.20 timeout 0 comment "text message 20" +2.0.1.21 timeout 0 comment "text message 21" +2.0.1.22 timeout 0 comment "text message 22" +2.0.1.23 timeout 0 comment "text message 23" +2.0.1.24 timeout 0 comment "text message 24" +2.0.1.25 timeout 0 comment "text message 25" +2.0.1.26 timeout 0 comment "text message 26" +2.0.1.27 timeout 0 comment "text message 27" +2.0.1.28 timeout 0 comment "text message 28" +2.0.1.29 timeout 0 comment "text message 29" +2.0.1.30 timeout 0 comment "text message 30" +2.0.1.31 timeout 0 comment "text message 31" +2.0.1.32 timeout 0 comment "text message 32" +2.0.1.33 timeout 0 comment "text message 33" +2.0.1.34 timeout 0 comment "text message 34" +2.0.1.35 timeout 0 comment "text message 35" +2.0.1.36 timeout 0 comment "text message 36" +2.0.1.37 timeout 0 comment "text message 37" +2.0.1.38 timeout 0 comment "text message 38" +2.0.1.39 timeout 0 comment "text message 39" +2.0.1.40 timeout 0 comment "text message 40" +2.0.1.41 timeout 0 comment "text message 41" +2.0.1.42 timeout 0 comment "text message 42" +2.0.1.43 timeout 0 comment "text message 43" +2.0.1.44 timeout 0 comment "text message 44" +2.0.1.45 timeout 0 comment "text message 45" +2.0.1.46 timeout 0 comment "text message 46" +2.0.1.47 timeout 0 comment "text message 47" +2.0.1.48 timeout 0 comment "text message 48" +2.0.1.49 timeout 0 comment "text message 49" +2.0.1.50 timeout 0 comment "text message 50" +2.0.1.51 timeout 0 comment "text message 51" +2.0.1.52 timeout 0 comment "text message 52" +2.0.1.53 timeout 0 comment "text message 53" +2.0.1.54 timeout 0 comment "text message 54" +2.0.1.55 timeout 0 comment "text message 55" +2.0.1.56 timeout 0 comment "text message 56" +2.0.1.57 timeout 0 comment "text message 57" +2.0.1.58 timeout 0 comment "text message 58" +2.0.1.59 timeout 0 comment "text message 59" +2.0.1.60 timeout 0 comment "text message 60" +2.0.1.61 timeout 0 comment "text message 61" +2.0.1.62 timeout 0 comment "text message 62" +2.0.1.63 timeout 0 comment "text message 63" +2.0.1.64 timeout 0 comment "text message 64" +2.0.1.65 timeout 0 comment "text message 65" +2.0.1.66 timeout 0 comment "text message 66" +2.0.1.67 timeout 0 comment "text message 67" +2.0.1.68 timeout 0 comment "text message 68" +2.0.1.69 timeout 0 comment "text message 69" +2.0.1.70 timeout 0 comment "text message 70" +2.0.1.71 timeout 0 comment "text message 71" +2.0.1.72 timeout 0 comment "text message 72" +2.0.1.73 timeout 0 comment "text message 73" +2.0.1.74 timeout 0 comment "text message 74" +2.0.1.75 timeout 0 comment "text message 75" +2.0.1.76 timeout 0 comment "text message 76" +2.0.1.77 timeout 0 comment "text message 77" +2.0.1.78 timeout 0 comment "text message 78" +2.0.1.79 timeout 0 comment "text message 79" +2.0.1.80 timeout 0 comment "text message 80" +2.0.1.81 timeout 0 comment "text message 81" +2.0.1.82 timeout 0 comment "text message 82" +2.0.1.83 timeout 0 comment "text message 83" +2.0.1.84 timeout 0 comment "text message 84" +2.0.1.85 timeout 0 comment "text message 85" +2.0.1.86 timeout 0 comment "text message 86" +2.0.1.87 timeout 0 comment "text message 87" +2.0.1.88 timeout 0 comment "text message 88" +2.0.1.89 timeout 0 comment "text message 89" +2.0.1.90 timeout 0 comment "text message 90" +2.0.1.91 timeout 0 comment "text message 91" +2.0.1.92 timeout 0 comment "text message 92" +2.0.1.93 timeout 0 comment "text message 93" +2.0.1.94 timeout 0 comment "text message 94" +2.0.1.95 timeout 0 comment "text message 95" +2.0.1.96 timeout 0 comment "text message 96" +2.0.1.97 timeout 0 comment "text message 97" +2.0.1.98 timeout 0 comment "text message 98" +2.0.1.99 timeout 0 comment "text message 99" +2.0.1.100 timeout 0 comment "text message 100" +2.0.1.101 timeout 0 comment "text message 101" +2.0.1.102 timeout 0 comment "text message 102" +2.0.1.103 timeout 0 comment "text message 103" +2.0.1.104 timeout 0 comment "text message 104" +2.0.1.105 timeout 0 comment "text message 105" +2.0.1.106 timeout 0 comment "text message 106" +2.0.1.107 timeout 0 comment "text message 107" +2.0.1.108 timeout 0 comment "text message 108" +2.0.1.109 timeout 0 comment "text message 109" +2.0.1.110 timeout 0 comment "text message 110" +2.0.1.111 timeout 0 comment "text message 111" +2.0.1.112 timeout 0 comment "text message 112" +2.0.1.113 timeout 0 comment "text message 113" +2.0.1.114 timeout 0 comment "text message 114" +2.0.1.115 timeout 0 comment "text message 115" +2.0.1.116 timeout 0 comment "text message 116" +2.0.1.117 timeout 0 comment "text message 117" +2.0.1.118 timeout 0 comment "text message 118" +2.0.1.119 timeout 0 comment "text message 119" +2.0.1.120 timeout 0 comment "text message 120" +2.0.1.121 timeout 0 comment "text message 121" +2.0.1.122 timeout 0 comment "text message 122" +2.0.1.123 timeout 0 comment "text message 123" +2.0.1.124 timeout 0 comment "text message 124" +2.0.1.125 timeout 0 comment "text message 125" +2.0.1.126 timeout 0 comment "text message 126" +2.0.1.127 timeout 0 comment "text message 127" +2.0.1.128 timeout 0 comment "text message 128" +2.0.1.129 timeout 0 comment "text message 129" +2.0.1.130 timeout 0 comment "text message 130" +2.0.1.131 timeout 0 comment "text message 131" +2.0.1.132 timeout 0 comment "text message 132" +2.0.1.133 timeout 0 comment "text message 133" +2.0.1.134 timeout 0 comment "text message 134" +2.0.1.135 timeout 0 comment "text message 135" +2.0.1.136 timeout 0 comment "text message 136" +2.0.1.137 timeout 0 comment "text message 137" +2.0.1.138 timeout 0 comment "text message 138" +2.0.1.139 timeout 0 comment "text message 139" +2.0.1.140 timeout 0 comment "text message 140" +2.0.1.141 timeout 0 comment "text message 141" +2.0.1.142 timeout 0 comment "text message 142" +2.0.1.143 timeout 0 comment "text message 143" +2.0.1.144 timeout 0 comment "text message 144" +2.0.1.145 timeout 0 comment "text message 145" +2.0.1.146 timeout 0 comment "text message 146" +2.0.1.147 timeout 0 comment "text message 147" +2.0.1.148 timeout 0 comment "text message 148" +2.0.1.149 timeout 0 comment "text message 149" +2.0.1.150 timeout 0 comment "text message 150" +2.0.1.151 timeout 0 comment "text message 151" +2.0.1.152 timeout 0 comment "text message 152" +2.0.1.153 timeout 0 comment "text message 153" +2.0.1.154 timeout 0 comment "text message 154" +2.0.1.155 timeout 0 comment "text message 155" +2.0.1.156 timeout 0 comment "text message 156" +2.0.1.157 timeout 0 comment "text message 157" +2.0.1.158 timeout 0 comment "text message 158" +2.0.1.159 timeout 0 comment "text message 159" +2.0.1.160 timeout 0 comment "text message 160" +2.0.1.161 timeout 0 comment "text message 161" +2.0.1.162 timeout 0 comment "text message 162" +2.0.1.163 timeout 0 comment "text message 163" +2.0.1.164 timeout 0 comment "text message 164" +2.0.1.165 timeout 0 comment "text message 165" +2.0.1.166 timeout 0 comment "text message 166" +2.0.1.167 timeout 0 comment "text message 167" +2.0.1.168 timeout 0 comment "text message 168" +2.0.1.169 timeout 0 comment "text message 169" +2.0.1.170 timeout 0 comment "text message 170" +2.0.1.171 timeout 0 comment "text message 171" +2.0.1.172 timeout 0 comment "text message 172" +2.0.1.173 timeout 0 comment "text message 173" +2.0.1.174 timeout 0 comment "text message 174" +2.0.1.175 timeout 0 comment "text message 175" +2.0.1.176 timeout 0 comment "text message 176" +2.0.1.177 timeout 0 comment "text message 177" +2.0.1.178 timeout 0 comment "text message 178" +2.0.1.179 timeout 0 comment "text message 179" +2.0.1.180 timeout 0 comment "text message 180" +2.0.1.181 timeout 0 comment "text message 181" +2.0.1.182 timeout 0 comment "text message 182" +2.0.1.183 timeout 0 comment "text message 183" +2.0.1.184 timeout 0 comment "text message 184" +2.0.1.185 timeout 0 comment "text message 185" +2.0.1.186 timeout 0 comment "text message 186" +2.0.1.187 timeout 0 comment "text message 187" +2.0.1.188 timeout 0 comment "text message 188" +2.0.1.189 timeout 0 comment "text message 189" +2.0.1.190 timeout 0 comment "text message 190" +2.0.1.191 timeout 0 comment "text message 191" +2.0.1.192 timeout 0 comment "text message 192" +2.0.1.193 timeout 0 comment "text message 193" +2.0.1.194 timeout 0 comment "text message 194" +2.0.1.195 timeout 0 comment "text message 195" +2.0.1.196 timeout 0 comment "text message 196" +2.0.1.197 timeout 0 comment "text message 197" +2.0.1.198 timeout 0 comment "text message 198" +2.0.1.199 timeout 0 comment "text message 199" +2.0.1.200 timeout 0 comment "text message 200" +2.0.1.201 timeout 0 comment "text message 201" +2.0.1.202 timeout 0 comment "text message 202" +2.0.1.203 timeout 0 comment "text message 203" +2.0.1.204 timeout 0 comment "text message 204" +2.0.1.205 timeout 0 comment "text message 205" +2.0.1.206 timeout 0 comment "text message 206" +2.0.1.207 timeout 0 comment "text message 207" +2.0.1.208 timeout 0 comment "text message 208" +2.0.1.209 timeout 0 comment "text message 209" +2.0.1.210 timeout 0 comment "text message 210" +2.0.1.211 timeout 0 comment "text message 211" +2.0.1.212 timeout 0 comment "text message 212" +2.0.1.213 timeout 0 comment "text message 213" +2.0.1.214 timeout 0 comment "text message 214" +2.0.1.215 timeout 0 comment "text message 215" +2.0.1.216 timeout 0 comment "text message 216" +2.0.1.217 timeout 0 comment "text message 217" +2.0.1.218 timeout 0 comment "text message 218" +2.0.1.219 timeout 0 comment "text message 219" +2.0.1.220 timeout 0 comment "text message 220" +2.0.1.221 timeout 0 comment "text message 221" +2.0.1.222 timeout 0 comment "text message 222" +2.0.1.223 timeout 0 comment "text message 223" +2.0.1.224 timeout 0 comment "text message 224" +2.0.1.225 timeout 0 comment "text message 225" +2.0.1.226 timeout 0 comment "text message 226" +2.0.1.227 timeout 0 comment "text message 227" +2.0.1.228 timeout 0 comment "text message 228" +2.0.1.229 timeout 0 comment "text message 229" +2.0.1.230 timeout 0 comment "text message 230" +2.0.1.231 timeout 0 comment "text message 231" +2.0.1.232 timeout 0 comment "text message 232" +2.0.1.233 timeout 0 comment "text message 233" +2.0.1.234 timeout 0 comment "text message 234" +2.0.1.235 timeout 0 comment "text message 235" +2.0.1.236 timeout 0 comment "text message 236" +2.0.1.237 timeout 0 comment "text message 237" +2.0.1.238 timeout 0 comment "text message 238" +2.0.1.239 timeout 0 comment "text message 239" +2.0.1.240 timeout 0 comment "text message 240" +2.0.1.241 timeout 0 comment "text message 241" +2.0.1.242 timeout 0 comment "text message 242" +2.0.1.243 timeout 0 comment "text message 243" +2.0.1.244 timeout 0 comment "text message 244" +2.0.1.245 timeout 0 comment "text message 245" +2.0.1.246 timeout 0 comment "text message 246" +2.0.1.247 timeout 0 comment "text message 247" +2.0.1.248 timeout 0 comment "text message 248" +2.0.1.249 timeout 0 comment "text message 249" +2.0.1.250 timeout 0 comment "text message 250" +2.0.1.251 timeout 0 comment "text message 251" +2.0.1.252 timeout 0 comment "text message 252" +2.0.1.253 timeout 0 comment "text message 253" +2.0.1.254 timeout 0 comment "text message 254" +2.0.1.255 timeout 0 comment "text message 255" diff --git a/tests/comment.t.list12 b/tests/comment.t.list12 index 9440b75..202c841 100644 --- a/tests/comment.t.list12 +++ b/tests/comment.t.list12 @@ -1,262 +1,263 @@ Name: test Type: bitmap:ip -Header: range 2.0.0.1-2.1.0.0 timeout x comment -Size in memory: 1056928 +Revision: 3 +Header: range 2.0.0.1-2.1.0.0 timeout 3 comment +Size in memory: 1065203 References: 0 -Number of entries: 510 +Number of entries: 255 Members: -2.0.1.1 timeout x comment "text message 1" -2.0.1.2 timeout x comment "text message 2" -2.0.1.3 timeout x comment "text message 3" -2.0.1.4 timeout x comment "text message 4" -2.0.1.5 timeout x comment "text message 5" -2.0.1.6 timeout x comment "text message 6" -2.0.1.7 timeout x comment "text message 7" -2.0.1.8 timeout x comment "text message 8" -2.0.1.9 timeout x comment "text message 9" -2.0.1.10 timeout x comment "text message 10" -2.0.1.11 timeout x comment "text message 11" -2.0.1.12 timeout x comment "text message 12" -2.0.1.13 timeout x comment "text message 13" -2.0.1.14 timeout x comment "text message 14" -2.0.1.15 timeout x comment "text message 15" -2.0.1.16 timeout x comment "text message 16" -2.0.1.17 timeout x comment "text message 17" -2.0.1.18 timeout x comment "text message 18" -2.0.1.19 timeout x comment "text message 19" -2.0.1.20 timeout x comment "text message 20" -2.0.1.21 timeout x comment "text message 21" -2.0.1.22 timeout x comment "text message 22" -2.0.1.23 timeout x comment "text message 23" -2.0.1.24 timeout x comment "text message 24" -2.0.1.25 timeout x comment "text message 25" -2.0.1.26 timeout x comment "text message 26" -2.0.1.27 timeout x comment "text message 27" -2.0.1.28 timeout x comment "text message 28" -2.0.1.29 timeout x comment "text message 29" -2.0.1.30 timeout x comment "text message 30" -2.0.1.31 timeout x comment "text message 31" -2.0.1.32 timeout x comment "text message 32" -2.0.1.33 timeout x comment "text message 33" -2.0.1.34 timeout x comment "text message 34" -2.0.1.35 timeout x comment "text message 35" -2.0.1.36 timeout x comment "text message 36" -2.0.1.37 timeout x comment "text message 37" -2.0.1.38 timeout x comment "text message 38" -2.0.1.39 timeout x comment "text message 39" -2.0.1.40 timeout x comment "text message 40" -2.0.1.41 timeout x comment "text message 41" -2.0.1.42 timeout x comment "text message 42" -2.0.1.43 timeout x comment "text message 43" -2.0.1.44 timeout x comment "text message 44" -2.0.1.45 timeout x comment "text message 45" -2.0.1.46 timeout x comment "text message 46" -2.0.1.47 timeout x comment "text message 47" -2.0.1.48 timeout x comment "text message 48" -2.0.1.49 timeout x comment "text message 49" -2.0.1.50 timeout x comment "text message 50" -2.0.1.51 timeout x comment "text message 51" -2.0.1.52 timeout x comment "text message 52" -2.0.1.53 timeout x comment "text message 53" -2.0.1.54 timeout x comment "text message 54" -2.0.1.55 timeout x comment "text message 55" -2.0.1.56 timeout x comment "text message 56" -2.0.1.57 timeout x comment "text message 57" -2.0.1.58 timeout x comment "text message 58" -2.0.1.59 timeout x comment "text message 59" -2.0.1.60 timeout x comment "text message 60" -2.0.1.61 timeout x comment "text message 61" -2.0.1.62 timeout x comment "text message 62" -2.0.1.63 timeout x comment "text message 63" -2.0.1.64 timeout x comment "text message 64" -2.0.1.65 timeout x comment "text message 65" -2.0.1.66 timeout x comment "text message 66" -2.0.1.67 timeout x comment "text message 67" -2.0.1.68 timeout x comment "text message 68" -2.0.1.69 timeout x comment "text message 69" -2.0.1.70 timeout x comment "text message 70" -2.0.1.71 timeout x comment "text message 71" -2.0.1.72 timeout x comment "text message 72" -2.0.1.73 timeout x comment "text message 73" -2.0.1.74 timeout x comment "text message 74" -2.0.1.75 timeout x comment "text message 75" -2.0.1.76 timeout x comment "text message 76" -2.0.1.77 timeout x comment "text message 77" -2.0.1.78 timeout x comment "text message 78" -2.0.1.79 timeout x comment "text message 79" -2.0.1.80 timeout x comment "text message 80" -2.0.1.81 timeout x comment "text message 81" -2.0.1.82 timeout x comment "text message 82" -2.0.1.83 timeout x comment "text message 83" -2.0.1.84 timeout x comment "text message 84" -2.0.1.85 timeout x comment "text message 85" -2.0.1.86 timeout x comment "text message 86" -2.0.1.87 timeout x comment "text message 87" -2.0.1.88 timeout x comment "text message 88" -2.0.1.89 timeout x comment "text message 89" -2.0.1.90 timeout x comment "text message 90" -2.0.1.91 timeout x comment "text message 91" -2.0.1.92 timeout x comment "text message 92" -2.0.1.93 timeout x comment "text message 93" -2.0.1.94 timeout x comment "text message 94" -2.0.1.95 timeout x comment "text message 95" -2.0.1.96 timeout x comment "text message 96" -2.0.1.97 timeout x comment "text message 97" -2.0.1.98 timeout x comment "text message 98" -2.0.1.99 timeout x comment "text message 99" -2.0.1.100 timeout x comment "text message 100" -2.0.1.101 timeout x comment "text message 101" -2.0.1.102 timeout x comment "text message 102" -2.0.1.103 timeout x comment "text message 103" -2.0.1.104 timeout x comment "text message 104" -2.0.1.105 timeout x comment "text message 105" -2.0.1.106 timeout x comment "text message 106" -2.0.1.107 timeout x comment "text message 107" -2.0.1.108 timeout x comment "text message 108" -2.0.1.109 timeout x comment "text message 109" -2.0.1.110 timeout x comment "text message 110" -2.0.1.111 timeout x comment "text message 111" -2.0.1.112 timeout x comment "text message 112" -2.0.1.113 timeout x comment "text message 113" -2.0.1.114 timeout x comment "text message 114" -2.0.1.115 timeout x comment "text message 115" -2.0.1.116 timeout x comment "text message 116" -2.0.1.117 timeout x comment "text message 117" -2.0.1.118 timeout x comment "text message 118" -2.0.1.119 timeout x comment "text message 119" -2.0.1.120 timeout x comment "text message 120" -2.0.1.121 timeout x comment "text message 121" -2.0.1.122 timeout x comment "text message 122" -2.0.1.123 timeout x comment "text message 123" -2.0.1.124 timeout x comment "text message 124" -2.0.1.125 timeout x comment "text message 125" -2.0.1.126 timeout x comment "text message 126" -2.0.1.127 timeout x comment "text message 127" -2.0.1.128 timeout x comment "text message 128" -2.0.1.129 timeout x comment "text message 129" -2.0.1.130 timeout x comment "text message 130" -2.0.1.131 timeout x comment "text message 131" -2.0.1.132 timeout x comment "text message 132" -2.0.1.133 timeout x comment "text message 133" -2.0.1.134 timeout x comment "text message 134" -2.0.1.135 timeout x comment "text message 135" -2.0.1.136 timeout x comment "text message 136" -2.0.1.137 timeout x comment "text message 137" -2.0.1.138 timeout x comment "text message 138" -2.0.1.139 timeout x comment "text message 139" -2.0.1.140 timeout x comment "text message 140" -2.0.1.141 timeout x comment "text message 141" -2.0.1.142 timeout x comment "text message 142" -2.0.1.143 timeout x comment "text message 143" -2.0.1.144 timeout x comment "text message 144" -2.0.1.145 timeout x comment "text message 145" -2.0.1.146 timeout x comment "text message 146" -2.0.1.147 timeout x comment "text message 147" -2.0.1.148 timeout x comment "text message 148" -2.0.1.149 timeout x comment "text message 149" -2.0.1.150 timeout x comment "text message 150" -2.0.1.151 timeout x comment "text message 151" -2.0.1.152 timeout x comment "text message 152" -2.0.1.153 timeout x comment "text message 153" -2.0.1.154 timeout x comment "text message 154" -2.0.1.155 timeout x comment "text message 155" -2.0.1.156 timeout x comment "text message 156" -2.0.1.157 timeout x comment "text message 157" -2.0.1.158 timeout x comment "text message 158" -2.0.1.159 timeout x comment "text message 159" -2.0.1.160 timeout x comment "text message 160" -2.0.1.161 timeout x comment "text message 161" -2.0.1.162 timeout x comment "text message 162" -2.0.1.163 timeout x comment "text message 163" -2.0.1.164 timeout x comment "text message 164" -2.0.1.165 timeout x comment "text message 165" -2.0.1.166 timeout x comment "text message 166" -2.0.1.167 timeout x comment "text message 167" -2.0.1.168 timeout x comment "text message 168" -2.0.1.169 timeout x comment "text message 169" -2.0.1.170 timeout x comment "text message 170" -2.0.1.171 timeout x comment "text message 171" -2.0.1.172 timeout x comment "text message 172" -2.0.1.173 timeout x comment "text message 173" -2.0.1.174 timeout x comment "text message 174" -2.0.1.175 timeout x comment "text message 175" -2.0.1.176 timeout x comment "text message 176" -2.0.1.177 timeout x comment "text message 177" -2.0.1.178 timeout x comment "text message 178" -2.0.1.179 timeout x comment "text message 179" -2.0.1.180 timeout x comment "text message 180" -2.0.1.181 timeout x comment "text message 181" -2.0.1.182 timeout x comment "text message 182" -2.0.1.183 timeout x comment "text message 183" -2.0.1.184 timeout x comment "text message 184" -2.0.1.185 timeout x comment "text message 185" -2.0.1.186 timeout x comment "text message 186" -2.0.1.187 timeout x comment "text message 187" -2.0.1.188 timeout x comment "text message 188" -2.0.1.189 timeout x comment "text message 189" -2.0.1.190 timeout x comment "text message 190" -2.0.1.191 timeout x comment "text message 191" -2.0.1.192 timeout x comment "text message 192" -2.0.1.193 timeout x comment "text message 193" -2.0.1.194 timeout x comment "text message 194" -2.0.1.195 timeout x comment "text message 195" -2.0.1.196 timeout x comment "text message 196" -2.0.1.197 timeout x comment "text message 197" -2.0.1.198 timeout x comment "text message 198" -2.0.1.199 timeout x comment "text message 199" -2.0.1.200 timeout x comment "text message 200" -2.0.1.201 timeout x comment "text message 201" -2.0.1.202 timeout x comment "text message 202" -2.0.1.203 timeout x comment "text message 203" -2.0.1.204 timeout x comment "text message 204" -2.0.1.205 timeout x comment "text message 205" -2.0.1.206 timeout x comment "text message 206" -2.0.1.207 timeout x comment "text message 207" -2.0.1.208 timeout x comment "text message 208" -2.0.1.209 timeout x comment "text message 209" -2.0.1.210 timeout x comment "text message 210" -2.0.1.211 timeout x comment "text message 211" -2.0.1.212 timeout x comment "text message 212" -2.0.1.213 timeout x comment "text message 213" -2.0.1.214 timeout x comment "text message 214" -2.0.1.215 timeout x comment "text message 215" -2.0.1.216 timeout x comment "text message 216" -2.0.1.217 timeout x comment "text message 217" -2.0.1.218 timeout x comment "text message 218" -2.0.1.219 timeout x comment "text message 219" -2.0.1.220 timeout x comment "text message 220" -2.0.1.221 timeout x comment "text message 221" -2.0.1.222 timeout x comment "text message 222" -2.0.1.223 timeout x comment "text message 223" -2.0.1.224 timeout x comment "text message 224" -2.0.1.225 timeout x comment "text message 225" -2.0.1.226 timeout x comment "text message 226" -2.0.1.227 timeout x comment "text message 227" -2.0.1.228 timeout x comment "text message 228" -2.0.1.229 timeout x comment "text message 229" -2.0.1.230 timeout x comment "text message 230" -2.0.1.231 timeout x comment "text message 231" -2.0.1.232 timeout x comment "text message 232" -2.0.1.233 timeout x comment "text message 233" -2.0.1.234 timeout x comment "text message 234" -2.0.1.235 timeout x comment "text message 235" -2.0.1.236 timeout x comment "text message 236" -2.0.1.237 timeout x comment "text message 237" -2.0.1.238 timeout x comment "text message 238" -2.0.1.239 timeout x comment "text message 239" -2.0.1.240 timeout x comment "text message 240" -2.0.1.241 timeout x comment "text message 241" -2.0.1.242 timeout x comment "text message 242" -2.0.1.243 timeout x comment "text message 243" -2.0.1.244 timeout x comment "text message 244" -2.0.1.245 timeout x comment "text message 245" -2.0.1.246 timeout x comment "text message 246" -2.0.1.247 timeout x comment "text message 247" -2.0.1.248 timeout x comment "text message 248" -2.0.1.249 timeout x comment "text message 249" -2.0.1.250 timeout x comment "text message 250" -2.0.1.251 timeout x comment "text message 251" -2.0.1.252 timeout x comment "text message 252" -2.0.1.253 timeout x comment "text message 253" -2.0.1.254 timeout x comment "text message 254" -2.0.1.255 timeout x comment "text message 255" +2.0.1.1 timeout 0 comment "text message 1" +2.0.1.2 timeout 0 comment "text message 2" +2.0.1.3 timeout 0 comment "text message 3" +2.0.1.4 timeout 0 comment "text message 4" +2.0.1.5 timeout 0 comment "text message 5" +2.0.1.6 timeout 0 comment "text message 6" +2.0.1.7 timeout 0 comment "text message 7" +2.0.1.8 timeout 0 comment "text message 8" +2.0.1.9 timeout 0 comment "text message 9" +2.0.1.10 timeout 0 comment "text message 10" +2.0.1.11 timeout 0 comment "text message 11" +2.0.1.12 timeout 0 comment "text message 12" +2.0.1.13 timeout 0 comment "text message 13" +2.0.1.14 timeout 0 comment "text message 14" +2.0.1.15 timeout 0 comment "text message 15" +2.0.1.16 timeout 0 comment "text message 16" +2.0.1.17 timeout 0 comment "text message 17" +2.0.1.18 timeout 0 comment "text message 18" +2.0.1.19 timeout 0 comment "text message 19" +2.0.1.20 timeout 0 comment "text message 20" +2.0.1.21 timeout 0 comment "text message 21" +2.0.1.22 timeout 0 comment "text message 22" +2.0.1.23 timeout 0 comment "text message 23" +2.0.1.24 timeout 0 comment "text message 24" +2.0.1.25 timeout 0 comment "text message 25" +2.0.1.26 timeout 0 comment "text message 26" +2.0.1.27 timeout 0 comment "text message 27" +2.0.1.28 timeout 0 comment "text message 28" +2.0.1.29 timeout 0 comment "text message 29" +2.0.1.30 timeout 0 comment "text message 30" +2.0.1.31 timeout 0 comment "text message 31" +2.0.1.32 timeout 0 comment "text message 32" +2.0.1.33 timeout 0 comment "text message 33" +2.0.1.34 timeout 0 comment "text message 34" +2.0.1.35 timeout 0 comment "text message 35" +2.0.1.36 timeout 0 comment "text message 36" +2.0.1.37 timeout 0 comment "text message 37" +2.0.1.38 timeout 0 comment "text message 38" +2.0.1.39 timeout 0 comment "text message 39" +2.0.1.40 timeout 0 comment "text message 40" +2.0.1.41 timeout 0 comment "text message 41" +2.0.1.42 timeout 0 comment "text message 42" +2.0.1.43 timeout 0 comment "text message 43" +2.0.1.44 timeout 0 comment "text message 44" +2.0.1.45 timeout 0 comment "text message 45" +2.0.1.46 timeout 0 comment "text message 46" +2.0.1.47 timeout 0 comment "text message 47" +2.0.1.48 timeout 0 comment "text message 48" +2.0.1.49 timeout 0 comment "text message 49" +2.0.1.50 timeout 0 comment "text message 50" +2.0.1.51 timeout 0 comment "text message 51" +2.0.1.52 timeout 0 comment "text message 52" +2.0.1.53 timeout 0 comment "text message 53" +2.0.1.54 timeout 0 comment "text message 54" +2.0.1.55 timeout 0 comment "text message 55" +2.0.1.56 timeout 0 comment "text message 56" +2.0.1.57 timeout 0 comment "text message 57" +2.0.1.58 timeout 0 comment "text message 58" +2.0.1.59 timeout 0 comment "text message 59" +2.0.1.60 timeout 0 comment "text message 60" +2.0.1.61 timeout 0 comment "text message 61" +2.0.1.62 timeout 0 comment "text message 62" +2.0.1.63 timeout 0 comment "text message 63" +2.0.1.64 timeout 0 comment "text message 64" +2.0.1.65 timeout 0 comment "text message 65" +2.0.1.66 timeout 0 comment "text message 66" +2.0.1.67 timeout 0 comment "text message 67" +2.0.1.68 timeout 0 comment "text message 68" +2.0.1.69 timeout 0 comment "text message 69" +2.0.1.70 timeout 0 comment "text message 70" +2.0.1.71 timeout 0 comment "text message 71" +2.0.1.72 timeout 0 comment "text message 72" +2.0.1.73 timeout 0 comment "text message 73" +2.0.1.74 timeout 0 comment "text message 74" +2.0.1.75 timeout 0 comment "text message 75" +2.0.1.76 timeout 0 comment "text message 76" +2.0.1.77 timeout 0 comment "text message 77" +2.0.1.78 timeout 0 comment "text message 78" +2.0.1.79 timeout 0 comment "text message 79" +2.0.1.80 timeout 0 comment "text message 80" +2.0.1.81 timeout 0 comment "text message 81" +2.0.1.82 timeout 0 comment "text message 82" +2.0.1.83 timeout 0 comment "text message 83" +2.0.1.84 timeout 0 comment "text message 84" +2.0.1.85 timeout 0 comment "text message 85" +2.0.1.86 timeout 0 comment "text message 86" +2.0.1.87 timeout 0 comment "text message 87" +2.0.1.88 timeout 0 comment "text message 88" +2.0.1.89 timeout 0 comment "text message 89" +2.0.1.90 timeout 0 comment "text message 90" +2.0.1.91 timeout 0 comment "text message 91" +2.0.1.92 timeout 0 comment "text message 92" +2.0.1.93 timeout 0 comment "text message 93" +2.0.1.94 timeout 0 comment "text message 94" +2.0.1.95 timeout 0 comment "text message 95" +2.0.1.96 timeout 0 comment "text message 96" +2.0.1.97 timeout 0 comment "text message 97" +2.0.1.98 timeout 0 comment "text message 98" +2.0.1.99 timeout 0 comment "text message 99" +2.0.1.100 timeout 0 comment "text message 100" +2.0.1.101 timeout 0 comment "text message 101" +2.0.1.102 timeout 0 comment "text message 102" +2.0.1.103 timeout 0 comment "text message 103" +2.0.1.104 timeout 0 comment "text message 104" +2.0.1.105 timeout 0 comment "text message 105" +2.0.1.106 timeout 0 comment "text message 106" +2.0.1.107 timeout 0 comment "text message 107" +2.0.1.108 timeout 0 comment "text message 108" +2.0.1.109 timeout 0 comment "text message 109" +2.0.1.110 timeout 0 comment "text message 110" +2.0.1.111 timeout 0 comment "text message 111" +2.0.1.112 timeout 0 comment "text message 112" +2.0.1.113 timeout 0 comment "text message 113" +2.0.1.114 timeout 0 comment "text message 114" +2.0.1.115 timeout 0 comment "text message 115" +2.0.1.116 timeout 0 comment "text message 116" +2.0.1.117 timeout 0 comment "text message 117" +2.0.1.118 timeout 0 comment "text message 118" +2.0.1.119 timeout 0 comment "text message 119" +2.0.1.120 timeout 0 comment "text message 120" +2.0.1.121 timeout 0 comment "text message 121" +2.0.1.122 timeout 0 comment "text message 122" +2.0.1.123 timeout 0 comment "text message 123" +2.0.1.124 timeout 0 comment "text message 124" +2.0.1.125 timeout 0 comment "text message 125" +2.0.1.126 timeout 0 comment "text message 126" +2.0.1.127 timeout 0 comment "text message 127" +2.0.1.128 timeout 0 comment "text message 128" +2.0.1.129 timeout 0 comment "text message 129" +2.0.1.130 timeout 0 comment "text message 130" +2.0.1.131 timeout 0 comment "text message 131" +2.0.1.132 timeout 0 comment "text message 132" +2.0.1.133 timeout 0 comment "text message 133" +2.0.1.134 timeout 0 comment "text message 134" +2.0.1.135 timeout 0 comment "text message 135" +2.0.1.136 timeout 0 comment "text message 136" +2.0.1.137 timeout 0 comment "text message 137" +2.0.1.138 timeout 0 comment "text message 138" +2.0.1.139 timeout 0 comment "text message 139" +2.0.1.140 timeout 0 comment "text message 140" +2.0.1.141 timeout 0 comment "text message 141" +2.0.1.142 timeout 0 comment "text message 142" +2.0.1.143 timeout 0 comment "text message 143" +2.0.1.144 timeout 0 comment "text message 144" +2.0.1.145 timeout 0 comment "text message 145" +2.0.1.146 timeout 0 comment "text message 146" +2.0.1.147 timeout 0 comment "text message 147" +2.0.1.148 timeout 0 comment "text message 148" +2.0.1.149 timeout 0 comment "text message 149" +2.0.1.150 timeout 0 comment "text message 150" +2.0.1.151 timeout 0 comment "text message 151" +2.0.1.152 timeout 0 comment "text message 152" +2.0.1.153 timeout 0 comment "text message 153" +2.0.1.154 timeout 0 comment "text message 154" +2.0.1.155 timeout 0 comment "text message 155" +2.0.1.156 timeout 0 comment "text message 156" +2.0.1.157 timeout 0 comment "text message 157" +2.0.1.158 timeout 0 comment "text message 158" +2.0.1.159 timeout 0 comment "text message 159" +2.0.1.160 timeout 0 comment "text message 160" +2.0.1.161 timeout 0 comment "text message 161" +2.0.1.162 timeout 0 comment "text message 162" +2.0.1.163 timeout 0 comment "text message 163" +2.0.1.164 timeout 0 comment "text message 164" +2.0.1.165 timeout 0 comment "text message 165" +2.0.1.166 timeout 0 comment "text message 166" +2.0.1.167 timeout 0 comment "text message 167" +2.0.1.168 timeout 0 comment "text message 168" +2.0.1.169 timeout 0 comment "text message 169" +2.0.1.170 timeout 0 comment "text message 170" +2.0.1.171 timeout 0 comment "text message 171" +2.0.1.172 timeout 0 comment "text message 172" +2.0.1.173 timeout 0 comment "text message 173" +2.0.1.174 timeout 0 comment "text message 174" +2.0.1.175 timeout 0 comment "text message 175" +2.0.1.176 timeout 0 comment "text message 176" +2.0.1.177 timeout 0 comment "text message 177" +2.0.1.178 timeout 0 comment "text message 178" +2.0.1.179 timeout 0 comment "text message 179" +2.0.1.180 timeout 0 comment "text message 180" +2.0.1.181 timeout 0 comment "text message 181" +2.0.1.182 timeout 0 comment "text message 182" +2.0.1.183 timeout 0 comment "text message 183" +2.0.1.184 timeout 0 comment "text message 184" +2.0.1.185 timeout 0 comment "text message 185" +2.0.1.186 timeout 0 comment "text message 186" +2.0.1.187 timeout 0 comment "text message 187" +2.0.1.188 timeout 0 comment "text message 188" +2.0.1.189 timeout 0 comment "text message 189" +2.0.1.190 timeout 0 comment "text message 190" +2.0.1.191 timeout 0 comment "text message 191" +2.0.1.192 timeout 0 comment "text message 192" +2.0.1.193 timeout 0 comment "text message 193" +2.0.1.194 timeout 0 comment "text message 194" +2.0.1.195 timeout 0 comment "text message 195" +2.0.1.196 timeout 0 comment "text message 196" +2.0.1.197 timeout 0 comment "text message 197" +2.0.1.198 timeout 0 comment "text message 198" +2.0.1.199 timeout 0 comment "text message 199" +2.0.1.200 timeout 0 comment "text message 200" +2.0.1.201 timeout 0 comment "text message 201" +2.0.1.202 timeout 0 comment "text message 202" +2.0.1.203 timeout 0 comment "text message 203" +2.0.1.204 timeout 0 comment "text message 204" +2.0.1.205 timeout 0 comment "text message 205" +2.0.1.206 timeout 0 comment "text message 206" +2.0.1.207 timeout 0 comment "text message 207" +2.0.1.208 timeout 0 comment "text message 208" +2.0.1.209 timeout 0 comment "text message 209" +2.0.1.210 timeout 0 comment "text message 210" +2.0.1.211 timeout 0 comment "text message 211" +2.0.1.212 timeout 0 comment "text message 212" +2.0.1.213 timeout 0 comment "text message 213" +2.0.1.214 timeout 0 comment "text message 214" +2.0.1.215 timeout 0 comment "text message 215" +2.0.1.216 timeout 0 comment "text message 216" +2.0.1.217 timeout 0 comment "text message 217" +2.0.1.218 timeout 0 comment "text message 218" +2.0.1.219 timeout 0 comment "text message 219" +2.0.1.220 timeout 0 comment "text message 220" +2.0.1.221 timeout 0 comment "text message 221" +2.0.1.222 timeout 0 comment "text message 222" +2.0.1.223 timeout 0 comment "text message 223" +2.0.1.224 timeout 0 comment "text message 224" +2.0.1.225 timeout 0 comment "text message 225" +2.0.1.226 timeout 0 comment "text message 226" +2.0.1.227 timeout 0 comment "text message 227" +2.0.1.228 timeout 0 comment "text message 228" +2.0.1.229 timeout 0 comment "text message 229" +2.0.1.230 timeout 0 comment "text message 230" +2.0.1.231 timeout 0 comment "text message 231" +2.0.1.232 timeout 0 comment "text message 232" +2.0.1.233 timeout 0 comment "text message 233" +2.0.1.234 timeout 0 comment "text message 234" +2.0.1.235 timeout 0 comment "text message 235" +2.0.1.236 timeout 0 comment "text message 236" +2.0.1.237 timeout 0 comment "text message 237" +2.0.1.238 timeout 0 comment "text message 238" +2.0.1.239 timeout 0 comment "text message 239" +2.0.1.240 timeout 0 comment "text message 240" +2.0.1.241 timeout 0 comment "text message 241" +2.0.1.242 timeout 0 comment "text message 242" +2.0.1.243 timeout 0 comment "text message 243" +2.0.1.244 timeout 0 comment "text message 244" +2.0.1.245 timeout 0 comment "text message 245" +2.0.1.246 timeout 0 comment "text message 246" +2.0.1.247 timeout 0 comment "text message 247" +2.0.1.248 timeout 0 comment "text message 248" +2.0.1.249 timeout 0 comment "text message 249" +2.0.1.250 timeout 0 comment "text message 250" +2.0.1.251 timeout 0 comment "text message 251" +2.0.1.252 timeout 0 comment "text message 252" +2.0.1.253 timeout 0 comment "text message 253" +2.0.1.254 timeout 0 comment "text message 254" +2.0.1.255 timeout 0 comment "text message 255" diff --git a/tests/comment.t.list2 b/tests/comment.t.list2 index 90a7e9b..8fc69f2 100644 --- a/tests/comment.t.list2 +++ b/tests/comment.t.list2 @@ -1,7 +1,8 @@ Name: test Type: hash:net,net -Header: family inet hashsize 128 maxelem 65536 comment -Size in memory: 1288 +Revision: 3 +Header: family inet hashsize 128 maxelem 65536 comment bucketsize 12 initval 0xa48336cf +Size in memory: 1190 References: 0 Number of entries: 4 Members: diff --git a/tests/comment.t.list21 b/tests/comment.t.list21 index 973b344..416db40 100644 --- a/tests/comment.t.list21 +++ b/tests/comment.t.list21 @@ -1,519 +1,520 @@ Name: test Type: hash:ip -Header: family inet hashsize 1024 maxelem 65536 timeout x comment -Size in memory: 95168 +Revision: 5 +Header: family inet hashsize 1024 maxelem 65536 timeout 4 comment bucketsize 12 initval 0x8a1632dd +Size in memory: 50132 References: 0 Number of entries: 512 Members: -2.0.0.0 timeout x comment "text message 0" -2.0.0.1 timeout x comment "text message 1" -2.0.0.10 timeout x comment "text message 10" -2.0.0.100 timeout x comment "text message 100" -2.0.0.101 timeout x comment "text message 101" -2.0.0.102 timeout x comment "text message 102" -2.0.0.103 timeout x comment "text message 103" -2.0.0.104 timeout x comment "text message 104" -2.0.0.105 timeout x comment "text message 105" -2.0.0.106 timeout x comment "text message 106" -2.0.0.107 timeout x comment "text message 107" -2.0.0.108 timeout x comment "text message 108" -2.0.0.109 timeout x comment "text message 109" -2.0.0.11 timeout x comment "text message 11" -2.0.0.110 timeout x comment "text message 110" -2.0.0.111 timeout x comment "text message 111" -2.0.0.112 timeout x comment "text message 112" -2.0.0.113 timeout x comment "text message 113" -2.0.0.114 timeout x comment "text message 114" -2.0.0.115 timeout x comment "text message 115" -2.0.0.116 timeout x comment "text message 116" -2.0.0.117 timeout x comment "text message 117" -2.0.0.118 timeout x comment "text message 118" -2.0.0.119 timeout x comment "text message 119" -2.0.0.12 timeout x comment "text message 12" -2.0.0.120 timeout x comment "text message 120" -2.0.0.121 timeout x comment "text message 121" -2.0.0.122 timeout x comment "text message 122" -2.0.0.123 timeout x comment "text message 123" -2.0.0.124 timeout x comment "text message 124" -2.0.0.125 timeout x comment "text message 125" -2.0.0.126 timeout x comment "text message 126" -2.0.0.127 timeout x comment "text message 127" -2.0.0.128 timeout x comment "text message 128" -2.0.0.129 timeout x comment "text message 129" -2.0.0.13 timeout x comment "text message 13" -2.0.0.130 timeout x comment "text message 130" -2.0.0.131 timeout x comment "text message 131" -2.0.0.132 timeout x comment "text message 132" -2.0.0.133 timeout x comment "text message 133" -2.0.0.134 timeout x comment "text message 134" -2.0.0.135 timeout x comment "text message 135" -2.0.0.136 timeout x comment "text message 136" -2.0.0.137 timeout x comment "text message 137" -2.0.0.138 timeout x comment "text message 138" -2.0.0.139 timeout x comment "text message 139" -2.0.0.14 timeout x comment "text message 14" -2.0.0.140 timeout x comment "text message 140" -2.0.0.141 timeout x comment "text message 141" -2.0.0.142 timeout x comment "text message 142" -2.0.0.143 timeout x comment "text message 143" -2.0.0.144 timeout x comment "text message 144" -2.0.0.145 timeout x comment "text message 145" -2.0.0.146 timeout x comment "text message 146" -2.0.0.147 timeout x comment "text message 147" -2.0.0.148 timeout x comment "text message 148" -2.0.0.149 timeout x comment "text message 149" -2.0.0.15 timeout x comment "text message 15" -2.0.0.150 timeout x comment "text message 150" -2.0.0.151 timeout x comment "text message 151" -2.0.0.152 timeout x comment "text message 152" -2.0.0.153 timeout x comment "text message 153" -2.0.0.154 timeout x comment "text message 154" -2.0.0.155 timeout x comment "text message 155" -2.0.0.156 timeout x comment "text message 156" -2.0.0.157 timeout x comment "text message 157" -2.0.0.158 timeout x comment "text message 158" -2.0.0.159 timeout x comment "text message 159" -2.0.0.16 timeout x comment "text message 16" -2.0.0.160 timeout x comment "text message 160" -2.0.0.161 timeout x comment "text message 161" -2.0.0.162 timeout x comment "text message 162" -2.0.0.163 timeout x comment "text message 163" -2.0.0.164 timeout x comment "text message 164" -2.0.0.165 timeout x comment "text message 165" -2.0.0.166 timeout x comment "text message 166" -2.0.0.167 timeout x comment "text message 167" -2.0.0.168 timeout x comment "text message 168" -2.0.0.169 timeout x comment "text message 169" -2.0.0.17 timeout x comment "text message 17" -2.0.0.170 timeout x comment "text message 170" -2.0.0.171 timeout x comment "text message 171" -2.0.0.172 timeout x comment "text message 172" -2.0.0.173 timeout x comment "text message 173" -2.0.0.174 timeout x comment "text message 174" -2.0.0.175 timeout x comment "text message 175" -2.0.0.176 timeout x comment "text message 176" -2.0.0.177 timeout x comment "text message 177" -2.0.0.178 timeout x comment "text message 178" -2.0.0.179 timeout x comment "text message 179" -2.0.0.18 timeout x comment "text message 18" -2.0.0.180 timeout x comment "text message 180" -2.0.0.181 timeout x comment "text message 181" -2.0.0.182 timeout x comment "text message 182" -2.0.0.183 timeout x comment "text message 183" -2.0.0.184 timeout x comment "text message 184" -2.0.0.185 timeout x comment "text message 185" -2.0.0.186 timeout x comment "text message 186" -2.0.0.187 timeout x comment "text message 187" -2.0.0.188 timeout x comment "text message 188" -2.0.0.189 timeout x comment "text message 189" -2.0.0.19 timeout x comment "text message 19" -2.0.0.190 timeout x comment "text message 190" -2.0.0.191 timeout x comment "text message 191" -2.0.0.192 timeout x comment "text message 192" -2.0.0.193 timeout x comment "text message 193" -2.0.0.194 timeout x comment "text message 194" -2.0.0.195 timeout x comment "text message 195" -2.0.0.196 timeout x comment "text message 196" -2.0.0.197 timeout x comment "text message 197" -2.0.0.198 timeout x comment "text message 198" -2.0.0.199 timeout x comment "text message 199" -2.0.0.2 timeout x comment "text message 2" -2.0.0.20 timeout x comment "text message 20" -2.0.0.200 timeout x comment "text message 200" -2.0.0.201 timeout x comment "text message 201" -2.0.0.202 timeout x comment "text message 202" -2.0.0.203 timeout x comment "text message 203" -2.0.0.204 timeout x comment "text message 204" -2.0.0.205 timeout x comment "text message 205" -2.0.0.206 timeout x comment "text message 206" -2.0.0.207 timeout x comment "text message 207" -2.0.0.208 timeout x comment "text message 208" -2.0.0.209 timeout x comment "text message 209" -2.0.0.21 timeout x comment "text message 21" -2.0.0.210 timeout x comment "text message 210" -2.0.0.211 timeout x comment "text message 211" -2.0.0.212 timeout x comment "text message 212" -2.0.0.213 timeout x comment "text message 213" -2.0.0.214 timeout x comment "text message 214" -2.0.0.215 timeout x comment "text message 215" -2.0.0.216 timeout x comment "text message 216" -2.0.0.217 timeout x comment "text message 217" -2.0.0.218 timeout x comment "text message 218" -2.0.0.219 timeout x comment "text message 219" -2.0.0.22 timeout x comment "text message 22" -2.0.0.220 timeout x comment "text message 220" -2.0.0.221 timeout x comment "text message 221" -2.0.0.222 timeout x comment "text message 222" -2.0.0.223 timeout x comment "text message 223" -2.0.0.224 timeout x comment "text message 224" -2.0.0.225 timeout x comment "text message 225" -2.0.0.226 timeout x comment "text message 226" -2.0.0.227 timeout x comment "text message 227" -2.0.0.228 timeout x comment "text message 228" -2.0.0.229 timeout x comment "text message 229" -2.0.0.23 timeout x comment "text message 23" -2.0.0.230 timeout x comment "text message 230" -2.0.0.231 timeout x comment "text message 231" -2.0.0.232 timeout x comment "text message 232" -2.0.0.233 timeout x comment "text message 233" -2.0.0.234 timeout x comment "text message 234" -2.0.0.235 timeout x comment "text message 235" -2.0.0.236 timeout x comment "text message 236" -2.0.0.237 timeout x comment "text message 237" -2.0.0.238 timeout x comment "text message 238" -2.0.0.239 timeout x comment "text message 239" -2.0.0.24 timeout x comment "text message 24" -2.0.0.240 timeout x comment "text message 240" -2.0.0.241 timeout x comment "text message 241" -2.0.0.242 timeout x comment "text message 242" -2.0.0.243 timeout x comment "text message 243" -2.0.0.244 timeout x comment "text message 244" -2.0.0.245 timeout x comment "text message 245" -2.0.0.246 timeout x comment "text message 246" -2.0.0.247 timeout x comment "text message 247" -2.0.0.248 timeout x comment "text message 248" -2.0.0.249 timeout x comment "text message 249" -2.0.0.25 timeout x comment "text message 25" -2.0.0.250 timeout x comment "text message 250" -2.0.0.251 timeout x comment "text message 251" -2.0.0.252 timeout x comment "text message 252" -2.0.0.253 timeout x comment "text message 253" -2.0.0.254 timeout x comment "text message 254" -2.0.0.255 timeout x comment "text message 255" -2.0.0.26 timeout x comment "text message 26" -2.0.0.27 timeout x comment "text message 27" -2.0.0.28 timeout x comment "text message 28" -2.0.0.29 timeout x comment "text message 29" -2.0.0.3 timeout x comment "text message 3" -2.0.0.30 timeout x comment "text message 30" -2.0.0.31 timeout x comment "text message 31" -2.0.0.32 timeout x comment "text message 32" -2.0.0.33 timeout x comment "text message 33" -2.0.0.34 timeout x comment "text message 34" -2.0.0.35 timeout x comment "text message 35" -2.0.0.36 timeout x comment "text message 36" -2.0.0.37 timeout x comment "text message 37" -2.0.0.38 timeout x comment "text message 38" -2.0.0.39 timeout x comment "text message 39" -2.0.0.4 timeout x comment "text message 4" -2.0.0.40 timeout x comment "text message 40" -2.0.0.41 timeout x comment "text message 41" -2.0.0.42 timeout x comment "text message 42" -2.0.0.43 timeout x comment "text message 43" -2.0.0.44 timeout x comment "text message 44" -2.0.0.45 timeout x comment "text message 45" -2.0.0.46 timeout x comment "text message 46" -2.0.0.47 timeout x comment "text message 47" -2.0.0.48 timeout x comment "text message 48" -2.0.0.49 timeout x comment "text message 49" -2.0.0.5 timeout x comment "text message 5" -2.0.0.50 timeout x comment "text message 50" -2.0.0.51 timeout x comment "text message 51" -2.0.0.52 timeout x comment "text message 52" -2.0.0.53 timeout x comment "text message 53" -2.0.0.54 timeout x comment "text message 54" -2.0.0.55 timeout x comment "text message 55" -2.0.0.56 timeout x comment "text message 56" -2.0.0.57 timeout x comment "text message 57" -2.0.0.58 timeout x comment "text message 58" -2.0.0.59 timeout x comment "text message 59" -2.0.0.6 timeout x comment "text message 6" -2.0.0.60 timeout x comment "text message 60" -2.0.0.61 timeout x comment "text message 61" -2.0.0.62 timeout x comment "text message 62" -2.0.0.63 timeout x comment "text message 63" -2.0.0.64 timeout x comment "text message 64" -2.0.0.65 timeout x comment "text message 65" -2.0.0.66 timeout x comment "text message 66" -2.0.0.67 timeout x comment "text message 67" -2.0.0.68 timeout x comment "text message 68" -2.0.0.69 timeout x comment "text message 69" -2.0.0.7 timeout x comment "text message 7" -2.0.0.70 timeout x comment "text message 70" -2.0.0.71 timeout x comment "text message 71" -2.0.0.72 timeout x comment "text message 72" -2.0.0.73 timeout x comment "text message 73" -2.0.0.74 timeout x comment "text message 74" -2.0.0.75 timeout x comment "text message 75" -2.0.0.76 timeout x comment "text message 76" -2.0.0.77 timeout x comment "text message 77" -2.0.0.78 timeout x comment "text message 78" -2.0.0.79 timeout x comment "text message 79" -2.0.0.8 timeout x comment "text message 8" -2.0.0.80 timeout x comment "text message 80" -2.0.0.81 timeout x comment "text message 81" -2.0.0.82 timeout x comment "text message 82" -2.0.0.83 timeout x comment "text message 83" -2.0.0.84 timeout x comment "text message 84" -2.0.0.85 timeout x comment "text message 85" -2.0.0.86 timeout x comment "text message 86" -2.0.0.87 timeout x comment "text message 87" -2.0.0.88 timeout x comment "text message 88" -2.0.0.89 timeout x comment "text message 89" -2.0.0.9 timeout x comment "text message 9" -2.0.0.90 timeout x comment "text message 90" -2.0.0.91 timeout x comment "text message 91" -2.0.0.92 timeout x comment "text message 92" -2.0.0.93 timeout x comment "text message 93" -2.0.0.94 timeout x comment "text message 94" -2.0.0.95 timeout x comment "text message 95" -2.0.0.96 timeout x comment "text message 96" -2.0.0.97 timeout x comment "text message 97" -2.0.0.98 timeout x comment "text message 98" -2.0.0.99 timeout x comment "text message 99" -2.0.1.0 timeout x comment "text message 0" -2.0.1.1 timeout x comment "text message 1" -2.0.1.10 timeout x comment "text message 10" -2.0.1.100 timeout x comment "text message 100" -2.0.1.101 timeout x comment "text message 101" -2.0.1.102 timeout x comment "text message 102" -2.0.1.103 timeout x comment "text message 103" -2.0.1.104 timeout x comment "text message 104" -2.0.1.105 timeout x comment "text message 105" -2.0.1.106 timeout x comment "text message 106" -2.0.1.107 timeout x comment "text message 107" -2.0.1.108 timeout x comment "text message 108" -2.0.1.109 timeout x comment "text message 109" -2.0.1.11 timeout x comment "text message 11" -2.0.1.110 timeout x comment "text message 110" -2.0.1.111 timeout x comment "text message 111" -2.0.1.112 timeout x comment "text message 112" -2.0.1.113 timeout x comment "text message 113" -2.0.1.114 timeout x comment "text message 114" -2.0.1.115 timeout x comment "text message 115" -2.0.1.116 timeout x comment "text message 116" -2.0.1.117 timeout x comment "text message 117" -2.0.1.118 timeout x comment "text message 118" -2.0.1.119 timeout x comment "text message 119" -2.0.1.12 timeout x comment "text message 12" -2.0.1.120 timeout x comment "text message 120" -2.0.1.121 timeout x comment "text message 121" -2.0.1.122 timeout x comment "text message 122" -2.0.1.123 timeout x comment "text message 123" -2.0.1.124 timeout x comment "text message 124" -2.0.1.125 timeout x comment "text message 125" -2.0.1.126 timeout x comment "text message 126" -2.0.1.127 timeout x comment "text message 127" -2.0.1.128 timeout x comment "text message 128" -2.0.1.129 timeout x comment "text message 129" -2.0.1.13 timeout x comment "text message 13" -2.0.1.130 timeout x comment "text message 130" -2.0.1.131 timeout x comment "text message 131" -2.0.1.132 timeout x comment "text message 132" -2.0.1.133 timeout x comment "text message 133" -2.0.1.134 timeout x comment "text message 134" -2.0.1.135 timeout x comment "text message 135" -2.0.1.136 timeout x comment "text message 136" -2.0.1.137 timeout x comment "text message 137" -2.0.1.138 timeout x comment "text message 138" -2.0.1.139 timeout x comment "text message 139" -2.0.1.14 timeout x comment "text message 14" -2.0.1.140 timeout x comment "text message 140" -2.0.1.141 timeout x comment "text message 141" -2.0.1.142 timeout x comment "text message 142" -2.0.1.143 timeout x comment "text message 143" -2.0.1.144 timeout x comment "text message 144" -2.0.1.145 timeout x comment "text message 145" -2.0.1.146 timeout x comment "text message 146" -2.0.1.147 timeout x comment "text message 147" -2.0.1.148 timeout x comment "text message 148" -2.0.1.149 timeout x comment "text message 149" -2.0.1.15 timeout x comment "text message 15" -2.0.1.150 timeout x comment "text message 150" -2.0.1.151 timeout x comment "text message 151" -2.0.1.152 timeout x comment "text message 152" -2.0.1.153 timeout x comment "text message 153" -2.0.1.154 timeout x comment "text message 154" -2.0.1.155 timeout x comment "text message 155" -2.0.1.156 timeout x comment "text message 156" -2.0.1.157 timeout x comment "text message 157" -2.0.1.158 timeout x comment "text message 158" -2.0.1.159 timeout x comment "text message 159" -2.0.1.16 timeout x comment "text message 16" -2.0.1.160 timeout x comment "text message 160" -2.0.1.161 timeout x comment "text message 161" -2.0.1.162 timeout x comment "text message 162" -2.0.1.163 timeout x comment "text message 163" -2.0.1.164 timeout x comment "text message 164" -2.0.1.165 timeout x comment "text message 165" -2.0.1.166 timeout x comment "text message 166" -2.0.1.167 timeout x comment "text message 167" -2.0.1.168 timeout x comment "text message 168" -2.0.1.169 timeout x comment "text message 169" -2.0.1.17 timeout x comment "text message 17" -2.0.1.170 timeout x comment "text message 170" -2.0.1.171 timeout x comment "text message 171" -2.0.1.172 timeout x comment "text message 172" -2.0.1.173 timeout x comment "text message 173" -2.0.1.174 timeout x comment "text message 174" -2.0.1.175 timeout x comment "text message 175" -2.0.1.176 timeout x comment "text message 176" -2.0.1.177 timeout x comment "text message 177" -2.0.1.178 timeout x comment "text message 178" -2.0.1.179 timeout x comment "text message 179" -2.0.1.18 timeout x comment "text message 18" -2.0.1.180 timeout x comment "text message 180" -2.0.1.181 timeout x comment "text message 181" -2.0.1.182 timeout x comment "text message 182" -2.0.1.183 timeout x comment "text message 183" -2.0.1.184 timeout x comment "text message 184" -2.0.1.185 timeout x comment "text message 185" -2.0.1.186 timeout x comment "text message 186" -2.0.1.187 timeout x comment "text message 187" -2.0.1.188 timeout x comment "text message 188" -2.0.1.189 timeout x comment "text message 189" -2.0.1.19 timeout x comment "text message 19" -2.0.1.190 timeout x comment "text message 190" -2.0.1.191 timeout x comment "text message 191" -2.0.1.192 timeout x comment "text message 192" -2.0.1.193 timeout x comment "text message 193" -2.0.1.194 timeout x comment "text message 194" -2.0.1.195 timeout x comment "text message 195" -2.0.1.196 timeout x comment "text message 196" -2.0.1.197 timeout x comment "text message 197" -2.0.1.198 timeout x comment "text message 198" -2.0.1.199 timeout x comment "text message 199" -2.0.1.2 timeout x comment "text message 2" -2.0.1.20 timeout x comment "text message 20" -2.0.1.200 timeout x comment "text message 200" -2.0.1.201 timeout x comment "text message 201" -2.0.1.202 timeout x comment "text message 202" -2.0.1.203 timeout x comment "text message 203" -2.0.1.204 timeout x comment "text message 204" -2.0.1.205 timeout x comment "text message 205" -2.0.1.206 timeout x comment "text message 206" -2.0.1.207 timeout x comment "text message 207" -2.0.1.208 timeout x comment "text message 208" -2.0.1.209 timeout x comment "text message 209" -2.0.1.21 timeout x comment "text message 21" -2.0.1.210 timeout x comment "text message 210" -2.0.1.211 timeout x comment "text message 211" -2.0.1.212 timeout x comment "text message 212" -2.0.1.213 timeout x comment "text message 213" -2.0.1.214 timeout x comment "text message 214" -2.0.1.215 timeout x comment "text message 215" -2.0.1.216 timeout x comment "text message 216" -2.0.1.217 timeout x comment "text message 217" -2.0.1.218 timeout x comment "text message 218" -2.0.1.219 timeout x comment "text message 219" -2.0.1.22 timeout x comment "text message 22" -2.0.1.220 timeout x comment "text message 220" -2.0.1.221 timeout x comment "text message 221" -2.0.1.222 timeout x comment "text message 222" -2.0.1.223 timeout x comment "text message 223" -2.0.1.224 timeout x comment "text message 224" -2.0.1.225 timeout x comment "text message 225" -2.0.1.226 timeout x comment "text message 226" -2.0.1.227 timeout x comment "text message 227" -2.0.1.228 timeout x comment "text message 228" -2.0.1.229 timeout x comment "text message 229" -2.0.1.23 timeout x comment "text message 23" -2.0.1.230 timeout x comment "text message 230" -2.0.1.231 timeout x comment "text message 231" -2.0.1.232 timeout x comment "text message 232" -2.0.1.233 timeout x comment "text message 233" -2.0.1.234 timeout x comment "text message 234" -2.0.1.235 timeout x comment "text message 235" -2.0.1.236 timeout x comment "text message 236" -2.0.1.237 timeout x comment "text message 237" -2.0.1.238 timeout x comment "text message 238" -2.0.1.239 timeout x comment "text message 239" -2.0.1.24 timeout x comment "text message 24" -2.0.1.240 timeout x comment "text message 240" -2.0.1.241 timeout x comment "text message 241" -2.0.1.242 timeout x comment "text message 242" -2.0.1.243 timeout x comment "text message 243" -2.0.1.244 timeout x comment "text message 244" -2.0.1.245 timeout x comment "text message 245" -2.0.1.246 timeout x comment "text message 246" -2.0.1.247 timeout x comment "text message 247" -2.0.1.248 timeout x comment "text message 248" -2.0.1.249 timeout x comment "text message 249" -2.0.1.25 timeout x comment "text message 25" -2.0.1.250 timeout x comment "text message 250" -2.0.1.251 timeout x comment "text message 251" -2.0.1.252 timeout x comment "text message 252" -2.0.1.253 timeout x comment "text message 253" -2.0.1.254 timeout x comment "text message 254" -2.0.1.255 timeout x comment "text message 255" -2.0.1.26 timeout x comment "text message 26" -2.0.1.27 timeout x comment "text message 27" -2.0.1.28 timeout x comment "text message 28" -2.0.1.29 timeout x comment "text message 29" -2.0.1.3 timeout x comment "text message 3" -2.0.1.30 timeout x comment "text message 30" -2.0.1.31 timeout x comment "text message 31" -2.0.1.32 timeout x comment "text message 32" -2.0.1.33 timeout x comment "text message 33" -2.0.1.34 timeout x comment "text message 34" -2.0.1.35 timeout x comment "text message 35" -2.0.1.36 timeout x comment "text message 36" -2.0.1.37 timeout x comment "text message 37" -2.0.1.38 timeout x comment "text message 38" -2.0.1.39 timeout x comment "text message 39" -2.0.1.4 timeout x comment "text message 4" -2.0.1.40 timeout x comment "text message 40" -2.0.1.41 timeout x comment "text message 41" -2.0.1.42 timeout x comment "text message 42" -2.0.1.43 timeout x comment "text message 43" -2.0.1.44 timeout x comment "text message 44" -2.0.1.45 timeout x comment "text message 45" -2.0.1.46 timeout x comment "text message 46" -2.0.1.47 timeout x comment "text message 47" -2.0.1.48 timeout x comment "text message 48" -2.0.1.49 timeout x comment "text message 49" -2.0.1.5 timeout x comment "text message 5" -2.0.1.50 timeout x comment "text message 50" -2.0.1.51 timeout x comment "text message 51" -2.0.1.52 timeout x comment "text message 52" -2.0.1.53 timeout x comment "text message 53" -2.0.1.54 timeout x comment "text message 54" -2.0.1.55 timeout x comment "text message 55" -2.0.1.56 timeout x comment "text message 56" -2.0.1.57 timeout x comment "text message 57" -2.0.1.58 timeout x comment "text message 58" -2.0.1.59 timeout x comment "text message 59" -2.0.1.6 timeout x comment "text message 6" -2.0.1.60 timeout x comment "text message 60" -2.0.1.61 timeout x comment "text message 61" -2.0.1.62 timeout x comment "text message 62" -2.0.1.63 timeout x comment "text message 63" -2.0.1.64 timeout x comment "text message 64" -2.0.1.65 timeout x comment "text message 65" -2.0.1.66 timeout x comment "text message 66" -2.0.1.67 timeout x comment "text message 67" -2.0.1.68 timeout x comment "text message 68" -2.0.1.69 timeout x comment "text message 69" -2.0.1.7 timeout x comment "text message 7" -2.0.1.70 timeout x comment "text message 70" -2.0.1.71 timeout x comment "text message 71" -2.0.1.72 timeout x comment "text message 72" -2.0.1.73 timeout x comment "text message 73" -2.0.1.74 timeout x comment "text message 74" -2.0.1.75 timeout x comment "text message 75" -2.0.1.76 timeout x comment "text message 76" -2.0.1.77 timeout x comment "text message 77" -2.0.1.78 timeout x comment "text message 78" -2.0.1.79 timeout x comment "text message 79" -2.0.1.8 timeout x comment "text message 8" -2.0.1.80 timeout x comment "text message 80" -2.0.1.81 timeout x comment "text message 81" -2.0.1.82 timeout x comment "text message 82" -2.0.1.83 timeout x comment "text message 83" -2.0.1.84 timeout x comment "text message 84" -2.0.1.85 timeout x comment "text message 85" -2.0.1.86 timeout x comment "text message 86" -2.0.1.87 timeout x comment "text message 87" -2.0.1.88 timeout x comment "text message 88" -2.0.1.89 timeout x comment "text message 89" -2.0.1.9 timeout x comment "text message 9" -2.0.1.90 timeout x comment "text message 90" -2.0.1.91 timeout x comment "text message 91" -2.0.1.92 timeout x comment "text message 92" -2.0.1.93 timeout x comment "text message 93" -2.0.1.94 timeout x comment "text message 94" -2.0.1.95 timeout x comment "text message 95" -2.0.1.96 timeout x comment "text message 96" -2.0.1.97 timeout x comment "text message 97" -2.0.1.98 timeout x comment "text message 98" -2.0.1.99 timeout x comment "text message 99" +2.0.0.0 timeout 3 comment "text message 0" +2.0.0.1 timeout 3 comment "text message 1" +2.0.0.10 timeout 3 comment "text message 10" +2.0.0.100 timeout 3 comment "text message 100" +2.0.0.101 timeout 3 comment "text message 101" +2.0.0.102 timeout 3 comment "text message 102" +2.0.0.103 timeout 3 comment "text message 103" +2.0.0.104 timeout 3 comment "text message 104" +2.0.0.105 timeout 3 comment "text message 105" +2.0.0.106 timeout 3 comment "text message 106" +2.0.0.107 timeout 3 comment "text message 107" +2.0.0.108 timeout 3 comment "text message 108" +2.0.0.109 timeout 3 comment "text message 109" +2.0.0.11 timeout 3 comment "text message 11" +2.0.0.110 timeout 3 comment "text message 110" +2.0.0.111 timeout 3 comment "text message 111" +2.0.0.112 timeout 3 comment "text message 112" +2.0.0.113 timeout 3 comment "text message 113" +2.0.0.114 timeout 3 comment "text message 114" +2.0.0.115 timeout 3 comment "text message 115" +2.0.0.116 timeout 3 comment "text message 116" +2.0.0.117 timeout 3 comment "text message 117" +2.0.0.118 timeout 3 comment "text message 118" +2.0.0.119 timeout 3 comment "text message 119" +2.0.0.12 timeout 3 comment "text message 12" +2.0.0.120 timeout 3 comment "text message 120" +2.0.0.121 timeout 3 comment "text message 121" +2.0.0.122 timeout 3 comment "text message 122" +2.0.0.123 timeout 3 comment "text message 123" +2.0.0.124 timeout 3 comment "text message 124" +2.0.0.125 timeout 3 comment "text message 125" +2.0.0.126 timeout 3 comment "text message 126" +2.0.0.127 timeout 3 comment "text message 127" +2.0.0.128 timeout 3 comment "text message 128" +2.0.0.129 timeout 3 comment "text message 129" +2.0.0.13 timeout 3 comment "text message 13" +2.0.0.130 timeout 3 comment "text message 130" +2.0.0.131 timeout 3 comment "text message 131" +2.0.0.132 timeout 3 comment "text message 132" +2.0.0.133 timeout 3 comment "text message 133" +2.0.0.134 timeout 3 comment "text message 134" +2.0.0.135 timeout 3 comment "text message 135" +2.0.0.136 timeout 3 comment "text message 136" +2.0.0.137 timeout 3 comment "text message 137" +2.0.0.138 timeout 3 comment "text message 138" +2.0.0.139 timeout 3 comment "text message 139" +2.0.0.14 timeout 3 comment "text message 14" +2.0.0.140 timeout 3 comment "text message 140" +2.0.0.141 timeout 3 comment "text message 141" +2.0.0.142 timeout 3 comment "text message 142" +2.0.0.143 timeout 3 comment "text message 143" +2.0.0.144 timeout 3 comment "text message 144" +2.0.0.145 timeout 3 comment "text message 145" +2.0.0.146 timeout 3 comment "text message 146" +2.0.0.147 timeout 3 comment "text message 147" +2.0.0.148 timeout 3 comment "text message 148" +2.0.0.149 timeout 3 comment "text message 149" +2.0.0.15 timeout 3 comment "text message 15" +2.0.0.150 timeout 3 comment "text message 150" +2.0.0.151 timeout 3 comment "text message 151" +2.0.0.152 timeout 3 comment "text message 152" +2.0.0.153 timeout 3 comment "text message 153" +2.0.0.154 timeout 3 comment "text message 154" +2.0.0.155 timeout 3 comment "text message 155" +2.0.0.156 timeout 3 comment "text message 156" +2.0.0.157 timeout 3 comment "text message 157" +2.0.0.158 timeout 3 comment "text message 158" +2.0.0.159 timeout 3 comment "text message 159" +2.0.0.16 timeout 3 comment "text message 16" +2.0.0.160 timeout 3 comment "text message 160" +2.0.0.161 timeout 3 comment "text message 161" +2.0.0.162 timeout 3 comment "text message 162" +2.0.0.163 timeout 3 comment "text message 163" +2.0.0.164 timeout 3 comment "text message 164" +2.0.0.165 timeout 3 comment "text message 165" +2.0.0.166 timeout 3 comment "text message 166" +2.0.0.167 timeout 3 comment "text message 167" +2.0.0.168 timeout 3 comment "text message 168" +2.0.0.169 timeout 3 comment "text message 169" +2.0.0.17 timeout 3 comment "text message 17" +2.0.0.170 timeout 3 comment "text message 170" +2.0.0.171 timeout 3 comment "text message 171" +2.0.0.172 timeout 3 comment "text message 172" +2.0.0.173 timeout 3 comment "text message 173" +2.0.0.174 timeout 3 comment "text message 174" +2.0.0.175 timeout 3 comment "text message 175" +2.0.0.176 timeout 3 comment "text message 176" +2.0.0.177 timeout 3 comment "text message 177" +2.0.0.178 timeout 3 comment "text message 178" +2.0.0.179 timeout 3 comment "text message 179" +2.0.0.18 timeout 3 comment "text message 18" +2.0.0.180 timeout 3 comment "text message 180" +2.0.0.181 timeout 3 comment "text message 181" +2.0.0.182 timeout 3 comment "text message 182" +2.0.0.183 timeout 3 comment "text message 183" +2.0.0.184 timeout 3 comment "text message 184" +2.0.0.185 timeout 3 comment "text message 185" +2.0.0.186 timeout 3 comment "text message 186" +2.0.0.187 timeout 3 comment "text message 187" +2.0.0.188 timeout 3 comment "text message 188" +2.0.0.189 timeout 3 comment "text message 189" +2.0.0.19 timeout 3 comment "text message 19" +2.0.0.190 timeout 3 comment "text message 190" +2.0.0.191 timeout 3 comment "text message 191" +2.0.0.192 timeout 3 comment "text message 192" +2.0.0.193 timeout 3 comment "text message 193" +2.0.0.194 timeout 3 comment "text message 194" +2.0.0.195 timeout 3 comment "text message 195" +2.0.0.196 timeout 3 comment "text message 196" +2.0.0.197 timeout 3 comment "text message 197" +2.0.0.198 timeout 3 comment "text message 198" +2.0.0.199 timeout 3 comment "text message 199" +2.0.0.2 timeout 3 comment "text message 2" +2.0.0.20 timeout 3 comment "text message 20" +2.0.0.200 timeout 3 comment "text message 200" +2.0.0.201 timeout 3 comment "text message 201" +2.0.0.202 timeout 3 comment "text message 202" +2.0.0.203 timeout 3 comment "text message 203" +2.0.0.204 timeout 3 comment "text message 204" +2.0.0.205 timeout 3 comment "text message 205" +2.0.0.206 timeout 3 comment "text message 206" +2.0.0.207 timeout 3 comment "text message 207" +2.0.0.208 timeout 3 comment "text message 208" +2.0.0.209 timeout 3 comment "text message 209" +2.0.0.21 timeout 3 comment "text message 21" +2.0.0.210 timeout 3 comment "text message 210" +2.0.0.211 timeout 3 comment "text message 211" +2.0.0.212 timeout 3 comment "text message 212" +2.0.0.213 timeout 3 comment "text message 213" +2.0.0.214 timeout 3 comment "text message 214" +2.0.0.215 timeout 3 comment "text message 215" +2.0.0.216 timeout 3 comment "text message 216" +2.0.0.217 timeout 3 comment "text message 217" +2.0.0.218 timeout 3 comment "text message 218" +2.0.0.219 timeout 3 comment "text message 219" +2.0.0.22 timeout 3 comment "text message 22" +2.0.0.220 timeout 3 comment "text message 220" +2.0.0.221 timeout 3 comment "text message 221" +2.0.0.222 timeout 3 comment "text message 222" +2.0.0.223 timeout 3 comment "text message 223" +2.0.0.224 timeout 3 comment "text message 224" +2.0.0.225 timeout 3 comment "text message 225" +2.0.0.226 timeout 3 comment "text message 226" +2.0.0.227 timeout 3 comment "text message 227" +2.0.0.228 timeout 3 comment "text message 228" +2.0.0.229 timeout 3 comment "text message 229" +2.0.0.23 timeout 3 comment "text message 23" +2.0.0.230 timeout 3 comment "text message 230" +2.0.0.231 timeout 3 comment "text message 231" +2.0.0.232 timeout 3 comment "text message 232" +2.0.0.233 timeout 3 comment "text message 233" +2.0.0.234 timeout 3 comment "text message 234" +2.0.0.235 timeout 3 comment "text message 235" +2.0.0.236 timeout 3 comment "text message 236" +2.0.0.237 timeout 3 comment "text message 237" +2.0.0.238 timeout 3 comment "text message 238" +2.0.0.239 timeout 3 comment "text message 239" +2.0.0.24 timeout 3 comment "text message 24" +2.0.0.240 timeout 3 comment "text message 240" +2.0.0.241 timeout 3 comment "text message 241" +2.0.0.242 timeout 3 comment "text message 242" +2.0.0.243 timeout 3 comment "text message 243" +2.0.0.244 timeout 3 comment "text message 244" +2.0.0.245 timeout 3 comment "text message 245" +2.0.0.246 timeout 3 comment "text message 246" +2.0.0.247 timeout 3 comment "text message 247" +2.0.0.248 timeout 3 comment "text message 248" +2.0.0.249 timeout 3 comment "text message 249" +2.0.0.25 timeout 3 comment "text message 25" +2.0.0.250 timeout 3 comment "text message 250" +2.0.0.251 timeout 3 comment "text message 251" +2.0.0.252 timeout 3 comment "text message 252" +2.0.0.253 timeout 3 comment "text message 253" +2.0.0.254 timeout 3 comment "text message 254" +2.0.0.255 timeout 3 comment "text message 255" +2.0.0.26 timeout 3 comment "text message 26" +2.0.0.27 timeout 3 comment "text message 27" +2.0.0.28 timeout 3 comment "text message 28" +2.0.0.29 timeout 3 comment "text message 29" +2.0.0.3 timeout 3 comment "text message 3" +2.0.0.30 timeout 3 comment "text message 30" +2.0.0.31 timeout 3 comment "text message 31" +2.0.0.32 timeout 3 comment "text message 32" +2.0.0.33 timeout 3 comment "text message 33" +2.0.0.34 timeout 3 comment "text message 34" +2.0.0.35 timeout 3 comment "text message 35" +2.0.0.36 timeout 3 comment "text message 36" +2.0.0.37 timeout 3 comment "text message 37" +2.0.0.38 timeout 3 comment "text message 38" +2.0.0.39 timeout 3 comment "text message 39" +2.0.0.4 timeout 3 comment "text message 4" +2.0.0.40 timeout 3 comment "text message 40" +2.0.0.41 timeout 3 comment "text message 41" +2.0.0.42 timeout 3 comment "text message 42" +2.0.0.43 timeout 3 comment "text message 43" +2.0.0.44 timeout 3 comment "text message 44" +2.0.0.45 timeout 3 comment "text message 45" +2.0.0.46 timeout 3 comment "text message 46" +2.0.0.47 timeout 3 comment "text message 47" +2.0.0.48 timeout 3 comment "text message 48" +2.0.0.49 timeout 3 comment "text message 49" +2.0.0.5 timeout 3 comment "text message 5" +2.0.0.50 timeout 3 comment "text message 50" +2.0.0.51 timeout 3 comment "text message 51" +2.0.0.52 timeout 3 comment "text message 52" +2.0.0.53 timeout 3 comment "text message 53" +2.0.0.54 timeout 3 comment "text message 54" +2.0.0.55 timeout 3 comment "text message 55" +2.0.0.56 timeout 3 comment "text message 56" +2.0.0.57 timeout 3 comment "text message 57" +2.0.0.58 timeout 3 comment "text message 58" +2.0.0.59 timeout 3 comment "text message 59" +2.0.0.6 timeout 3 comment "text message 6" +2.0.0.60 timeout 3 comment "text message 60" +2.0.0.61 timeout 3 comment "text message 61" +2.0.0.62 timeout 3 comment "text message 62" +2.0.0.63 timeout 3 comment "text message 63" +2.0.0.64 timeout 3 comment "text message 64" +2.0.0.65 timeout 3 comment "text message 65" +2.0.0.66 timeout 3 comment "text message 66" +2.0.0.67 timeout 3 comment "text message 67" +2.0.0.68 timeout 3 comment "text message 68" +2.0.0.69 timeout 3 comment "text message 69" +2.0.0.7 timeout 3 comment "text message 7" +2.0.0.70 timeout 3 comment "text message 70" +2.0.0.71 timeout 3 comment "text message 71" +2.0.0.72 timeout 3 comment "text message 72" +2.0.0.73 timeout 3 comment "text message 73" +2.0.0.74 timeout 3 comment "text message 74" +2.0.0.75 timeout 3 comment "text message 75" +2.0.0.76 timeout 3 comment "text message 76" +2.0.0.77 timeout 3 comment "text message 77" +2.0.0.78 timeout 3 comment "text message 78" +2.0.0.79 timeout 3 comment "text message 79" +2.0.0.8 timeout 3 comment "text message 8" +2.0.0.80 timeout 3 comment "text message 80" +2.0.0.81 timeout 3 comment "text message 81" +2.0.0.82 timeout 3 comment "text message 82" +2.0.0.83 timeout 3 comment "text message 83" +2.0.0.84 timeout 3 comment "text message 84" +2.0.0.85 timeout 3 comment "text message 85" +2.0.0.86 timeout 3 comment "text message 86" +2.0.0.87 timeout 3 comment "text message 87" +2.0.0.88 timeout 3 comment "text message 88" +2.0.0.89 timeout 3 comment "text message 89" +2.0.0.9 timeout 3 comment "text message 9" +2.0.0.90 timeout 3 comment "text message 90" +2.0.0.91 timeout 3 comment "text message 91" +2.0.0.92 timeout 3 comment "text message 92" +2.0.0.93 timeout 3 comment "text message 93" +2.0.0.94 timeout 3 comment "text message 94" +2.0.0.95 timeout 3 comment "text message 95" +2.0.0.96 timeout 3 comment "text message 96" +2.0.0.97 timeout 3 comment "text message 97" +2.0.0.98 timeout 3 comment "text message 98" +2.0.0.99 timeout 3 comment "text message 99" +2.0.1.0 timeout 0 comment "text message 0" +2.0.1.1 timeout 0 comment "text message 1" +2.0.1.10 timeout 0 comment "text message 10" +2.0.1.100 timeout 0 comment "text message 100" +2.0.1.101 timeout 0 comment "text message 101" +2.0.1.102 timeout 0 comment "text message 102" +2.0.1.103 timeout 0 comment "text message 103" +2.0.1.104 timeout 0 comment "text message 104" +2.0.1.105 timeout 0 comment "text message 105" +2.0.1.106 timeout 0 comment "text message 106" +2.0.1.107 timeout 0 comment "text message 107" +2.0.1.108 timeout 0 comment "text message 108" +2.0.1.109 timeout 0 comment "text message 109" +2.0.1.11 timeout 0 comment "text message 11" +2.0.1.110 timeout 0 comment "text message 110" +2.0.1.111 timeout 0 comment "text message 111" +2.0.1.112 timeout 0 comment "text message 112" +2.0.1.113 timeout 0 comment "text message 113" +2.0.1.114 timeout 0 comment "text message 114" +2.0.1.115 timeout 0 comment "text message 115" +2.0.1.116 timeout 0 comment "text message 116" +2.0.1.117 timeout 0 comment "text message 117" +2.0.1.118 timeout 0 comment "text message 118" +2.0.1.119 timeout 0 comment "text message 119" +2.0.1.12 timeout 0 comment "text message 12" +2.0.1.120 timeout 0 comment "text message 120" +2.0.1.121 timeout 0 comment "text message 121" +2.0.1.122 timeout 0 comment "text message 122" +2.0.1.123 timeout 0 comment "text message 123" +2.0.1.124 timeout 0 comment "text message 124" +2.0.1.125 timeout 0 comment "text message 125" +2.0.1.126 timeout 0 comment "text message 126" +2.0.1.127 timeout 0 comment "text message 127" +2.0.1.128 timeout 0 comment "text message 128" +2.0.1.129 timeout 0 comment "text message 129" +2.0.1.13 timeout 0 comment "text message 13" +2.0.1.130 timeout 0 comment "text message 130" +2.0.1.131 timeout 0 comment "text message 131" +2.0.1.132 timeout 0 comment "text message 132" +2.0.1.133 timeout 0 comment "text message 133" +2.0.1.134 timeout 0 comment "text message 134" +2.0.1.135 timeout 0 comment "text message 135" +2.0.1.136 timeout 0 comment "text message 136" +2.0.1.137 timeout 0 comment "text message 137" +2.0.1.138 timeout 0 comment "text message 138" +2.0.1.139 timeout 0 comment "text message 139" +2.0.1.14 timeout 0 comment "text message 14" +2.0.1.140 timeout 0 comment "text message 140" +2.0.1.141 timeout 0 comment "text message 141" +2.0.1.142 timeout 0 comment "text message 142" +2.0.1.143 timeout 0 comment "text message 143" +2.0.1.144 timeout 0 comment "text message 144" +2.0.1.145 timeout 0 comment "text message 145" +2.0.1.146 timeout 0 comment "text message 146" +2.0.1.147 timeout 0 comment "text message 147" +2.0.1.148 timeout 0 comment "text message 148" +2.0.1.149 timeout 0 comment "text message 149" +2.0.1.15 timeout 0 comment "text message 15" +2.0.1.150 timeout 0 comment "text message 150" +2.0.1.151 timeout 0 comment "text message 151" +2.0.1.152 timeout 0 comment "text message 152" +2.0.1.153 timeout 0 comment "text message 153" +2.0.1.154 timeout 0 comment "text message 154" +2.0.1.155 timeout 0 comment "text message 155" +2.0.1.156 timeout 0 comment "text message 156" +2.0.1.157 timeout 0 comment "text message 157" +2.0.1.158 timeout 0 comment "text message 158" +2.0.1.159 timeout 0 comment "text message 159" +2.0.1.16 timeout 0 comment "text message 16" +2.0.1.160 timeout 0 comment "text message 160" +2.0.1.161 timeout 0 comment "text message 161" +2.0.1.162 timeout 0 comment "text message 162" +2.0.1.163 timeout 0 comment "text message 163" +2.0.1.164 timeout 0 comment "text message 164" +2.0.1.165 timeout 0 comment "text message 165" +2.0.1.166 timeout 0 comment "text message 166" +2.0.1.167 timeout 0 comment "text message 167" +2.0.1.168 timeout 0 comment "text message 168" +2.0.1.169 timeout 0 comment "text message 169" +2.0.1.17 timeout 0 comment "text message 17" +2.0.1.170 timeout 0 comment "text message 170" +2.0.1.171 timeout 0 comment "text message 171" +2.0.1.172 timeout 0 comment "text message 172" +2.0.1.173 timeout 0 comment "text message 173" +2.0.1.174 timeout 0 comment "text message 174" +2.0.1.175 timeout 0 comment "text message 175" +2.0.1.176 timeout 0 comment "text message 176" +2.0.1.177 timeout 0 comment "text message 177" +2.0.1.178 timeout 0 comment "text message 178" +2.0.1.179 timeout 0 comment "text message 179" +2.0.1.18 timeout 0 comment "text message 18" +2.0.1.180 timeout 0 comment "text message 180" +2.0.1.181 timeout 0 comment "text message 181" +2.0.1.182 timeout 0 comment "text message 182" +2.0.1.183 timeout 0 comment "text message 183" +2.0.1.184 timeout 0 comment "text message 184" +2.0.1.185 timeout 0 comment "text message 185" +2.0.1.186 timeout 0 comment "text message 186" +2.0.1.187 timeout 0 comment "text message 187" +2.0.1.188 timeout 0 comment "text message 188" +2.0.1.189 timeout 0 comment "text message 189" +2.0.1.19 timeout 0 comment "text message 19" +2.0.1.190 timeout 0 comment "text message 190" +2.0.1.191 timeout 0 comment "text message 191" +2.0.1.192 timeout 0 comment "text message 192" +2.0.1.193 timeout 0 comment "text message 193" +2.0.1.194 timeout 0 comment "text message 194" +2.0.1.195 timeout 0 comment "text message 195" +2.0.1.196 timeout 0 comment "text message 196" +2.0.1.197 timeout 0 comment "text message 197" +2.0.1.198 timeout 0 comment "text message 198" +2.0.1.199 timeout 0 comment "text message 199" +2.0.1.2 timeout 0 comment "text message 2" +2.0.1.20 timeout 0 comment "text message 20" +2.0.1.200 timeout 0 comment "text message 200" +2.0.1.201 timeout 0 comment "text message 201" +2.0.1.202 timeout 0 comment "text message 202" +2.0.1.203 timeout 0 comment "text message 203" +2.0.1.204 timeout 0 comment "text message 204" +2.0.1.205 timeout 0 comment "text message 205" +2.0.1.206 timeout 0 comment "text message 206" +2.0.1.207 timeout 0 comment "text message 207" +2.0.1.208 timeout 0 comment "text message 208" +2.0.1.209 timeout 0 comment "text message 209" +2.0.1.21 timeout 0 comment "text message 21" +2.0.1.210 timeout 0 comment "text message 210" +2.0.1.211 timeout 0 comment "text message 211" +2.0.1.212 timeout 0 comment "text message 212" +2.0.1.213 timeout 0 comment "text message 213" +2.0.1.214 timeout 0 comment "text message 214" +2.0.1.215 timeout 0 comment "text message 215" +2.0.1.216 timeout 0 comment "text message 216" +2.0.1.217 timeout 0 comment "text message 217" +2.0.1.218 timeout 0 comment "text message 218" +2.0.1.219 timeout 0 comment "text message 219" +2.0.1.22 timeout 0 comment "text message 22" +2.0.1.220 timeout 0 comment "text message 220" +2.0.1.221 timeout 0 comment "text message 221" +2.0.1.222 timeout 0 comment "text message 222" +2.0.1.223 timeout 0 comment "text message 223" +2.0.1.224 timeout 0 comment "text message 224" +2.0.1.225 timeout 0 comment "text message 225" +2.0.1.226 timeout 0 comment "text message 226" +2.0.1.227 timeout 0 comment "text message 227" +2.0.1.228 timeout 0 comment "text message 228" +2.0.1.229 timeout 0 comment "text message 229" +2.0.1.23 timeout 0 comment "text message 23" +2.0.1.230 timeout 0 comment "text message 230" +2.0.1.231 timeout 0 comment "text message 231" +2.0.1.232 timeout 0 comment "text message 232" +2.0.1.233 timeout 0 comment "text message 233" +2.0.1.234 timeout 0 comment "text message 234" +2.0.1.235 timeout 0 comment "text message 235" +2.0.1.236 timeout 0 comment "text message 236" +2.0.1.237 timeout 0 comment "text message 237" +2.0.1.238 timeout 0 comment "text message 238" +2.0.1.239 timeout 0 comment "text message 239" +2.0.1.24 timeout 0 comment "text message 24" +2.0.1.240 timeout 0 comment "text message 240" +2.0.1.241 timeout 0 comment "text message 241" +2.0.1.242 timeout 0 comment "text message 242" +2.0.1.243 timeout 0 comment "text message 243" +2.0.1.244 timeout 0 comment "text message 244" +2.0.1.245 timeout 0 comment "text message 245" +2.0.1.246 timeout 0 comment "text message 246" +2.0.1.247 timeout 0 comment "text message 247" +2.0.1.248 timeout 0 comment "text message 248" +2.0.1.249 timeout 0 comment "text message 249" +2.0.1.25 timeout 0 comment "text message 25" +2.0.1.250 timeout 0 comment "text message 250" +2.0.1.251 timeout 0 comment "text message 251" +2.0.1.252 timeout 0 comment "text message 252" +2.0.1.253 timeout 0 comment "text message 253" +2.0.1.254 timeout 0 comment "text message 254" +2.0.1.255 timeout 0 comment "text message 255" +2.0.1.26 timeout 0 comment "text message 26" +2.0.1.27 timeout 0 comment "text message 27" +2.0.1.28 timeout 0 comment "text message 28" +2.0.1.29 timeout 0 comment "text message 29" +2.0.1.3 timeout 0 comment "text message 3" +2.0.1.30 timeout 0 comment "text message 30" +2.0.1.31 timeout 0 comment "text message 31" +2.0.1.32 timeout 0 comment "text message 32" +2.0.1.33 timeout 0 comment "text message 33" +2.0.1.34 timeout 0 comment "text message 34" +2.0.1.35 timeout 0 comment "text message 35" +2.0.1.36 timeout 0 comment "text message 36" +2.0.1.37 timeout 0 comment "text message 37" +2.0.1.38 timeout 0 comment "text message 38" +2.0.1.39 timeout 0 comment "text message 39" +2.0.1.4 timeout 0 comment "text message 4" +2.0.1.40 timeout 0 comment "text message 40" +2.0.1.41 timeout 0 comment "text message 41" +2.0.1.42 timeout 0 comment "text message 42" +2.0.1.43 timeout 0 comment "text message 43" +2.0.1.44 timeout 0 comment "text message 44" +2.0.1.45 timeout 0 comment "text message 45" +2.0.1.46 timeout 0 comment "text message 46" +2.0.1.47 timeout 0 comment "text message 47" +2.0.1.48 timeout 0 comment "text message 48" +2.0.1.49 timeout 0 comment "text message 49" +2.0.1.5 timeout 0 comment "text message 5" +2.0.1.50 timeout 0 comment "text message 50" +2.0.1.51 timeout 0 comment "text message 51" +2.0.1.52 timeout 0 comment "text message 52" +2.0.1.53 timeout 0 comment "text message 53" +2.0.1.54 timeout 0 comment "text message 54" +2.0.1.55 timeout 0 comment "text message 55" +2.0.1.56 timeout 0 comment "text message 56" +2.0.1.57 timeout 0 comment "text message 57" +2.0.1.58 timeout 0 comment "text message 58" +2.0.1.59 timeout 0 comment "text message 59" +2.0.1.6 timeout 0 comment "text message 6" +2.0.1.60 timeout 0 comment "text message 60" +2.0.1.61 timeout 0 comment "text message 61" +2.0.1.62 timeout 0 comment "text message 62" +2.0.1.63 timeout 0 comment "text message 63" +2.0.1.64 timeout 0 comment "text message 64" +2.0.1.65 timeout 0 comment "text message 65" +2.0.1.66 timeout 0 comment "text message 66" +2.0.1.67 timeout 0 comment "text message 67" +2.0.1.68 timeout 0 comment "text message 68" +2.0.1.69 timeout 0 comment "text message 69" +2.0.1.7 timeout 0 comment "text message 7" +2.0.1.70 timeout 0 comment "text message 70" +2.0.1.71 timeout 0 comment "text message 71" +2.0.1.72 timeout 0 comment "text message 72" +2.0.1.73 timeout 0 comment "text message 73" +2.0.1.74 timeout 0 comment "text message 74" +2.0.1.75 timeout 0 comment "text message 75" +2.0.1.76 timeout 0 comment "text message 76" +2.0.1.77 timeout 0 comment "text message 77" +2.0.1.78 timeout 0 comment "text message 78" +2.0.1.79 timeout 0 comment "text message 79" +2.0.1.8 timeout 0 comment "text message 8" +2.0.1.80 timeout 0 comment "text message 80" +2.0.1.81 timeout 0 comment "text message 81" +2.0.1.82 timeout 0 comment "text message 82" +2.0.1.83 timeout 0 comment "text message 83" +2.0.1.84 timeout 0 comment "text message 84" +2.0.1.85 timeout 0 comment "text message 85" +2.0.1.86 timeout 0 comment "text message 86" +2.0.1.87 timeout 0 comment "text message 87" +2.0.1.88 timeout 0 comment "text message 88" +2.0.1.89 timeout 0 comment "text message 89" +2.0.1.9 timeout 0 comment "text message 9" +2.0.1.90 timeout 0 comment "text message 90" +2.0.1.91 timeout 0 comment "text message 91" +2.0.1.92 timeout 0 comment "text message 92" +2.0.1.93 timeout 0 comment "text message 93" +2.0.1.94 timeout 0 comment "text message 94" +2.0.1.95 timeout 0 comment "text message 95" +2.0.1.96 timeout 0 comment "text message 96" +2.0.1.97 timeout 0 comment "text message 97" +2.0.1.98 timeout 0 comment "text message 98" +2.0.1.99 timeout 0 comment "text message 99" diff --git a/tests/comment.t.list22 b/tests/comment.t.list22 index 9215b0d..4cfdabe 100644 --- a/tests/comment.t.list22 +++ b/tests/comment.t.list22 @@ -1,263 +1,264 @@ Name: test Type: hash:ip -Header: family inet hashsize 1024 maxelem 65536 timeout x comment -Size in memory: 57634 +Revision: 5 +Header: family inet hashsize 1024 maxelem 65536 timeout 4 comment bucketsize 12 initval 0x8e7fb9de +Size in memory: 40834 References: 0 Number of entries: 256 Members: -2.0.1.0 timeout x comment "text message 0" -2.0.1.1 timeout x comment "text message 1" -2.0.1.10 timeout x comment "text message 10" -2.0.1.100 timeout x comment "text message 100" -2.0.1.101 timeout x comment "text message 101" -2.0.1.102 timeout x comment "text message 102" -2.0.1.103 timeout x comment "text message 103" -2.0.1.104 timeout x comment "text message 104" -2.0.1.105 timeout x comment "text message 105" -2.0.1.106 timeout x comment "text message 106" -2.0.1.107 timeout x comment "text message 107" -2.0.1.108 timeout x comment "text message 108" -2.0.1.109 timeout x comment "text message 109" -2.0.1.11 timeout x comment "text message 11" -2.0.1.110 timeout x comment "text message 110" -2.0.1.111 timeout x comment "text message 111" -2.0.1.112 timeout x comment "text message 112" -2.0.1.113 timeout x comment "text message 113" -2.0.1.114 timeout x comment "text message 114" -2.0.1.115 timeout x comment "text message 115" -2.0.1.116 timeout x comment "text message 116" -2.0.1.117 timeout x comment "text message 117" -2.0.1.118 timeout x comment "text message 118" -2.0.1.119 timeout x comment "text message 119" -2.0.1.12 timeout x comment "text message 12" -2.0.1.120 timeout x comment "text message 120" -2.0.1.121 timeout x comment "text message 121" -2.0.1.122 timeout x comment "text message 122" -2.0.1.123 timeout x comment "text message 123" -2.0.1.124 timeout x comment "text message 124" -2.0.1.125 timeout x comment "text message 125" -2.0.1.126 timeout x comment "text message 126" -2.0.1.127 timeout x comment "text message 127" -2.0.1.128 timeout x comment "text message 128" -2.0.1.129 timeout x comment "text message 129" -2.0.1.13 timeout x comment "text message 13" -2.0.1.130 timeout x comment "text message 130" -2.0.1.131 timeout x comment "text message 131" -2.0.1.132 timeout x comment "text message 132" -2.0.1.133 timeout x comment "text message 133" -2.0.1.134 timeout x comment "text message 134" -2.0.1.135 timeout x comment "text message 135" -2.0.1.136 timeout x comment "text message 136" -2.0.1.137 timeout x comment "text message 137" -2.0.1.138 timeout x comment "text message 138" -2.0.1.139 timeout x comment "text message 139" -2.0.1.14 timeout x comment "text message 14" -2.0.1.140 timeout x comment "text message 140" -2.0.1.141 timeout x comment "text message 141" -2.0.1.142 timeout x comment "text message 142" -2.0.1.143 timeout x comment "text message 143" -2.0.1.144 timeout x comment "text message 144" -2.0.1.145 timeout x comment "text message 145" -2.0.1.146 timeout x comment "text message 146" -2.0.1.147 timeout x comment "text message 147" -2.0.1.148 timeout x comment "text message 148" -2.0.1.149 timeout x comment "text message 149" -2.0.1.15 timeout x comment "text message 15" -2.0.1.150 timeout x comment "text message 150" -2.0.1.151 timeout x comment "text message 151" -2.0.1.152 timeout x comment "text message 152" -2.0.1.153 timeout x comment "text message 153" -2.0.1.154 timeout x comment "text message 154" -2.0.1.155 timeout x comment "text message 155" -2.0.1.156 timeout x comment "text message 156" -2.0.1.157 timeout x comment "text message 157" -2.0.1.158 timeout x comment "text message 158" -2.0.1.159 timeout x comment "text message 159" -2.0.1.16 timeout x comment "text message 16" -2.0.1.160 timeout x comment "text message 160" -2.0.1.161 timeout x comment "text message 161" -2.0.1.162 timeout x comment "text message 162" -2.0.1.163 timeout x comment "text message 163" -2.0.1.164 timeout x comment "text message 164" -2.0.1.165 timeout x comment "text message 165" -2.0.1.166 timeout x comment "text message 166" -2.0.1.167 timeout x comment "text message 167" -2.0.1.168 timeout x comment "text message 168" -2.0.1.169 timeout x comment "text message 169" -2.0.1.17 timeout x comment "text message 17" -2.0.1.170 timeout x comment "text message 170" -2.0.1.171 timeout x comment "text message 171" -2.0.1.172 timeout x comment "text message 172" -2.0.1.173 timeout x comment "text message 173" -2.0.1.174 timeout x comment "text message 174" -2.0.1.175 timeout x comment "text message 175" -2.0.1.176 timeout x comment "text message 176" -2.0.1.177 timeout x comment "text message 177" -2.0.1.178 timeout x comment "text message 178" -2.0.1.179 timeout x comment "text message 179" -2.0.1.18 timeout x comment "text message 18" -2.0.1.180 timeout x comment "text message 180" -2.0.1.181 timeout x comment "text message 181" -2.0.1.182 timeout x comment "text message 182" -2.0.1.183 timeout x comment "text message 183" -2.0.1.184 timeout x comment "text message 184" -2.0.1.185 timeout x comment "text message 185" -2.0.1.186 timeout x comment "text message 186" -2.0.1.187 timeout x comment "text message 187" -2.0.1.188 timeout x comment "text message 188" -2.0.1.189 timeout x comment "text message 189" -2.0.1.19 timeout x comment "text message 19" -2.0.1.190 timeout x comment "text message 190" -2.0.1.191 timeout x comment "text message 191" -2.0.1.192 timeout x comment "text message 192" -2.0.1.193 timeout x comment "text message 193" -2.0.1.194 timeout x comment "text message 194" -2.0.1.195 timeout x comment "text message 195" -2.0.1.196 timeout x comment "text message 196" -2.0.1.197 timeout x comment "text message 197" -2.0.1.198 timeout x comment "text message 198" -2.0.1.199 timeout x comment "text message 199" -2.0.1.2 timeout x comment "text message 2" -2.0.1.20 timeout x comment "text message 20" -2.0.1.200 timeout x comment "text message 200" -2.0.1.201 timeout x comment "text message 201" -2.0.1.202 timeout x comment "text message 202" -2.0.1.203 timeout x comment "text message 203" -2.0.1.204 timeout x comment "text message 204" -2.0.1.205 timeout x comment "text message 205" -2.0.1.206 timeout x comment "text message 206" -2.0.1.207 timeout x comment "text message 207" -2.0.1.208 timeout x comment "text message 208" -2.0.1.209 timeout x comment "text message 209" -2.0.1.21 timeout x comment "text message 21" -2.0.1.210 timeout x comment "text message 210" -2.0.1.211 timeout x comment "text message 211" -2.0.1.212 timeout x comment "text message 212" -2.0.1.213 timeout x comment "text message 213" -2.0.1.214 timeout x comment "text message 214" -2.0.1.215 timeout x comment "text message 215" -2.0.1.216 timeout x comment "text message 216" -2.0.1.217 timeout x comment "text message 217" -2.0.1.218 timeout x comment "text message 218" -2.0.1.219 timeout x comment "text message 219" -2.0.1.22 timeout x comment "text message 22" -2.0.1.220 timeout x comment "text message 220" -2.0.1.221 timeout x comment "text message 221" -2.0.1.222 timeout x comment "text message 222" -2.0.1.223 timeout x comment "text message 223" -2.0.1.224 timeout x comment "text message 224" -2.0.1.225 timeout x comment "text message 225" -2.0.1.226 timeout x comment "text message 226" -2.0.1.227 timeout x comment "text message 227" -2.0.1.228 timeout x comment "text message 228" -2.0.1.229 timeout x comment "text message 229" -2.0.1.23 timeout x comment "text message 23" -2.0.1.230 timeout x comment "text message 230" -2.0.1.231 timeout x comment "text message 231" -2.0.1.232 timeout x comment "text message 232" -2.0.1.233 timeout x comment "text message 233" -2.0.1.234 timeout x comment "text message 234" -2.0.1.235 timeout x comment "text message 235" -2.0.1.236 timeout x comment "text message 236" -2.0.1.237 timeout x comment "text message 237" -2.0.1.238 timeout x comment "text message 238" -2.0.1.239 timeout x comment "text message 239" -2.0.1.24 timeout x comment "text message 24" -2.0.1.240 timeout x comment "text message 240" -2.0.1.241 timeout x comment "text message 241" -2.0.1.242 timeout x comment "text message 242" -2.0.1.243 timeout x comment "text message 243" -2.0.1.244 timeout x comment "text message 244" -2.0.1.245 timeout x comment "text message 245" -2.0.1.246 timeout x comment "text message 246" -2.0.1.247 timeout x comment "text message 247" -2.0.1.248 timeout x comment "text message 248" -2.0.1.249 timeout x comment "text message 249" -2.0.1.25 timeout x comment "text message 25" -2.0.1.250 timeout x comment "text message 250" -2.0.1.251 timeout x comment "text message 251" -2.0.1.252 timeout x comment "text message 252" -2.0.1.253 timeout x comment "text message 253" -2.0.1.254 timeout x comment "text message 254" -2.0.1.255 timeout x comment "text message 255" -2.0.1.26 timeout x comment "text message 26" -2.0.1.27 timeout x comment "text message 27" -2.0.1.28 timeout x comment "text message 28" -2.0.1.29 timeout x comment "text message 29" -2.0.1.3 timeout x comment "text message 3" -2.0.1.30 timeout x comment "text message 30" -2.0.1.31 timeout x comment "text message 31" -2.0.1.32 timeout x comment "text message 32" -2.0.1.33 timeout x comment "text message 33" -2.0.1.34 timeout x comment "text message 34" -2.0.1.35 timeout x comment "text message 35" -2.0.1.36 timeout x comment "text message 36" -2.0.1.37 timeout x comment "text message 37" -2.0.1.38 timeout x comment "text message 38" -2.0.1.39 timeout x comment "text message 39" -2.0.1.4 timeout x comment "text message 4" -2.0.1.40 timeout x comment "text message 40" -2.0.1.41 timeout x comment "text message 41" -2.0.1.42 timeout x comment "text message 42" -2.0.1.43 timeout x comment "text message 43" -2.0.1.44 timeout x comment "text message 44" -2.0.1.45 timeout x comment "text message 45" -2.0.1.46 timeout x comment "text message 46" -2.0.1.47 timeout x comment "text message 47" -2.0.1.48 timeout x comment "text message 48" -2.0.1.49 timeout x comment "text message 49" -2.0.1.5 timeout x comment "text message 5" -2.0.1.50 timeout x comment "text message 50" -2.0.1.51 timeout x comment "text message 51" -2.0.1.52 timeout x comment "text message 52" -2.0.1.53 timeout x comment "text message 53" -2.0.1.54 timeout x comment "text message 54" -2.0.1.55 timeout x comment "text message 55" -2.0.1.56 timeout x comment "text message 56" -2.0.1.57 timeout x comment "text message 57" -2.0.1.58 timeout x comment "text message 58" -2.0.1.59 timeout x comment "text message 59" -2.0.1.6 timeout x comment "text message 6" -2.0.1.60 timeout x comment "text message 60" -2.0.1.61 timeout x comment "text message 61" -2.0.1.62 timeout x comment "text message 62" -2.0.1.63 timeout x comment "text message 63" -2.0.1.64 timeout x comment "text message 64" -2.0.1.65 timeout x comment "text message 65" -2.0.1.66 timeout x comment "text message 66" -2.0.1.67 timeout x comment "text message 67" -2.0.1.68 timeout x comment "text message 68" -2.0.1.69 timeout x comment "text message 69" -2.0.1.7 timeout x comment "text message 7" -2.0.1.70 timeout x comment "text message 70" -2.0.1.71 timeout x comment "text message 71" -2.0.1.72 timeout x comment "text message 72" -2.0.1.73 timeout x comment "text message 73" -2.0.1.74 timeout x comment "text message 74" -2.0.1.75 timeout x comment "text message 75" -2.0.1.76 timeout x comment "text message 76" -2.0.1.77 timeout x comment "text message 77" -2.0.1.78 timeout x comment "text message 78" -2.0.1.79 timeout x comment "text message 79" -2.0.1.8 timeout x comment "text message 8" -2.0.1.80 timeout x comment "text message 80" -2.0.1.81 timeout x comment "text message 81" -2.0.1.82 timeout x comment "text message 82" -2.0.1.83 timeout x comment "text message 83" -2.0.1.84 timeout x comment "text message 84" -2.0.1.85 timeout x comment "text message 85" -2.0.1.86 timeout x comment "text message 86" -2.0.1.87 timeout x comment "text message 87" -2.0.1.88 timeout x comment "text message 88" -2.0.1.89 timeout x comment "text message 89" -2.0.1.9 timeout x comment "text message 9" -2.0.1.90 timeout x comment "text message 90" -2.0.1.91 timeout x comment "text message 91" -2.0.1.92 timeout x comment "text message 92" -2.0.1.93 timeout x comment "text message 93" -2.0.1.94 timeout x comment "text message 94" -2.0.1.95 timeout x comment "text message 95" -2.0.1.96 timeout x comment "text message 96" -2.0.1.97 timeout x comment "text message 97" -2.0.1.98 timeout x comment "text message 98" -2.0.1.99 timeout x comment "text message 99" +2.0.1.0 timeout 0 comment "text message 0" +2.0.1.1 timeout 0 comment "text message 1" +2.0.1.10 timeout 0 comment "text message 10" +2.0.1.100 timeout 0 comment "text message 100" +2.0.1.101 timeout 0 comment "text message 101" +2.0.1.102 timeout 0 comment "text message 102" +2.0.1.103 timeout 0 comment "text message 103" +2.0.1.104 timeout 0 comment "text message 104" +2.0.1.105 timeout 0 comment "text message 105" +2.0.1.106 timeout 0 comment "text message 106" +2.0.1.107 timeout 0 comment "text message 107" +2.0.1.108 timeout 0 comment "text message 108" +2.0.1.109 timeout 0 comment "text message 109" +2.0.1.11 timeout 0 comment "text message 11" +2.0.1.110 timeout 0 comment "text message 110" +2.0.1.111 timeout 0 comment "text message 111" +2.0.1.112 timeout 0 comment "text message 112" +2.0.1.113 timeout 0 comment "text message 113" +2.0.1.114 timeout 0 comment "text message 114" +2.0.1.115 timeout 0 comment "text message 115" +2.0.1.116 timeout 0 comment "text message 116" +2.0.1.117 timeout 0 comment "text message 117" +2.0.1.118 timeout 0 comment "text message 118" +2.0.1.119 timeout 0 comment "text message 119" +2.0.1.12 timeout 0 comment "text message 12" +2.0.1.120 timeout 0 comment "text message 120" +2.0.1.121 timeout 0 comment "text message 121" +2.0.1.122 timeout 0 comment "text message 122" +2.0.1.123 timeout 0 comment "text message 123" +2.0.1.124 timeout 0 comment "text message 124" +2.0.1.125 timeout 0 comment "text message 125" +2.0.1.126 timeout 0 comment "text message 126" +2.0.1.127 timeout 0 comment "text message 127" +2.0.1.128 timeout 0 comment "text message 128" +2.0.1.129 timeout 0 comment "text message 129" +2.0.1.13 timeout 0 comment "text message 13" +2.0.1.130 timeout 0 comment "text message 130" +2.0.1.131 timeout 0 comment "text message 131" +2.0.1.132 timeout 0 comment "text message 132" +2.0.1.133 timeout 0 comment "text message 133" +2.0.1.134 timeout 0 comment "text message 134" +2.0.1.135 timeout 0 comment "text message 135" +2.0.1.136 timeout 0 comment "text message 136" +2.0.1.137 timeout 0 comment "text message 137" +2.0.1.138 timeout 0 comment "text message 138" +2.0.1.139 timeout 0 comment "text message 139" +2.0.1.14 timeout 0 comment "text message 14" +2.0.1.140 timeout 0 comment "text message 140" +2.0.1.141 timeout 0 comment "text message 141" +2.0.1.142 timeout 0 comment "text message 142" +2.0.1.143 timeout 0 comment "text message 143" +2.0.1.144 timeout 0 comment "text message 144" +2.0.1.145 timeout 0 comment "text message 145" +2.0.1.146 timeout 0 comment "text message 146" +2.0.1.147 timeout 0 comment "text message 147" +2.0.1.148 timeout 0 comment "text message 148" +2.0.1.149 timeout 0 comment "text message 149" +2.0.1.15 timeout 0 comment "text message 15" +2.0.1.150 timeout 0 comment "text message 150" +2.0.1.151 timeout 0 comment "text message 151" +2.0.1.152 timeout 0 comment "text message 152" +2.0.1.153 timeout 0 comment "text message 153" +2.0.1.154 timeout 0 comment "text message 154" +2.0.1.155 timeout 0 comment "text message 155" +2.0.1.156 timeout 0 comment "text message 156" +2.0.1.157 timeout 0 comment "text message 157" +2.0.1.158 timeout 0 comment "text message 158" +2.0.1.159 timeout 0 comment "text message 159" +2.0.1.16 timeout 0 comment "text message 16" +2.0.1.160 timeout 0 comment "text message 160" +2.0.1.161 timeout 0 comment "text message 161" +2.0.1.162 timeout 0 comment "text message 162" +2.0.1.163 timeout 0 comment "text message 163" +2.0.1.164 timeout 0 comment "text message 164" +2.0.1.165 timeout 0 comment "text message 165" +2.0.1.166 timeout 0 comment "text message 166" +2.0.1.167 timeout 0 comment "text message 167" +2.0.1.168 timeout 0 comment "text message 168" +2.0.1.169 timeout 0 comment "text message 169" +2.0.1.17 timeout 0 comment "text message 17" +2.0.1.170 timeout 0 comment "text message 170" +2.0.1.171 timeout 0 comment "text message 171" +2.0.1.172 timeout 0 comment "text message 172" +2.0.1.173 timeout 0 comment "text message 173" +2.0.1.174 timeout 0 comment "text message 174" +2.0.1.175 timeout 0 comment "text message 175" +2.0.1.176 timeout 0 comment "text message 176" +2.0.1.177 timeout 0 comment "text message 177" +2.0.1.178 timeout 0 comment "text message 178" +2.0.1.179 timeout 0 comment "text message 179" +2.0.1.18 timeout 0 comment "text message 18" +2.0.1.180 timeout 0 comment "text message 180" +2.0.1.181 timeout 0 comment "text message 181" +2.0.1.182 timeout 0 comment "text message 182" +2.0.1.183 timeout 0 comment "text message 183" +2.0.1.184 timeout 0 comment "text message 184" +2.0.1.185 timeout 0 comment "text message 185" +2.0.1.186 timeout 0 comment "text message 186" +2.0.1.187 timeout 0 comment "text message 187" +2.0.1.188 timeout 0 comment "text message 188" +2.0.1.189 timeout 0 comment "text message 189" +2.0.1.19 timeout 0 comment "text message 19" +2.0.1.190 timeout 0 comment "text message 190" +2.0.1.191 timeout 0 comment "text message 191" +2.0.1.192 timeout 0 comment "text message 192" +2.0.1.193 timeout 0 comment "text message 193" +2.0.1.194 timeout 0 comment "text message 194" +2.0.1.195 timeout 0 comment "text message 195" +2.0.1.196 timeout 0 comment "text message 196" +2.0.1.197 timeout 0 comment "text message 197" +2.0.1.198 timeout 0 comment "text message 198" +2.0.1.199 timeout 0 comment "text message 199" +2.0.1.2 timeout 0 comment "text message 2" +2.0.1.20 timeout 0 comment "text message 20" +2.0.1.200 timeout 0 comment "text message 200" +2.0.1.201 timeout 0 comment "text message 201" +2.0.1.202 timeout 0 comment "text message 202" +2.0.1.203 timeout 0 comment "text message 203" +2.0.1.204 timeout 0 comment "text message 204" +2.0.1.205 timeout 0 comment "text message 205" +2.0.1.206 timeout 0 comment "text message 206" +2.0.1.207 timeout 0 comment "text message 207" +2.0.1.208 timeout 0 comment "text message 208" +2.0.1.209 timeout 0 comment "text message 209" +2.0.1.21 timeout 0 comment "text message 21" +2.0.1.210 timeout 0 comment "text message 210" +2.0.1.211 timeout 0 comment "text message 211" +2.0.1.212 timeout 0 comment "text message 212" +2.0.1.213 timeout 0 comment "text message 213" +2.0.1.214 timeout 0 comment "text message 214" +2.0.1.215 timeout 0 comment "text message 215" +2.0.1.216 timeout 0 comment "text message 216" +2.0.1.217 timeout 0 comment "text message 217" +2.0.1.218 timeout 0 comment "text message 218" +2.0.1.219 timeout 0 comment "text message 219" +2.0.1.22 timeout 0 comment "text message 22" +2.0.1.220 timeout 0 comment "text message 220" +2.0.1.221 timeout 0 comment "text message 221" +2.0.1.222 timeout 0 comment "text message 222" +2.0.1.223 timeout 0 comment "text message 223" +2.0.1.224 timeout 0 comment "text message 224" +2.0.1.225 timeout 0 comment "text message 225" +2.0.1.226 timeout 0 comment "text message 226" +2.0.1.227 timeout 0 comment "text message 227" +2.0.1.228 timeout 0 comment "text message 228" +2.0.1.229 timeout 0 comment "text message 229" +2.0.1.23 timeout 0 comment "text message 23" +2.0.1.230 timeout 0 comment "text message 230" +2.0.1.231 timeout 0 comment "text message 231" +2.0.1.232 timeout 0 comment "text message 232" +2.0.1.233 timeout 0 comment "text message 233" +2.0.1.234 timeout 0 comment "text message 234" +2.0.1.235 timeout 0 comment "text message 235" +2.0.1.236 timeout 0 comment "text message 236" +2.0.1.237 timeout 0 comment "text message 237" +2.0.1.238 timeout 0 comment "text message 238" +2.0.1.239 timeout 0 comment "text message 239" +2.0.1.24 timeout 0 comment "text message 24" +2.0.1.240 timeout 0 comment "text message 240" +2.0.1.241 timeout 0 comment "text message 241" +2.0.1.242 timeout 0 comment "text message 242" +2.0.1.243 timeout 0 comment "text message 243" +2.0.1.244 timeout 0 comment "text message 244" +2.0.1.245 timeout 0 comment "text message 245" +2.0.1.246 timeout 0 comment "text message 246" +2.0.1.247 timeout 0 comment "text message 247" +2.0.1.248 timeout 0 comment "text message 248" +2.0.1.249 timeout 0 comment "text message 249" +2.0.1.25 timeout 0 comment "text message 25" +2.0.1.250 timeout 0 comment "text message 250" +2.0.1.251 timeout 0 comment "text message 251" +2.0.1.252 timeout 0 comment "text message 252" +2.0.1.253 timeout 0 comment "text message 253" +2.0.1.254 timeout 0 comment "text message 254" +2.0.1.255 timeout 0 comment "text message 255" +2.0.1.26 timeout 0 comment "text message 26" +2.0.1.27 timeout 0 comment "text message 27" +2.0.1.28 timeout 0 comment "text message 28" +2.0.1.29 timeout 0 comment "text message 29" +2.0.1.3 timeout 0 comment "text message 3" +2.0.1.30 timeout 0 comment "text message 30" +2.0.1.31 timeout 0 comment "text message 31" +2.0.1.32 timeout 0 comment "text message 32" +2.0.1.33 timeout 0 comment "text message 33" +2.0.1.34 timeout 0 comment "text message 34" +2.0.1.35 timeout 0 comment "text message 35" +2.0.1.36 timeout 0 comment "text message 36" +2.0.1.37 timeout 0 comment "text message 37" +2.0.1.38 timeout 0 comment "text message 38" +2.0.1.39 timeout 0 comment "text message 39" +2.0.1.4 timeout 0 comment "text message 4" +2.0.1.40 timeout 0 comment "text message 40" +2.0.1.41 timeout 0 comment "text message 41" +2.0.1.42 timeout 0 comment "text message 42" +2.0.1.43 timeout 0 comment "text message 43" +2.0.1.44 timeout 0 comment "text message 44" +2.0.1.45 timeout 0 comment "text message 45" +2.0.1.46 timeout 0 comment "text message 46" +2.0.1.47 timeout 0 comment "text message 47" +2.0.1.48 timeout 0 comment "text message 48" +2.0.1.49 timeout 0 comment "text message 49" +2.0.1.5 timeout 0 comment "text message 5" +2.0.1.50 timeout 0 comment "text message 50" +2.0.1.51 timeout 0 comment "text message 51" +2.0.1.52 timeout 0 comment "text message 52" +2.0.1.53 timeout 0 comment "text message 53" +2.0.1.54 timeout 0 comment "text message 54" +2.0.1.55 timeout 0 comment "text message 55" +2.0.1.56 timeout 0 comment "text message 56" +2.0.1.57 timeout 0 comment "text message 57" +2.0.1.58 timeout 0 comment "text message 58" +2.0.1.59 timeout 0 comment "text message 59" +2.0.1.6 timeout 0 comment "text message 6" +2.0.1.60 timeout 0 comment "text message 60" +2.0.1.61 timeout 0 comment "text message 61" +2.0.1.62 timeout 0 comment "text message 62" +2.0.1.63 timeout 0 comment "text message 63" +2.0.1.64 timeout 0 comment "text message 64" +2.0.1.65 timeout 0 comment "text message 65" +2.0.1.66 timeout 0 comment "text message 66" +2.0.1.67 timeout 0 comment "text message 67" +2.0.1.68 timeout 0 comment "text message 68" +2.0.1.69 timeout 0 comment "text message 69" +2.0.1.7 timeout 0 comment "text message 7" +2.0.1.70 timeout 0 comment "text message 70" +2.0.1.71 timeout 0 comment "text message 71" +2.0.1.72 timeout 0 comment "text message 72" +2.0.1.73 timeout 0 comment "text message 73" +2.0.1.74 timeout 0 comment "text message 74" +2.0.1.75 timeout 0 comment "text message 75" +2.0.1.76 timeout 0 comment "text message 76" +2.0.1.77 timeout 0 comment "text message 77" +2.0.1.78 timeout 0 comment "text message 78" +2.0.1.79 timeout 0 comment "text message 79" +2.0.1.8 timeout 0 comment "text message 8" +2.0.1.80 timeout 0 comment "text message 80" +2.0.1.81 timeout 0 comment "text message 81" +2.0.1.82 timeout 0 comment "text message 82" +2.0.1.83 timeout 0 comment "text message 83" +2.0.1.84 timeout 0 comment "text message 84" +2.0.1.85 timeout 0 comment "text message 85" +2.0.1.86 timeout 0 comment "text message 86" +2.0.1.87 timeout 0 comment "text message 87" +2.0.1.88 timeout 0 comment "text message 88" +2.0.1.89 timeout 0 comment "text message 89" +2.0.1.9 timeout 0 comment "text message 9" +2.0.1.90 timeout 0 comment "text message 90" +2.0.1.91 timeout 0 comment "text message 91" +2.0.1.92 timeout 0 comment "text message 92" +2.0.1.93 timeout 0 comment "text message 93" +2.0.1.94 timeout 0 comment "text message 94" +2.0.1.95 timeout 0 comment "text message 95" +2.0.1.96 timeout 0 comment "text message 96" +2.0.1.97 timeout 0 comment "text message 97" +2.0.1.98 timeout 0 comment "text message 98" +2.0.1.99 timeout 0 comment "text message 99" diff --git a/tests/comment.t.list3 b/tests/comment.t.list3 index 673678a..b6eab32 100644 --- a/tests/comment.t.list3 +++ b/tests/comment.t.list3 @@ -1,31 +1,35 @@ Name: a Type: hash:ip -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 152 +Revision: 5 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xe2558329 +Size in memory: 336 References: 1 Number of entries: 0 Members: Name: b Type: hash:ip -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 152 +Revision: 5 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x0dfa7d5d +Size in memory: 336 References: 1 Number of entries: 0 Members: Name: c Type: hash:ip -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 152 +Revision: 5 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x8fada201 +Size in memory: 336 References: 1 Number of entries: 0 Members: Name: test Type: list:set +Revision: 3 Header: size 8 comment -Size in memory: 288 +Size in memory: 378 References: 0 Number of entries: 3 Members: diff --git a/tests/diff.sh b/tests/diff.sh new file mode 100755 index 0000000..a364a28 --- /dev/null +++ b/tests/diff.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +diff -u -I 'Revision: .*' -I 'Size in memory.*' \ + <(sed -e 's/timeout [0-9]*/timeout x/' -e 's/initval 0x[0-9a-fA-F]\{8\}/initval 0x00000000/' $1) \ + <(sed -e 's/timeout [0-9]*/timeout x/' -e 's/initval 0x[0-9a-fA-F]\{8\}/initval 0x00000000/' $2) + + diff --git a/tests/hash:ip,mark.t b/tests/hash:ip,mark.t index 9c51201..ce94efc 100644 --- a/tests/hash:ip,mark.t +++ b/tests/hash:ip,mark.t @@ -27,15 +27,15 @@ # Try to add value after second random value 0 ipset add test 2.1.0.1,0x80 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip,mark.t.list0 +0 ./diff.sh .foo hash:ip,mark.t.list0 # Sleep 5s so that elements can time out 0 sleep 5 # List set -0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip,mark.t.list1 +0 ./diff.sh .foo hash:ip,mark.t.list1 # Flush test set 0 ipset flush test # Add multiple elements in one step diff --git a/tests/hash:ip,mark.t.list0 b/tests/hash:ip,mark.t.list0 index 3866bf5..1df024f 100644 --- a/tests/hash:ip,mark.t.list0 +++ b/tests/hash:ip,mark.t.list0 @@ -1,11 +1,12 @@ Name: test Type: hash:ip,mark -Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 timeout x -Size in memory: 640 +Revision: 3 +Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x30edb64c +Size in memory: 592 References: 0 Number of entries: 4 Members: -2.0.0.0,0x00000005 timeout x -2.0.0.1,0x00000005 timeout x -2.1.0.0,0x00000080 timeout x -2.1.0.1,0x00000080 timeout x +2.0.0.0,0x00000005 timeout 3 +2.0.0.1,0x00000005 timeout 3 +2.1.0.0,0x00000080 timeout 3 +2.1.0.1,0x00000080 timeout 3 diff --git a/tests/hash:ip,mark.t.list1 b/tests/hash:ip,mark.t.list1 index c959e4c..34fafcc 100644 --- a/tests/hash:ip,mark.t.list1 +++ b/tests/hash:ip,mark.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,mark -Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4 -Size in memory: 536 +Revision: 3 +Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x139cd632 +Size in memory: 592 References: 0 Number of entries: 0 Members: diff --git a/tests/hash:ip,port,ip.t b/tests/hash:ip,port,ip.t index 8a6954e..fcd6985 100644 --- a/tests/hash:ip,port,ip.t +++ b/tests/hash:ip,port,ip.t @@ -35,15 +35,15 @@ # Try to add value after second random value 0 ipset add test 2.1.0.1,128,2.2.2.2 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip,port,ip.t.list0 +0 ./diff.sh .foo hash:ip,port,ip.t.list0 # Sleep 5s so that elements can time out 0 sleep 5 # List set -0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip,port,ip.t.list1 +0 ./diff.sh .foo hash:ip,port,ip.t.list1 # Flush test set 0 ipset flush test # Add multiple elements in one step diff --git a/tests/hash:ip,port,ip.t.list0 b/tests/hash:ip,port,ip.t.list0 index 57adef1..f34c24a 100644 --- a/tests/hash:ip,port,ip.t.list0 +++ b/tests/hash:ip,port,ip.t.list0 @@ -1,11 +1,12 @@ Name: test Type: hash:ip,port,ip -Header: family inet hashsize 1024 maxelem 65536 timeout x -Size in memory: 840 +Revision: 6 +Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x7713f039 +Size in memory: 664 References: 0 Number of entries: 4 Members: -2.0.0.0,tcp:5,1.1.1.1 timeout x -2.0.0.1,tcp:5,1.1.1.1 timeout x -2.1.0.0,tcp:128,2.2.2.2 timeout x -2.1.0.1,tcp:128,2.2.2.2 timeout x +2.0.0.0,tcp:5,1.1.1.1 timeout 3 +2.0.0.1,tcp:5,1.1.1.1 timeout 3 +2.1.0.0,tcp:128,2.2.2.2 timeout 3 +2.1.0.1,tcp:128,2.2.2.2 timeout 3 diff --git a/tests/hash:ip,port,ip.t.list1 b/tests/hash:ip,port,ip.t.list1 index 7c7d560..e81e0ec 100644 --- a/tests/hash:ip,port,ip.t.list1 +++ b/tests/hash:ip,port,ip.t.list1 @@ -1,6 +1,7 @@ Name: test Type: hash:ip,port,ip -Header: family inet hashsize 1024 maxelem 65536 timeout 4 +Revision: 6 +Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x87fc0d22 Size in memory: 664 References: 0 Number of entries: 0 diff --git a/tests/hash:ip,port,net.t b/tests/hash:ip,port,net.t index 487f563..67d20b0 100644 --- a/tests/hash:ip,port,net.t +++ b/tests/hash:ip,port,net.t @@ -27,9 +27,9 @@ # Try to add value after second random value 0 ipset add test 2.1.0.1,128,10.0.0.0/17 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip,port,net.t.list0 +0 ./diff.sh .foo hash:ip,port,net.t.list0 # Sleep 5s so that elements can time out 0 sleep 5 # List set diff --git a/tests/hash:ip,port,net.t.list0 b/tests/hash:ip,port,net.t.list0 index 44c53c5..45ab21c 100644 --- a/tests/hash:ip,port,net.t.list0 +++ b/tests/hash:ip,port,net.t.list0 @@ -1,11 +1,12 @@ Name: test Type: hash:ip,port,net -Header: family inet hashsize 1024 maxelem 65536 timeout x -Size in memory: 1096 +Revision: 8 +Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x882e1e10 +Size in memory: 920 References: 0 Number of entries: 4 Members: -2.0.0.0,tcp:5,192.168.0.0/25 timeout x -2.0.0.1,tcp:5,192.168.0.0/24 timeout x -2.1.0.0,tcp:128,10.0.0.0/16 timeout x -2.1.0.1,tcp:128,10.0.0.0/17 timeout x +2.0.0.0,tcp:5,192.168.0.0/25 timeout 3 +2.0.0.1,tcp:5,192.168.0.0/24 timeout 3 +2.1.0.0,tcp:128,10.0.0.0/16 timeout 3 +2.1.0.1,tcp:128,10.0.0.0/17 timeout 3 diff --git a/tests/hash:ip,port.t b/tests/hash:ip,port.t index aba8fdc..f65fb59 100644 --- a/tests/hash:ip,port.t +++ b/tests/hash:ip,port.t @@ -31,15 +31,15 @@ # Delete port by number 0 ipset del test 2.1.0.3,25 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip,port.t.list0 +0 ./diff.sh .foo hash:ip,port.t.list0 # Sleep 5s so that elements can time out 0 sleep 5 # List set -0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip,port.t.list1 +0 ./diff.sh .foo hash:ip,port.t.list1 # Flush test set 0 ipset flush test # Add multiple elements in one step @@ -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 @@ -73,9 +73,9 @@ # Delete element with sctp 0 ipset del test 2.0.0.1,sctp:80 # List set -0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip,port.t.list2 +0 ./diff.sh .foo hash:ip,port.t.list2 # Delete set 0 ipset destroy test # Create set to add a range @@ -170,4 +170,122 @@ 0 ./check_extensions test 2.0.0.20 700 13 12479 # Counters and timeout: destroy set 0 ipset x test +# Network: Create a set with timeout and netmask +0 ipset -N test hash:ip,port --hashsize 128 --netmask 24 timeout 4 +# Network: Add zero valued element +1 ipset -A test 0.0.0.0,80 +# Network: Test zero valued element +1 ipset -T test 0.0.0.0,80 +# Network: Delete zero valued element +1 ipset -D test 0.0.0.0,80 +# Network: Add first random network +0 ipset -A test 2.0.0.1,8080 +# Network: Add second random network +0 ipset -A test 192.168.68.69,22 +# Network: Test first random value +0 ipset -T test 2.0.0.255,8080 +# Network: Test second random value +0 ipset -T test 192.168.68.95,22 +# Network: Test value not added to the set +1 ipset -T test 2.0.1.0,8080 +# Network: Add third element +0 ipset -A test 200.100.10.1,22 timeout 0 +# Network: Add third random network +0 ipset -A test 200.100.0.12,22 +# Network: Delete the same network +0 ipset -D test 200.100.0.12,22 +# Network: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Network: Check listing +0 ./diff.sh .foo hash:ip,port.t.list3 +# Sleep 5s so that elements can time out +0 sleep 5 +# Network: List set +0 ipset -L test > .foo +# Network: Check listing +0 ./diff.sh .foo hash:ip,port.t.list4 +# Network: Flush test set +0 ipset -F test +# Network: add element with 1s timeout +0 ipset add test 200.100.0.12,80 timeout 1 +# Network: readd element with 3s timeout +0 ipset add test 200.100.0.12,80 timeout 3 -exist +# Network: sleep 2s +0 sleep 2s +# Network: check readded element +0 ipset test test 200.100.0.12,80 +# Network: Delete test set +0 ipset -X test +# Network: Create a set with timeout and bitmask +0 ipset -N test hash:ip,port --hashsize 128 --bitmask 255.255.255.0 timeout 4 +# Network: Add zero valued element +1 ipset -A test 0.0.0.0,80 +# Network: Test zero valued element +1 ipset -T test 0.0.0.0,80 +# Network: Delete zero valued element +1 ipset -D test 0.0.0.0,80 +# Network: Add first random network +0 ipset -A test 2.0.0.1,8080 +# Network: Add second random network +0 ipset -A test 192.168.68.69,22 +# Network: Test first random value +0 ipset -T test 2.0.0.255,8080 +# Network: Test second random value +0 ipset -T test 192.168.68.95,22 +# Network: Test value not added to the set +1 ipset -T test 2.0.1.0,8080 +# Network: Add third element +0 ipset -A test 200.100.10.1,22 timeout 0 +# Network: Add third random network +0 ipset -A test 200.100.0.12,22 +# Network: Delete the same network +0 ipset -D test 200.100.0.12,22 +# Network: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Network: Check listing +0 ./diff.sh .foo hash:ip,port.t.list5 +# Sleep 5s so that elements can time out +0 sleep 5 +# Network: List set +0 ipset -L test > .foo +# Network: Check listing +0 ./diff.sh .foo hash:ip,port.t.list6 +# Network: Flush test set +0 ipset -F test +# Network: add element with 1s timeout +0 ipset add test 200.100.0.12,80 timeout 1 +# Network: readd element with 3s timeout +0 ipset add test 200.100.0.12,80 timeout 3 -exist +# Network: sleep 2s +0 sleep 2s +# Network: check readded element +0 ipset test test 200.100.0.12,80 +# Network: Delete test set +0 ipset -X test +# Network: Create a set with bitmask which is not a valid netmask +0 ipset -N test hash:ip,port --hashsize 128 --bitmask 255.255.0.255 +# Network: Add zero valued element +1 ipset -A test 0.0.0.0 +# Network: Test zero valued element +1 ipset -T test 0.0.0.0 +# Network: Delete zero valued element +1 ipset -D test 0.0.0.0 +# Network: Add first random network +0 ipset -A test 1.2.3.4,22 +# Network: Add second random network +0 ipset -A test 1.168.122.124,22 +# Network: Test first random value +0 ipset -T test 1.2.9.4,22 +# Network: Test second random value +0 ipset -T test 1.168.68.124,22 +# Network: Test value not added to the set +1 ipset -T test 2.0.1.0,23 +# Network: Test delete value +0 ipset -D test 1.168.0.124,22 +# Network: List set +0 ipset -L test > .foo +# Network: Check listing +0 ./diff.sh .foo hash:ip,port.t.list7 +# Network: Delete test set +0 ipset -X test # eof diff --git a/tests/hash:ip,port.t.list0 b/tests/hash:ip,port.t.list0 index 49e3033..b1541f5 100644 --- a/tests/hash:ip,port.t.list0 +++ b/tests/hash:ip,port.t.list0 @@ -1,11 +1,12 @@ Name: test Type: hash:ip,port -Header: family inet hashsize 1024 maxelem 65536 timeout x -Size in memory: 640 +Revision: 6 +Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0xf8e65168 +Size in memory: 592 References: 0 Number of entries: 4 Members: -2.0.0.0,tcp:5 timeout x -2.0.0.1,tcp:5 timeout x -2.1.0.0,tcp:128 timeout x -2.1.0.1,tcp:128 timeout x +2.0.0.0,tcp:5 timeout 3 +2.0.0.1,tcp:5 timeout 3 +2.1.0.0,tcp:128 timeout 3 +2.1.0.1,tcp:128 timeout 3 diff --git a/tests/hash:ip,port.t.list1 b/tests/hash:ip,port.t.list1 index 4b79124..4471ce6 100644 --- a/tests/hash:ip,port.t.list1 +++ b/tests/hash:ip,port.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,port -Header: family inet hashsize 1024 maxelem 65536 timeout 4 -Size in memory: 528 +Revision: 6 +Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x881c5fa0 +Size in memory: 592 References: 0 Number of entries: 0 Members: diff --git a/tests/hash:ip,port.t.list2 b/tests/hash:ip,port.t.list2 index 624d050..2550422 100644 --- a/tests/hash:ip,port.t.list2 +++ b/tests/hash:ip,port.t.list2 @@ -1,10 +1,11 @@ Name: test Type: hash:ip,port -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 320 +Revision: 6 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x819addf6 +Size in memory: 480 References: 0 Number of entries: 3 Members: +2.0.0.1,gre:0 2.0.0.1,tcp:80 2.0.0.1,udp:80 -2.0.0.1,vrrp:0 diff --git a/tests/hash:ip,port.t.list3 b/tests/hash:ip,port.t.list3 new file mode 100644 index 0000000..b2cdc28 --- /dev/null +++ b/tests/hash:ip,port.t.list3 @@ -0,0 +1,11 @@ +Name: test +Type: hash:ip,port +Revision: 7 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xf49ba001 netmask 24 +Size in memory: 408 +References: 0 +Number of entries: 3 +Members: +192.168.68.0,tcp:22 timeout 3 +2.0.0.0,tcp:8080 timeout 3 +200.100.10.0,tcp:22 timeout 0 diff --git a/tests/hash:ip,port.t.list4 b/tests/hash:ip,port.t.list4 new file mode 100644 index 0000000..c28987a --- /dev/null +++ b/tests/hash:ip,port.t.list4 @@ -0,0 +1,9 @@ +Name: test +Type: hash:ip,port +Revision: 7 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x18b2277a netmask 24 +Size in memory: 408 +References: 0 +Number of entries: 1 +Members: +200.100.10.0,tcp:22 timeout 0 diff --git a/tests/hash:ip,port.t.list5 b/tests/hash:ip,port.t.list5 new file mode 100644 index 0000000..b5fa817 --- /dev/null +++ b/tests/hash:ip,port.t.list5 @@ -0,0 +1,11 @@ +Name: test +Type: hash:ip,port +Revision: 7 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x6a0e903a bitmask 255.255.255.0 +Size in memory: 408 +References: 0 +Number of entries: 3 +Members: +192.168.68.0,tcp:22 timeout 3 +2.0.0.0,tcp:8080 timeout 3 +200.100.10.0,tcp:22 timeout 0 diff --git a/tests/hash:ip,port.t.list6 b/tests/hash:ip,port.t.list6 new file mode 100644 index 0000000..33969cf --- /dev/null +++ b/tests/hash:ip,port.t.list6 @@ -0,0 +1,9 @@ +Name: test +Type: hash:ip,port +Revision: 7 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x2fcffdca bitmask 255.255.255.0 +Size in memory: 408 +References: 0 +Number of entries: 1 +Members: +200.100.10.0,tcp:22 timeout 0 diff --git a/tests/hash:ip,port.t.list7 b/tests/hash:ip,port.t.list7 new file mode 100644 index 0000000..f223657 --- /dev/null +++ b/tests/hash:ip,port.t.list7 @@ -0,0 +1,9 @@ +Name: test +Type: hash:ip,port +Revision: 7 +Header: family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x98bdfa72 bitmask 255.255.0.255 +Size in memory: 312 +References: 0 +Number of entries: 1 +Members: +1.2.0.4,tcp:22 diff --git a/tests/hash:ip.t b/tests/hash:ip.t index 36b82f9..3771437 100644 --- a/tests/hash:ip.t +++ b/tests/hash:ip.t @@ -19,15 +19,15 @@ # IP: Delete the same value 0 ipset -D test 200.100.0.12 # IP: List set -0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # IP: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip.t.list2 +0 ./diff.sh .foo hash:ip.t.list2 # Sleep 5s so that element can time out 0 sleep 5 # IP: List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # IP: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip.t.list0 +0 ./diff.sh .foo hash:ip.t.list0 # IP: Flush test set 0 ipset -F test # IP: Add multiple elements in one step @@ -72,7 +72,7 @@ 0 n=`ipset list test|grep '^10.0'|wc -l` && test $n -eq 1024 # IP: Destroy sets 0 ipset -X -# Network: Create a set with timeout +# Network: Create a set with timeout and netmask 0 ipset -N test iphash --hashsize 128 --netmask 24 timeout 4 # Network: Add zero valued element 1 ipset -A test 0.0.0.0 @@ -97,15 +97,15 @@ # Network: Delete the same network 0 ipset -D test 200.100.0.12 # Network: List set -0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Network: Check listing -0 diff -u -I 'Size in memory.*' -I 'Size in memory.*' .foo hash:ip.t.list3 +0 ./diff.sh .foo hash:ip.t.list3 # Sleep 5s so that elements can time out 0 sleep 5 # Network: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Network: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip.t.list1 +0 ./diff.sh .foo hash:ip.t.list1 # Network: Flush test set 0 ipset -F test # Network: add element with 1s timeout @@ -136,6 +136,12 @@ 0 ipset del test 10.0.0.1-10.0.0.10 # Range: Check number of elements 0 n=`ipset save test|wc -l` && test $n -eq 1 +# Range: Flush set +0 ipset flush test +# Range: Add elements in multiple internal batches +0 ipset add test 10.1.0.0-10.1.64.255 +# Range: Check number of elements +0 n=`ipset save test|grep '^add test 10.1' | wc -l` && test $n -eq 16640 # Range: Delete test set 0 ipset destroy test # Timeout: Check that resizing keeps timeout values @@ -210,4 +216,78 @@ skip which sendip 0 ./check_extensions test 10.255.255.64 600 6 $((6*40)) # Counters and timeout: destroy set 0 ipset x test +# Network: Create a set with timeout and bitmask +0 ipset -N test iphash --hashsize 128 --bitmask 255.255.255.0 timeout 4 +# Network: Add zero valued element +1 ipset -A test 0.0.0.0 +# Network: Test zero valued element +1 ipset -T test 0.0.0.0 +# Network: Delete zero valued element +1 ipset -D test 0.0.0.0 +# Network: Add first random network +0 ipset -A test 2.0.0.1 +# Network: Add second random network +0 ipset -A test 192.168.68.69 +# Network: Test first random value +0 ipset -T test 2.0.0.255 +# Network: Test second random value +0 ipset -T test 192.168.68.95 +# Network: Test value not added to the set +1 ipset -T test 2.0.1.0 +# Network: Add third element +0 ipset -A test 200.100.10.1 timeout 0 +# Network: Add third random network +0 ipset -A test 200.100.0.12 +# Network: Delete the same network +0 ipset -D test 200.100.0.12 +# Network: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Network: Check listing +0 ./diff.sh .foo hash:ip.t.list4 +# Sleep 5s so that elements can time out +0 sleep 5 +# Network: List set +0 ipset -L test > .foo +# Network: Check listing +0 ./diff.sh .foo hash:ip.t.list5 +# Network: Flush test set +0 ipset -F test +# Network: add element with 1s timeout +0 ipset add test 200.100.0.12 timeout 1 +# Network: readd element with 3s timeout +0 ipset add test 200.100.0.12 timeout 3 -exist +# Network: sleep 2s +0 sleep 2s +# Network: check readded element +0 ipset test test 200.100.0.12 +# Network: Delete test set +0 ipset -X test +# Network: Create a set with both bitmask and netmask +1 ipset -N test iphash --hashsize 128 --bitmask 255.255.0.255 --netmask 24 +# Network: Create a set with bitmask which is not a valid netmask +0 ipset -N test iphash --hashsize 128 --bitmask 255.255.0.255 +# Network: Add zero valued element +1 ipset -A test 0.0.0.0 +# Network: Test zero valued element +1 ipset -T test 0.0.0.0 +# Network: Delete zero valued element +1 ipset -D test 0.0.0.0 +# Network: Add first random network +0 ipset -A test 1.2.3.4 +# Network: Add second random network +0 ipset -A test 1.2.4.5 +# Network: Test first random value +0 ipset -T test 1.2.9.4 +# Network: Test second random value +0 ipset -T test 1.2.9.5 +# Network: Test value not added to the set +1 ipset -T test 2.0.1.0 +# Network: Test delete value +0 ipset -D test 1.2.0.5 +# Network: List set +0 ipset -L test > .foo +# Network: Check listing +0 ./diff.sh .foo hash:ip.t.list6 +# Network: Delete test set +0 ipset -X test # eof diff --git a/tests/hash:ip.t.list0 b/tests/hash:ip.t.list0 index 1859015..efa642f 100644 --- a/tests/hash:ip.t.list0 +++ b/tests/hash:ip.t.list0 @@ -1,7 +1,7 @@ Name: test Type: hash:ip -Header: family inet hashsize 128 maxelem 65536 timeout 4 -Size in memory: 336 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x00000000 +Size in memory: 464 References: 0 Number of entries: 1 Members: diff --git a/tests/hash:ip.t.list1 b/tests/hash:ip.t.list1 index 0977324..5b832d9 100644 --- a/tests/hash:ip.t.list1 +++ b/tests/hash:ip.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:ip -Header: family inet hashsize 128 maxelem 65536 netmask 24 timeout 4 -Size in memory: 432 +Revision: 5 +Header: family inet hashsize 128 maxelem 65536 netmask 24 timeout 4 bucketsize 12 initval 0xbc66e38a +Size in memory: 528 References: 0 Number of entries: 1 Members: diff --git a/tests/hash:ip.t.list2 b/tests/hash:ip.t.list2 index 6cd2bf4..3198a72 100644 --- a/tests/hash:ip.t.list2 +++ b/tests/hash:ip.t.list2 @@ -1,9 +1,10 @@ Name: test Type: hash:ip -Header: family inet hashsize 128 maxelem 65536 timeout x -Size in memory: 352 +Revision: 5 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x3723bb8f +Size in memory: 464 References: 0 Number of entries: 2 Members: -192.168.68.69 timeout x -2.0.0.1 timeout x +192.168.68.69 timeout 0 +2.0.0.1 timeout 3 diff --git a/tests/hash:ip.t.list3 b/tests/hash:ip.t.list3 index 500abbc..a68b731 100644 --- a/tests/hash:ip.t.list3 +++ b/tests/hash:ip.t.list3 @@ -1,10 +1,11 @@ Name: test Type: hash:ip -Header: family inet hashsize 128 maxelem 65536 netmask 24 timeout x -Size in memory: 464 +Revision: 5 +Header: family inet hashsize 128 maxelem 65536 netmask 24 timeout 4 bucketsize 12 initval 0xfe970e91 +Size in memory: 528 References: 0 Number of entries: 3 Members: -192.168.68.0 timeout x -2.0.0.0 timeout x -200.100.10.0 timeout x +192.168.68.0 timeout 3 +2.0.0.0 timeout 3 +200.100.10.0 timeout 0 diff --git a/tests/hash:ip.t.list4 b/tests/hash:ip.t.list4 new file mode 100644 index 0000000..5f92afa --- /dev/null +++ b/tests/hash:ip.t.list4 @@ -0,0 +1,11 @@ +Name: test +Type: hash:ip +Revision: 5 +Header: family inet hashsize 128 maxelem 65536 bitmask 255.255.255.0 timeout 4 bucketsize 12 initval 0xfe970e91 +Size in memory: 528 +References: 0 +Number of entries: 3 +Members: +192.168.68.0 timeout 3 +2.0.0.0 timeout 3 +200.100.10.0 timeout 0 diff --git a/tests/hash:ip.t.list5 b/tests/hash:ip.t.list5 new file mode 100644 index 0000000..9a29e75 --- /dev/null +++ b/tests/hash:ip.t.list5 @@ -0,0 +1,9 @@ +Name: test +Type: hash:ip +Revision: 5 +Header: family inet hashsize 128 maxelem 65536 bitmask 255.255.255.0 timeout 4 bucketsize 12 initval 0xbc66e38a +Size in memory: 528 +References: 0 +Number of entries: 1 +Members: +200.100.10.0 timeout 0 diff --git a/tests/hash:ip.t.list6 b/tests/hash:ip.t.list6 new file mode 100644 index 0000000..44c5a49 --- /dev/null +++ b/tests/hash:ip.t.list6 @@ -0,0 +1,9 @@ +Name: test +Type: hash:ip +Revision: 6 +Header: family inet hashsize 128 maxelem 65536 bitmask 255.255.0.255 bucketsize 12 initval 0xd7d821e1 +Size in memory: 296 +References: 0 +Number of entries: 1 +Members: +1.2.0.4 diff --git a/tests/hash:ip6,mark.t b/tests/hash:ip6,mark.t index 8f50acf..af46d97 100644 --- a/tests/hash:ip6,mark.t +++ b/tests/hash:ip6,mark.t @@ -27,15 +27,15 @@ # Try to add value after second random value 0 ipset add test 2:1:0::1,0x80 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6,mark.t.list0 +0 ./diff.sh .foo hash:ip6,mark.t.list0 # Sleep 5s so that elements can time out 0 sleep 5 # List set -0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6,mark.t.list1 +0 ./diff.sh .foo hash:ip6,mark.t.list1 # Delete test set 0 ipset destroy test # Create set to add a range diff --git a/tests/hash:ip6,mark.t.list0 b/tests/hash:ip6,mark.t.list0 index be7c069..39a48f6 100644 --- a/tests/hash:ip6,mark.t.list0 +++ b/tests/hash:ip6,mark.t.list0 @@ -1,11 +1,12 @@ Name: test Type: hash:ip,mark -Header: family inet6 markmask 0xffffffff hashsize 1024 maxelem 65536 timeout x -Size in memory: 1088 +Revision: 3 +Header: family inet6 markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x861e4c6a +Size in memory: 736 References: 0 Number of entries: 4 Members: -2:1::,0x00000080 timeout x -2:1::1,0x00000080 timeout x -2::,0x00000005 timeout x -2::1,0x00000005 timeout x +2:1::,0x00000080 timeout 3 +2:1::1,0x00000080 timeout 3 +2::,0x00000005 timeout 3 +2::1,0x00000005 timeout 3 diff --git a/tests/hash:ip6,mark.t.list1 b/tests/hash:ip6,mark.t.list1 index 5c7b730..b2c4dd2 100644 --- a/tests/hash:ip6,mark.t.list1 +++ b/tests/hash:ip6,mark.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,mark -Header: family inet6 markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4 -Size in memory: 800 +Revision: 3 +Header: family inet6 markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x8e5240e7 +Size in memory: 736 References: 0 Number of entries: 0 Members: diff --git a/tests/hash:ip6,port,ip6.t b/tests/hash:ip6,port,ip6.t index e8a75f0..aaf6530 100644 --- a/tests/hash:ip6,port,ip6.t +++ b/tests/hash:ip6,port,ip6.t @@ -35,15 +35,15 @@ # Try to add value after second random value 0 ipset add test 2:1:0::1,128,2:2:2::2 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6,port,ip6.t.list0 +0 ./diff.sh .foo hash:ip6,port,ip6.t.list0 # Sleep 5s so that elements can time out 0 sleep 5 # List set -0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6,port,ip6.t.list1 +0 ./diff.sh .foo hash:ip6,port,ip6.t.list1 # Flush test set 0 ipset flush test # Add multiple elements in one step diff --git a/tests/hash:ip6,port,ip6.t.list0 b/tests/hash:ip6,port,ip6.t.list0 index 6fc6771..a7aaced 100644 --- a/tests/hash:ip6,port,ip6.t.list0 +++ b/tests/hash:ip6,port,ip6.t.list0 @@ -1,12 +1,12 @@ Name: test Type: hash:ip,port,ip -Header: family inet6 hashsize 1024 maxelem 65536 timeout x -Size in memory: 1608 +Revision: 6 +Header: family inet6 hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0xae2818a9 +Size in memory: 880 References: 0 -Size in memory: 9104 Number of entries: 4 Members: -2:1::,tcp:128,2:2:2::2 timeout x -2:1::1,tcp:128,2:2:2::2 timeout x -2::,tcp:5,1:1:1::1 timeout x -2::1,tcp:5,1:1:1::1 timeout x +2:1::,tcp:128,2:2:2::2 timeout 3 +2:1::1,tcp:128,2:2:2::2 timeout 3 +2::,tcp:5,1:1:1::1 timeout 3 +2::1,tcp:5,1:1:1::1 timeout 3 diff --git a/tests/hash:ip6,port,ip6.t.list1 b/tests/hash:ip6,port,ip6.t.list1 index d3b61b7..1e735c1 100644 --- a/tests/hash:ip6,port,ip6.t.list1 +++ b/tests/hash:ip6,port,ip6.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,port,ip -Header: family inet6 hashsize 1024 maxelem 65536 timeout 4 -Size in memory: 1072 +Revision: 6 +Header: family inet6 hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0xb9a9f4a5 +Size in memory: 880 References: 0 Number of entries: 0 Members: diff --git a/tests/hash:ip6,port,net6.t b/tests/hash:ip6,port,net6.t index 23a5da0..71dfa61 100644 --- a/tests/hash:ip6,port,net6.t +++ b/tests/hash:ip6,port,net6.t @@ -35,9 +35,9 @@ # Range: Try to add value after second random value 0 ipset -A test 2:1:0::1,128,2:2:2::2/12 # Range: List set -0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Range: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6,port,net6.t.list0 +0 ./diff.sh .foo hash:ip6,port,net6.t.list0 # Range: Flush test set 0 ipset -F test # Range: Delete test set diff --git a/tests/hash:ip6,port,net6.t.list0 b/tests/hash:ip6,port,net6.t.list0 index ad8ea8f..3e92bee 100644 --- a/tests/hash:ip6,port,net6.t.list0 +++ b/tests/hash:ip6,port,net6.t.list0 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,port,net -Header: family inet6 hashsize 1024 maxelem 65536 -Size in memory: 1864 +Revision: 8 +Header: family inet6 hashsize 1024 maxelem 65536 bucketsize 12 initval 0xa5d3d0fa +Size in memory: 1808 References: 0 Number of entries: 4 Members: diff --git a/tests/hash:ip6,port.t b/tests/hash:ip6,port.t index a47ca6e..e56e39c 100644 --- a/tests/hash:ip6,port.t +++ b/tests/hash:ip6,port.t @@ -27,15 +27,15 @@ # Try to add value after second random value 0 ipset add test 2:1:0::1,128 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6,port.t.list0 +0 ./diff.sh .foo hash:ip6,port.t.list0 # Sleep 5s so that elements can time out 0 sleep 5 # List set -0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6,port.t.list1 +0 ./diff.sh .foo hash:ip6,port.t.list1 # Flush test set 0 ipset flush test # Add multiple elements in one step diff --git a/tests/hash:ip6,port.t.list0 b/tests/hash:ip6,port.t.list0 index 926c4ec..9fca34a 100644 --- a/tests/hash:ip6,port.t.list0 +++ b/tests/hash:ip6,port.t.list0 @@ -1,11 +1,12 @@ Name: test Type: hash:ip,port -Header: family inet6 hashsize 1024 maxelem 65536 timeout x -Size in memory: 1088 +Revision: 6 +Header: family inet6 hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x013bd339 +Size in memory: 736 References: 0 Number of entries: 4 Members: -2:1::,tcp:128 timeout x -2:1::1,tcp:128 timeout x -2::,tcp:5 timeout x -2::1,tcp:5 timeout x +2:1::,tcp:128 timeout 3 +2:1::1,tcp:128 timeout 3 +2::,tcp:5 timeout 3 +2::1,tcp:5 timeout 3 diff --git a/tests/hash:ip6,port.t.list1 b/tests/hash:ip6,port.t.list1 index d707af5..46fdea2 100644 --- a/tests/hash:ip6,port.t.list1 +++ b/tests/hash:ip6,port.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,port -Header: family inet6 hashsize 1024 maxelem 65536 timeout 4 -Size in memory: 800 +Revision: 6 +Header: family inet6 hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x9f983aa9 +Size in memory: 736 References: 0 Number of entries: 0 Members: diff --git a/tests/hash:ip6.t b/tests/hash:ip6.t index 5edc267..52175a5 100644 --- a/tests/hash:ip6.t +++ b/tests/hash:ip6.t @@ -21,25 +21,25 @@ # IP: Delete the same value 0 ipset -D test 200:100:0::12 # IP: List set -0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # IP: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6.t.list2 +0 ./diff.sh .foo hash:ip6.t.list2 # IP: Save set 0 ipset save test > hash:ip6.t.restore # Sleep 5s so that element can time out 0 sleep 5 # IP: List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # IP: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6.t.list0 +0 ./diff.sh .foo hash:ip6.t.list0 # IP: Destroy set 0 ipset x test # IP: Restore saved set 0 ipset restore < hash:ip6.t.restore && rm hash:ip6.t.restore # IP: List set -0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # IP: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6.t.list2 +0 ./diff.sh .foo hash:ip6.t.list2 # IP: Flush test set 0 ipset -F test # IP: Try to add multiple elements in one step @@ -73,15 +73,15 @@ # Network: Test the deleted network 1 ipset -T test 200:101:0::12 # Network: List set -0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Network: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6.t.list3 +0 ./diff.sh .foo hash:ip6.t.list3 # Sleep 5s so that elements can time out 0 sleep 5 # Network: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Network: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:ip6.t.list1 +0 ./diff.sh .foo hash:ip6.t.list1 # Network: Flush test set 0 ipset -F test # Network: Delete test set @@ -89,13 +89,13 @@ # Check more complex restore commands 0 ipset restore < restore.t.restore # List restored set a -0 ipset l a | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset l a > .foo0 && ./sort.sh .foo0 # Check listing of set a -0 diff -u -I 'Size in memory.*' .foo restore.t.list0 +0 ./diff.sh .foo restore.t.list0 # List restored set b -0 ipset l b | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset l b > .foo0 && ./sort.sh .foo0 # Check listing of set b -0 diff -u -I 'Size in memory.*' .foo restore.t.list1 +0 ./diff.sh .foo restore.t.list1 # Destroy by restore 0 ipset restore < restore.t.destroy # Timeout: Check that resizing keeps timeout values diff --git a/tests/hash:ip6.t.list0 b/tests/hash:ip6.t.list0 index 44b6fb4..7dbe3dd 100644 --- a/tests/hash:ip6.t.list0 +++ b/tests/hash:ip6.t.list0 @@ -1,7 +1,8 @@ Name: test Type: hash:ip -Header: family inet6 hashsize 128 maxelem 65536 timeout 4 -Size in memory: 416 +Revision: 5 +Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xb377cb25 +Size in memory: 504 References: 0 Number of entries: 1 Members: diff --git a/tests/hash:ip6.t.list1 b/tests/hash:ip6.t.list1 index 838fa77..c839bea 100644 --- a/tests/hash:ip6.t.list1 +++ b/tests/hash:ip6.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:ip -Header: family inet6 hashsize 128 maxelem 65536 netmask 64 timeout 4 -Size in memory: 544 +Revision: 5 +Header: family inet6 hashsize 128 maxelem 65536 netmask 64 timeout 4 bucketsize 12 initval 0xc4b28af2 +Size in memory: 584 References: 0 Number of entries: 1 Members: diff --git a/tests/hash:ip6.t.list2 b/tests/hash:ip6.t.list2 index 46a92f7..d3045ea 100644 --- a/tests/hash:ip6.t.list2 +++ b/tests/hash:ip6.t.list2 @@ -1,9 +1,10 @@ Name: test Type: hash:ip -Header: family inet6 hashsize 128 maxelem 65536 timeout x -Size in memory: 512 +Revision: 5 +Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x4f3db7cd +Size in memory: 504 References: 0 Number of entries: 2 Members: -192:168:68::69 timeout x -2::1 timeout x +192:168:68::69 timeout 0 +2::1 timeout 3 diff --git a/tests/hash:ip6.t.list3 b/tests/hash:ip6.t.list3 index c6e2990..9becbe5 100644 --- a/tests/hash:ip6.t.list3 +++ b/tests/hash:ip6.t.list3 @@ -1,10 +1,11 @@ Name: test Type: hash:ip -Header: family inet6 hashsize 128 maxelem 65536 netmask 64 timeout x -Size in memory: 704 +Revision: 5 +Header: family inet6 hashsize 128 maxelem 65536 netmask 64 timeout 4 bucketsize 12 initval 0xcc03ae18 +Size in memory: 504 References: 0 Number of entries: 3 Members: -192:168:68:: timeout x -200:100:10:: timeout x -2:: timeout x +192:168:68:: timeout 3 +200:100:10:: timeout 0 +2:: timeout 3 diff --git a/tests/hash:mac.t b/tests/hash:mac.t index 361bf58..9192af0 100644 --- a/tests/hash:mac.t +++ b/tests/hash:mac.t @@ -19,15 +19,15 @@ # MAC: Delete the same value 0 ipset -D test 1:2:3:4:a:b # MAC: List set -0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # MAC: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:mac.t.list2 +0 ./diff.sh .foo hash:mac.t.list2 # Sleep 5s so that element can time out 0 sleep 5 # MAC: List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # MAC: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:mac.t.list0 +0 ./diff.sh .foo hash:mac.t.list0 # MAC: Destroy test set 0 ipset -X test # MAC: Create a set with skbinfo extension @@ -45,9 +45,9 @@ # MAC: Add element with mark, skbprio and skbqueue 0 ipset a test 1:2:3:4:5:11 skbmark 0x11223344/0xffff0000 skbprio 2:1 skbqueue 8 # MAC: List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # MAC: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:mac.t.list1 +0 ./diff.sh .foo hash:mac.t.list1 # MAC: Destroy test set 0 ipset -X test # MAC: Create a set with small maxelem parameter @@ -63,9 +63,9 @@ # MAC: Add second element with another extension value 0 ipset -! a test 1:2:3:4:5:7 skbprio 1:12 skbqueue 8 # MAC: List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # MAC: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:mac.t.list3 +0 ./diff.sh .foo hash:mac.t.list3 # MAC: Destroy test set 0 ipset x test # eof diff --git a/tests/hash:mac.t.list0 b/tests/hash:mac.t.list0 index 232b932..2c381ff 100644 --- a/tests/hash:mac.t.list0 +++ b/tests/hash:mac.t.list0 @@ -1,7 +1,8 @@ Name: test Type: hash:mac -Header: hashsize 128 maxelem 65536 timeout 4 -Size in memory: 336 +Revision: 1 +Header: hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x851b9eb1 +Size in memory: 464 References: 0 Number of entries: 1 Members: diff --git a/tests/hash:mac.t.list1 b/tests/hash:mac.t.list1 index 0c971ff..d464f74 100644 --- a/tests/hash:mac.t.list1 +++ b/tests/hash:mac.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:mac -Header: hashsize 1024 maxelem 65536 skbinfo -Size in memory: 1088 +Revision: 1 +Header: hashsize 1024 maxelem 65536 skbinfo bucketsize 12 initval 0x5698af00 +Size in memory: 816 References: 0 Number of entries: 6 Members: diff --git a/tests/hash:mac.t.list2 b/tests/hash:mac.t.list2 index 166f266..bc7ecb0 100644 --- a/tests/hash:mac.t.list2 +++ b/tests/hash:mac.t.list2 @@ -1,9 +1,10 @@ Name: test Type: hash:mac -Header: hashsize 128 maxelem 65536 timeout x -Size in memory: 384 +Revision: 1 +Header: hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x60a630a7 +Size in memory: 464 References: 0 Number of entries: 2 Members: -00:00:00:00:02:00 timeout x -00:0A:00:00:00:00 timeout x +00:00:00:00:02:00 timeout 3 +00:0A:00:00:00:00 timeout 0 diff --git a/tests/hash:mac.t.list3 b/tests/hash:mac.t.list3 index 4154342..cc02314 100644 --- a/tests/hash:mac.t.list3 +++ b/tests/hash:mac.t.list3 @@ -1,7 +1,8 @@ Name: test Type: hash:mac -Header: hashsize 1024 maxelem 2 skbinfo -Size in memory: 448 +Revision: 1 +Header: hashsize 1024 maxelem 2 skbinfo bucketsize 12 initval 0x7c818884 +Size in memory: 496 References: 0 Number of entries: 2 Members: diff --git a/tests/hash:net,iface.t b/tests/hash:net,iface.t index a847357..444f230 100644 --- a/tests/hash:net,iface.t +++ b/tests/hash:net,iface.t @@ -41,9 +41,9 @@ # Try to add IP address 0 ipset add test 2.0.0.1,eth0 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net,iface.t.list0 +0 ./diff.sh .foo hash:net,iface.t.list0 # Flush test set 0 ipset flush test # Delete test set @@ -53,9 +53,9 @@ # Add networks in range notation 0 ipset add test 10.2.0.0-10.2.1.12,eth0 # List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net,iface.t.list2 +0 ./diff.sh .foo hash:net,iface.t.list2 # Flush test set 0 ipset flush test # Add 0/0,eth0 @@ -117,9 +117,9 @@ # Add overlapping networks from /4 to /30 0 (set -e; for x in `seq 4 30`; do ipset add test 192.0.0.0/$x,eth$x; done) # List test set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net,iface.t.list1 +0 ./diff.sh .foo hash:net,iface.t.list1 # Test matching elements in all added networks from /30 to /24 0 (set -e; y=2; for x in `seq 24 30 | tac`; do ipset test test 192.0.0.$y,eth$x; y=$((y*2)); done) # Test non-matching elements in all added networks from /30 to /24 @@ -132,6 +132,10 @@ 0 (set -e; for x in `seq 0 63`; do ipset add test 10.0.0.0/16,eth$x; done) # Check listing 0 n=`ipset list test | grep -v Revision: | wc -l` && test $n -eq 71 +# Flush test set +0 ipset flush test +# Try to add more than 64 clashing entries +1 (set -e; for x in `seq 0 64`; do ipset add test 10.0.0.0/16,eth$x; done) # Delete test set 0 ipset destroy test # Check all possible CIDR values diff --git a/tests/hash:net,iface.t.list0 b/tests/hash:net,iface.t.list0 index e29a7d6..aeb3c52 100644 --- a/tests/hash:net,iface.t.list0 +++ b/tests/hash:net,iface.t.list0 @@ -1,7 +1,8 @@ Name: test Type: hash:net,iface -Header: family inet hashsize 128 maxelem 65536 -Size in memory: 928 +Revision: 8 +Header: family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x9b9671af +Size in memory: 976 References: 0 Number of entries: 4 Members: diff --git a/tests/hash:net,iface.t.list1 b/tests/hash:net,iface.t.list1 index 00f7d80..bf07a73 100644 --- a/tests/hash:net,iface.t.list1 +++ b/tests/hash:net,iface.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:net,iface -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 3872 +Revision: 8 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x79761aac +Size in memory: 3000 References: 0 Number of entries: 27 Members: diff --git a/tests/hash:net,iface.t.list2 b/tests/hash:net,iface.t.list2 index 4f5cc90..5dc128a 100644 --- a/tests/hash:net,iface.t.list2 +++ b/tests/hash:net,iface.t.list2 @@ -1,7 +1,8 @@ Name: test Type: hash:net,iface -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 928 +Revision: 8 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb61bc401 +Size in memory: 976 References: 0 Number of entries: 4 Members: diff --git a/tests/hash:net,net.t b/tests/hash:net,net.t index 13f1198..41189b7 100644 --- a/tests/hash:net,net.t +++ b/tests/hash:net,net.t @@ -33,15 +33,15 @@ # Try to add IP address 0 ipset add test 2.0.0.1,2.0.0.2 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net,net.t.list0 +0 ./diff.sh .foo hash:net,net.t.list0 # Sleep 5s so that element can time out 0 sleep 5 # List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net,net.t.list1 +0 ./diff.sh .foo hash:net,net.t.list1 # Flush test set 0 ipset flush test # Delete test set @@ -51,9 +51,9 @@ # Add networks in range notation 0 ipset add test 10.2.0.0-10.2.1.12,10.3.0.0-10.3.1.12 # List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net,net.t.list2 +0 ./diff.sh .foo hash:net,net.t.list2 # Delete test set 0 ipset destroy test # Stress test with range notation @@ -166,4 +166,110 @@ 0 ./check_extensions test 2.0.0.0/25,2.0.0.0/25 700 13 12479 # Counters and timeout: destroy set 0 ipset x test +# Network: Create a set with timeout and netmask +0 ipset -N test hash:net,net --hashsize 128 --netmask 24 timeout 4 +# Network: Add first random network +0 ipset -A test 2.0.10.1,2.10.10.254 +# Network: Add second random network +0 ipset -A test 192.168.68.1,192.168.68.254 +# Network: Test first random value +0 ipset -T test 2.0.10.11,2.10.10.25 +# Network: Test second random value +0 ipset -T test 192.168.68.11,192.168.68.5 +# Network: Test value not added to the set +1 ipset -T test 2.10.1.0,21.0.1.0 +# Network: Add third element +0 ipset -A test 200.100.10.1,200.100.10.100 timeout 0 +# Network: Add third random network +0 ipset -A test 200.100.0.12,200.100.0.13 +# Network: Delete the same network +0 ipset -D test 200.100.0.12,200.100.0.13 +# Network: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Network: Check listing +0 ./diff.sh .foo hash:net,net.t.list3 +# Sleep 5s so that elements can time out +0 sleep 5 +# Network: List set +0 ipset -L test > .foo +# Network: Check listing +0 ./diff.sh .foo hash:net,net.t.list4 +# Network: Flush test set +0 ipset -F test +# Network: add element with 1s timeout +0 ipset add test 200.100.0.12,80.20.0.12 timeout 1 +# Network: readd element with 3s timeout +0 ipset add test 200.100.0.12,80.20.0.12 timeout 3 -exist +# Network: sleep 2s +0 sleep 2s +# Network: check readded element +0 ipset test test 200.100.0.12,80.20.0.12 +# Network: Delete test set +0 ipset -X test +# Network: Create a set with timeout and bitmask +0 ipset -N test hash:net,net --hashsize 128 --bitmask 255.255.255.0 timeout 4 +# Network: Add first random network +0 ipset -A test 2.0.10.1,2.10.10.254 +# Network: Add second random network +0 ipset -A test 192.168.68.1,192.168.68.254 +# Network: Test first random value +0 ipset -T test 2.0.10.11,2.10.10.25 +# Network: Test second random value +0 ipset -T test 192.168.68.11,192.168.68.5 +# Network: Test value not added to the set +1 ipset -T test 2.10.1.0,21.0.1.0 +# Network: Add third element +0 ipset -A test 200.100.10.1,200.100.10.100 timeout 0 +# Network: Add third random network +0 ipset -A test 200.100.0.12,200.100.0.13 +# Network: Delete the same network +0 ipset -D test 200.100.0.12,200.100.0.13 +# Network: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Network: Check listing +0 ./diff.sh .foo hash:net,net.t.list5 +# Sleep 5s so that elements can time out +0 sleep 5 +# Network: List set +0 ipset -L test > .foo +# Network: Check listing +0 ./diff.sh .foo hash:net,net.t.list6 +# Network: Flush test set +0 ipset -F test +# Network: add element with 1s timeout +0 ipset add test 200.100.0.12,80.20.0.12 timeout 1 +# Network: readd element with 3s timeout +0 ipset add test 200.100.0.12,80.20.0.12 timeout 3 -exist +# Network: sleep 2s +0 sleep 2s +# Network: check readded element +0 ipset test test 200.100.0.12,80.20.0.12 +# Network: Delete test set +0 ipset -X test +# Network: Create a set with bitmask which is not a valid netmask +0 ipset -N test hash:net,net --hashsize 128 --bitmask 255.255.0.255 +# Network: Add zero valued element +1 ipset -A test 0.0.0.0 +# Network: Test zero valued element +1 ipset -T test 0.0.0.0 +# Network: Delete zero valued element +1 ipset -D test 0.0.0.0 +# Network: Add first random network +0 ipset -A test 1.2.3.4,22.23.24.25 +# Network: Add second random network +0 ipset -A test 1.168.122.124,122.23.45.50 +# Network: Test first random value +0 ipset -T test 1.2.43.4,22.23.2.25 +# Network: Test second random value +0 ipset -T test 1.168.12.124,122.23.4.50 +# Network: Test value not added to the set +1 ipset -T test 2.168.122.124,22.23.45.50 +# Network: Test delete value +0 ipset -D test 1.168.12.124,122.23.0.50 +# Network: List set +0 ipset -L test > .foo +# Network: Check listing +0 ./diff.sh .foo hash:net,net.t.list7 +# Network: Delete test set +0 ipset -X test # eof diff --git a/tests/hash:net,net.t.list0 b/tests/hash:net,net.t.list0 index 4b806ea..14be3c2 100644 --- a/tests/hash:net,net.t.list0 +++ b/tests/hash:net,net.t.list0 @@ -1,11 +1,12 @@ Name: test Type: hash:net,net -Header: family inet hashsize 128 maxelem 65536 timeout x -Size in memory: 1288 +Revision: 3 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x24629b16 +Size in memory: 1048 References: 0 Number of entries: 4 Members: -1.1.1.1,1.1.1.2 timeout x -192.168.68.64/27,192.168.129.64/27 timeout x -2.0.0.0/24,2.0.1.0/24 timeout x -2.0.0.1,2.0.0.2 timeout x +1.1.1.1,1.1.1.2 timeout 3 +192.168.68.64/27,192.168.129.64/27 timeout 3 +2.0.0.0/24,2.0.1.0/24 timeout 3 +2.0.0.1,2.0.0.2 timeout 3 diff --git a/tests/hash:net,net.t.list1 b/tests/hash:net,net.t.list1 index 99e62c1..7f1a1b6 100644 --- a/tests/hash:net,net.t.list1 +++ b/tests/hash:net,net.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:net,net -Header: family inet hashsize 128 maxelem 65536 timeout 4 -Size in memory: 920 +Revision: 3 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xff0645fb +Size in memory: 1048 References: 0 Number of entries: 0 Members: diff --git a/tests/hash:net,net.t.list2 b/tests/hash:net,net.t.list2 index 139b3e2..bb8d663 100644 --- a/tests/hash:net,net.t.list2 +++ b/tests/hash:net,net.t.list2 @@ -1,7 +1,8 @@ Name: test Type: hash:net,net -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 2056 +Revision: 3 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x957a74a3 +Size in memory: 1752 References: 0 Number of entries: 16 Members: diff --git a/tests/hash:net,net.t.list3 b/tests/hash:net,net.t.list3 new file mode 100644 index 0000000..fc5b97a --- /dev/null +++ b/tests/hash:net,net.t.list3 @@ -0,0 +1,11 @@ +Name: test +Type: hash:net,net +Revision: 4 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xe17e4732 netmask 24 +Size in memory: 848 +References: 0 +Number of entries: 3 +Members: +192.168.68.0,192.168.68.0 timeout 3 +2.0.10.0,2.10.10.0 timeout 3 +200.100.10.0,200.100.10.0 timeout 0 diff --git a/tests/hash:net,net.t.list4 b/tests/hash:net,net.t.list4 new file mode 100644 index 0000000..908cab6 --- /dev/null +++ b/tests/hash:net,net.t.list4 @@ -0,0 +1,9 @@ +Name: test +Type: hash:net,net +Revision: 4 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xb69e293e netmask 24 +Size in memory: 848 +References: 0 +Number of entries: 1 +Members: +200.100.10.0,200.100.10.0 timeout 0 diff --git a/tests/hash:net,net.t.list5 b/tests/hash:net,net.t.list5 new file mode 100644 index 0000000..0ff37fb --- /dev/null +++ b/tests/hash:net,net.t.list5 @@ -0,0 +1,11 @@ +Name: test +Type: hash:net,net +Revision: 4 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xe17e4732 bitmask 255.255.255.0 +Size in memory: 848 +References: 0 +Number of entries: 3 +Members: +192.168.68.0,192.168.68.0 timeout 3 +2.0.10.0,2.10.10.0 timeout 3 +200.100.10.0,200.100.10.0 timeout 0 diff --git a/tests/hash:net,net.t.list6 b/tests/hash:net,net.t.list6 new file mode 100644 index 0000000..84beb5b --- /dev/null +++ b/tests/hash:net,net.t.list6 @@ -0,0 +1,9 @@ +Name: test +Type: hash:net,net +Revision: 4 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xb69e293e bitmask 255.255.255.0 +Size in memory: 848 +References: 0 +Number of entries: 1 +Members: +200.100.10.0,200.100.10.0 timeout 0 diff --git a/tests/hash:net,net.t.list7 b/tests/hash:net,net.t.list7 new file mode 100644 index 0000000..6601795 --- /dev/null +++ b/tests/hash:net,net.t.list7 @@ -0,0 +1,9 @@ +Name: test +Type: hash:net,net +Revision: 4 +Header: family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x6223fef7 bitmask 255.255.0.255 +Size in memory: 736 +References: 0 +Number of entries: 1 +Members: +1.2.0.4,22.23.0.25 diff --git a/tests/hash:net,port,net.t b/tests/hash:net,port,net.t index 0e92f5b..2c9516b 100644 --- a/tests/hash:net,port,net.t +++ b/tests/hash:net,port,net.t @@ -27,9 +27,9 @@ # Try to add value after second random value 0 ipset add test 2.1.0.1,128,10.0.0.0/17 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net,port,net.t.list0 +0 ./diff.sh .foo hash:net,port,net.t.list0 # Sleep 5s so that elements can time out 0 sleep 5 # List set @@ -52,6 +52,12 @@ 0 ipset add test 10.0.0.0-10.0.3.255,tcp:80-82,192.168.0.0-192.168.2.255 # Check that correct number of elements are added 0 n=`ipset list test|grep '^10.0'|wc -l` && test $n -eq 6 +# Flush set +0 ipset flush test +# Add 0/0 networks +0 ipset add test 0.0.0.0/0,tcp:1-2,192.168.230.128/25 +# Check that correct number of elements are added +0 n=`ipset list test|grep '^0'|wc -l` && test $n -eq 2 # Destroy set 0 ipset -X test # Create test set with timeout support diff --git a/tests/hash:net,port,net.t.list0 b/tests/hash:net,port,net.t.list0 index 9f20e7d..166b602 100644 --- a/tests/hash:net,port,net.t.list0 +++ b/tests/hash:net,port,net.t.list0 @@ -1,11 +1,12 @@ Name: test Type: hash:net,port,net -Header: family inet hashsize 1024 maxelem 65536 timeout x -Size in memory: 1288 +Revision: 3 +Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0xf441dd10 +Size in memory: 1048 References: 0 Number of entries: 4 Members: -2.0.0.0/24,tcp:5,192.168.0.0/24 timeout x -2.0.0.0/24,tcp:5,192.168.0.0/25 timeout x -2.1.0.0/24,tcp:128,10.0.0.0/16 timeout x -2.1.0.1,tcp:128,10.0.0.0/17 timeout x +2.0.0.0/24,tcp:5,192.168.0.0/24 timeout 3 +2.0.0.0/24,tcp:5,192.168.0.0/25 timeout 3 +2.1.0.0/24,tcp:128,10.0.0.0/16 timeout 3 +2.1.0.1,tcp:128,10.0.0.0/17 timeout 3 diff --git a/tests/hash:net,port.t b/tests/hash:net,port.t index 5424ff7..5a850e6 100644 --- a/tests/hash:net,port.t +++ b/tests/hash:net,port.t @@ -41,15 +41,15 @@ # Test ICMP by name 0 ipset test test 2.0.0.255,icmp:host-prohibited # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net,port.t.list0 +0 ./diff.sh .foo hash:net,port.t.list0 # Sleep 5s so that element can time out 0 sleep 5 # IP: List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # IP: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net,port.t.list1 +0 ./diff.sh .foo hash:net,port.t.list1 # Flush test set 0 ipset flush test # Add multiple elements in one step diff --git a/tests/hash:net,port.t.list0 b/tests/hash:net,port.t.list0 index fbfab7f..afb7215 100644 --- a/tests/hash:net,port.t.list0 +++ b/tests/hash:net,port.t.list0 @@ -1,12 +1,13 @@ Name: test Type: hash:net,port -Header: family inet hashsize 128 maxelem 65536 timeout x -Size in memory: 1024 +Revision: 8 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x34b03146 +Size in memory: 912 References: 0 Number of entries: 5 Members: -1.1.1.1,tcp:5 timeout x -192.168.68.64/27,tcp:8 timeout x -2.0.0.0/24,icmp:echo-request timeout x -2.0.0.1,icmp:echo-request timeout x -2.0.0.255,icmp:host-prohibited timeout x +1.1.1.1,tcp:5 timeout 3 +192.168.68.64/27,tcp:8 timeout 3 +2.0.0.0/24,icmp:echo-request timeout 3 +2.0.0.1,icmp:echo-request timeout 2 +2.0.0.255,icmp:host-prohibited timeout 3 diff --git a/tests/hash:net,port.t.list1 b/tests/hash:net,port.t.list1 index 66f0955..4ee3e5b 100644 --- a/tests/hash:net,port.t.list1 +++ b/tests/hash:net,port.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:net,port -Header: family inet hashsize 128 maxelem 65536 timeout 4 -Size in memory: 880 +Revision: 8 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xad2d00b2 +Size in memory: 784 References: 0 Number of entries: 0 Members: diff --git a/tests/hash:net.t b/tests/hash:net.t index 501f63e..c74ace1 100644 --- a/tests/hash:net.t +++ b/tests/hash:net.t @@ -33,15 +33,15 @@ # Try to add IP address 0 ipset add test 2.0.0.1 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net.t.list0 +0 ./diff.sh .foo hash:net.t.list0 # Sleep 5s so that element can time out 0 sleep 5 # List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net.t.list1 +0 ./diff.sh .foo hash:net.t.list1 # Flush test set 0 ipset flush test # Delete test set @@ -51,9 +51,9 @@ # Add networks in range notation 0 ipset add test 10.2.0.0-10.2.1.12 # List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net.t.list2 +0 ./diff.sh .foo hash:net.t.list2 # Delete test set 0 ipset destroy test # Stress test with range notation @@ -127,9 +127,9 @@ # Add more than 2^31 elements in a range 0 ipset a test 0.0.0.0-128.0.0.1 # List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net.t.list3 +0 ./diff.sh .foo hash:net.t.list3 # Delete test set 0 ipset destroy test # Counters: create set diff --git a/tests/hash:net.t.list0 b/tests/hash:net.t.list0 index e22f183..fbab961 100644 --- a/tests/hash:net.t.list0 +++ b/tests/hash:net.t.list0 @@ -1,11 +1,12 @@ Name: test Type: hash:net -Header: family inet hashsize 128 maxelem 65536 timeout x -Size in memory: 896 +Revision: 7 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xb6f1b3fa +Size in memory: 848 References: 0 Number of entries: 4 Members: -1.1.1.1 timeout x -192.168.68.64/27 timeout x -2.0.0.0/24 timeout x -2.0.0.1 timeout x +1.1.1.1 timeout 3 +192.168.68.64/27 timeout 3 +2.0.0.0/24 timeout 3 +2.0.0.1 timeout 3 diff --git a/tests/hash:net.t.list1 b/tests/hash:net.t.list1 index 6e74a1d..afa8f0e 100644 --- a/tests/hash:net.t.list1 +++ b/tests/hash:net.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:net -Header: family inet hashsize 128 maxelem 65536 timeout 4 -Size in memory: 784 +Revision: 7 +Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x9d02405f +Size in memory: 848 References: 0 Number of entries: 0 Members: diff --git a/tests/hash:net.t.list2 b/tests/hash:net.t.list2 index 893ac9d..94bb184 100644 --- a/tests/hash:net.t.list2 +++ b/tests/hash:net.t.list2 @@ -1,7 +1,8 @@ Name: test Type: hash:net -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 640 +Revision: 7 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xadbf55c3 +Size in memory: 784 References: 0 Number of entries: 4 Members: diff --git a/tests/hash:net.t.list3 b/tests/hash:net.t.list3 index 265fcbd..7b21185 100644 --- a/tests/hash:net.t.list3 +++ b/tests/hash:net.t.list3 @@ -1,7 +1,8 @@ Name: test Type: hash:net -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 504 +Revision: 7 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5f93250 +Size in memory: 688 References: 0 Number of entries: 2 Members: diff --git a/tests/hash:net6,net6.t b/tests/hash:net6,net6.t index 57f8b2a..257d142 100644 --- a/tests/hash:net6,net6.t +++ b/tests/hash:net6,net6.t @@ -33,15 +33,15 @@ # Try to add IP address 0 ipset add test 3:0:0::1,8:0:0::1 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net6,net6.t.list0 +0 ./diff.sh .foo hash:net6,net6.t.list0 # Sleep 5s so that element can time out 0 sleep 5 # IP: List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # IP: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net6,net6.t.list1 +0 ./diff.sh .foo hash:net6,net6.t.list1 # Flush test set 0 ipset flush test # Add matching IP address entry diff --git a/tests/hash:net6,net6.t.list0 b/tests/hash:net6,net6.t.list0 index 1f021e5..93d3aeb 100644 --- a/tests/hash:net6,net6.t.list0 +++ b/tests/hash:net6,net6.t.list0 @@ -1,11 +1,12 @@ Name: test Type: hash:net,net -Header: family inet6 hashsize 128 maxelem 65536 timeout x -Size in memory: 3144 +Revision: 3 +Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x4f7b512c +Size in memory: 2416 References: 0 Number of entries: 4 Members: -192:160::/27,172:16:68::/48 timeout x -1:1:1::1,2:2:2::2 timeout x -2::/24,4::/32 timeout x -3::1,8::1 timeout x +192:160::/27,172:16:68::/48 timeout 3 +1:1:1::1,2:2:2::2 timeout 3 +2::/24,4::/32 timeout 3 +3::1,8::1 timeout 3 diff --git a/tests/hash:net6,net6.t.list1 b/tests/hash:net6,net6.t.list1 index 2ccfd51..3aad97e 100644 --- a/tests/hash:net6,net6.t.list1 +++ b/tests/hash:net6,net6.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:net,net -Header: family inet6 hashsize 128 maxelem 65536 timeout 4 -Size in memory: 2608 +Revision: 3 +Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x3ab35d63 +Size in memory: 2416 References: 0 Number of entries: 0 Members: diff --git a/tests/hash:net6,port,net6.t b/tests/hash:net6,port,net6.t index 5793b2d..7ec737e 100644 --- a/tests/hash:net6,port,net6.t +++ b/tests/hash:net6,port,net6.t @@ -41,9 +41,9 @@ # Range: Try to add value after second random value 0 ipset -A test 2:1:0::1,128,2:2:2::2/12 # Range: List set -0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Range: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net6,port,net6.t.list0 +0 ./diff.sh .foo hash:net6,port,net6.t.list0 # Range: Flush test set 0 ipset -F test # Range: Delete test set diff --git a/tests/hash:net6,port,net6.t.list0 b/tests/hash:net6,port,net6.t.list0 index 4b9f8f8..3777d54 100644 --- a/tests/hash:net6,port,net6.t.list0 +++ b/tests/hash:net6,port,net6.t.list0 @@ -1,7 +1,8 @@ Name: test Type: hash:net,port,net -Header: family inet6 hashsize 1024 maxelem 65536 -Size in memory: 2440 +Revision: 3 +Header: family inet6 hashsize 1024 maxelem 65536 bucketsize 12 initval 0x5b5fdcc8 +Size in memory: 2352 References: 0 Number of entries: 4 Members: diff --git a/tests/hash:net6,port.t b/tests/hash:net6,port.t index e3e6584..a9a0f90 100644 --- a/tests/hash:net6,port.t +++ b/tests/hash:net6,port.t @@ -41,25 +41,25 @@ # Test ICMPv6 by name 0 ipset test test 192:168:68::95,icmpv6:port-unreachable # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Save set 0 ipset save test > hash:net6,port.t.restore # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net6,port.t.list0 +0 ./diff.sh .foo hash:net6,port.t.list0 # Sleep 5s so that element can time out 0 sleep 5 # IP: List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # IP: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net6,port.t.list1 +0 ./diff.sh .foo hash:net6,port.t.list1 # Destroy set 0 ipset x test # Restore set 0 ipset restore < hash:net6,port.t.restore && rm hash:net6,port.t.restore # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net6,port.t.list0 +0 ./diff.sh .foo hash:net6,port.t.list0 # Flush test set 0 ipset flush test # Add multiple elements in one step diff --git a/tests/hash:net6,port.t.list0 b/tests/hash:net6,port.t.list0 index 2d3596c..ec3dae6 100644 --- a/tests/hash:net6,port.t.list0 +++ b/tests/hash:net6,port.t.list0 @@ -1,12 +1,13 @@ Name: test Type: hash:net,port -Header: family inet6 hashsize 128 maxelem 65536 timeout x -Size in memory: 2352 +Revision: 8 +Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xf2b7e0da +Size in memory: 1856 References: 0 Number of entries: 5 Members: -192:160::/27,ipv6-icmp:echo-request timeout x -192:168:68::95,ipv6-icmp:port-unreachable timeout x -1:1:1::1,tcp:8 timeout x -2::/24,tcp:8 timeout x -3::1,tcp:8 timeout x +192:160::/27,ipv6-icmp:echo-request timeout 3 +192:168:68::95,ipv6-icmp:port-unreachable timeout 3 +1:1:1::1,tcp:8 timeout 0 +2::/24,tcp:8 timeout 3 +3::1,tcp:8 timeout 3 diff --git a/tests/hash:net6,port.t.list1 b/tests/hash:net6,port.t.list1 index 788358b..b3a8c00 100644 --- a/tests/hash:net6,port.t.list1 +++ b/tests/hash:net6,port.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:net,port -Header: family inet6 hashsize 128 maxelem 65536 timeout 4 -Size in memory: 1984 +Revision: 8 +Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x799a2fc6 +Size in memory: 1856 References: 0 Number of entries: 1 Members: diff --git a/tests/hash:net6.t b/tests/hash:net6.t index 7a47655..67ef33e 100644 --- a/tests/hash:net6.t +++ b/tests/hash:net6.t @@ -33,15 +33,15 @@ # Try to add IP address 0 ipset add test 3:0:0::1 # List set -0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net6.t.list0 +0 ./diff.sh .foo hash:net6.t.list0 # Sleep 5s so that element can time out 0 sleep 5 # IP: List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # IP: Check listing -0 diff -u -I 'Size in memory.*' .foo hash:net6.t.list1 +0 ./diff.sh .foo hash:net6.t.list1 # Flush test set 0 ipset flush test # Delete test set diff --git a/tests/hash:net6.t.list0 b/tests/hash:net6.t.list0 index ad7133a..c78fb3a 100644 --- a/tests/hash:net6.t.list0 +++ b/tests/hash:net6.t.list0 @@ -1,11 +1,12 @@ Name: test Type: hash:net -Header: family inet6 hashsize 128 maxelem 65536 timeout x -Size in memory: 2112 +Revision: 7 +Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xd3799c51 +Size in memory: 1760 References: 0 Number of entries: 4 Members: -192:160::/27 timeout x -1:1:1::1 timeout x -2::/24 timeout x -3::1 timeout x +192:160::/27 timeout 3 +1:1:1::1 timeout 3 +2::/24 timeout 3 +3::1 timeout 3 diff --git a/tests/hash:net6.t.list1 b/tests/hash:net6.t.list1 index bf7dd88..e0a08ec 100644 --- a/tests/hash:net6.t.list1 +++ b/tests/hash:net6.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:net -Header: family inet6 hashsize 128 maxelem 65536 timeout 4 -Size in memory: 1824 +Revision: 7 +Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x1fb859e4 +Size in memory: 1760 References: 0 Number of entries: 0 Members: diff --git a/tests/ignore.sh b/tests/ignore.sh new file mode 100755 index 0000000..9d458e3 --- /dev/null +++ b/tests/ignore.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +grep -v Revision: $1 | sed 's/initval 0x[0-9a-fA-F]\{8\}/initval 0x00000000/' > .foo +rm $1 diff --git a/tests/iphash.t b/tests/iphash.t index 0393295..4d65113 100644 --- a/tests/iphash.t +++ b/tests/iphash.t @@ -23,9 +23,9 @@ # IP: Delete element not added to the set, ignoring error 0 ipset -! -D test 200.100.0.12 # IP: List set -0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # IP: Check listing -0 diff -u -I 'Size in memory.*' .foo iphash.t.list0 +0 ./diff.sh .foo iphash.t.list0 # IP: Flush test set 0 ipset -F test # IP: Delete test set @@ -53,9 +53,9 @@ # IP: Add more entries to the second set 0 tail -n +2 iphash.t.restore | sed -e 's/test/test2/' -e 's/ 10/ 30/' | ipset r # IP: Save sets -0 ipset -s -f .foo.1 save +0 ipset -s -f .foo0 save && ./ignore.sh .foo0 # IP: Compare sorted save and restore -0 cmp .foo.1 iphash.t.restore.sorted +0 cmp .foo iphash.t.restore.sorted # IP: Delete test set 0 ipset x test # IP: Delete test2 set @@ -63,9 +63,9 @@ # IP: Restore, which requires multiple messages 0 ipset restore < iphash.t.large # IP: Save the restored set -0 ipset save test | sort > .foo.1 +0 (ipset save test | sort > .foo.1) && ./ignore.sh .foo.1 # IP: Compare save and restore -0 (sort iphash.t.large > .foo.2) && (cmp .foo.1 .foo.2) +0 (sort iphash.t.large > .foo.2) && (cmp .foo .foo.2) # IP: Delete all elements, one by one 0 ipset list test | sed '1,/Members/d' | xargs -n1 ipset del test # IP: Delete test set @@ -95,9 +95,9 @@ # Network: Delete element not added to the set 1 ipset -D test 200.100.0.12 # Network: List set -0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Network: Check listing -0 diff -u -I 'Size in memory.*' .foo iphash.t.list1 +0 ./diff.sh .foo iphash.t.list1 # Network: Flush test set 0 ipset -F test # Network: Delete test set diff --git a/tests/iphash.t.large b/tests/iphash.t.large index 24cc125..dc36b2f 100644 --- a/tests/iphash.t.large +++ b/tests/iphash.t.large @@ -1,4 +1,4 @@ -create test hash:ip family inet hashsize 1024 maxelem 65536 +create test hash:ip family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x00000000 add test 10.10.0.0 add test 10.10.0.1 add test 10.10.0.2 diff --git a/tests/iphash.t.list0 b/tests/iphash.t.list0 index 4d75711..3403b82 100644 --- a/tests/iphash.t.list0 +++ b/tests/iphash.t.list0 @@ -1,7 +1,8 @@ Name: test Type: hash:ip -Header: family inet hashsize 128 maxelem 65536 -Size in memory: 224 +Revision: 5 +Header: family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x9806dfda +Size in memory: 416 References: 0 Number of entries: 2 Members: diff --git a/tests/iphash.t.list1 b/tests/iphash.t.list1 index 18ec027..4ff0d69 100644 --- a/tests/iphash.t.list1 +++ b/tests/iphash.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:ip -Header: family inet hashsize 128 maxelem 65536 netmask 24 -Size in memory: 224 +Revision: 5 +Header: family inet hashsize 128 maxelem 65536 netmask 24 bucketsize 12 initval 0x3bfba4f0 +Size in memory: 416 References: 0 Number of entries: 2 Members: diff --git a/tests/iphash.t.restore.sorted b/tests/iphash.t.restore.sorted index e944061..2cdd991 100644 --- a/tests/iphash.t.restore.sorted +++ b/tests/iphash.t.restore.sorted @@ -1,4 +1,4 @@ -create test hash:ip family inet hashsize 128 maxelem 65536 +create test hash:ip family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x00000000 add test 10.0.0.0 add test 10.0.0.1 add test 10.0.0.2 @@ -128,7 +128,7 @@ add test 10.0.0.125 add test 10.0.0.126 add test 10.0.0.127 add test 10.0.0.128 -create test2 hash:ip family inet hashsize 128 maxelem 65536 +create test2 hash:ip family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x00000000 add test2 20.0.0.0 add test2 20.0.0.1 add test2 20.0.0.2 diff --git a/tests/ipmap.t b/tests/ipmap.t index 7ae141c..8e90dc2 100644 --- a/tests/ipmap.t +++ b/tests/ipmap.t @@ -49,15 +49,15 @@ # Range: Restore set 0 ipset -R < ipmap.t.restore && rm ipmap.t.restore # Range: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Range: Check listing -0 diff -u -I 'Size in memory.*' .foo ipmap.t.list0 +0 ./diff.sh .foo ipmap.t.list0 # Range: Delete a range of elements 0 ipset -! -D test 2.0.0.128-2.0.0.132 # Range: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Range: Check listing -0 diff -u -I 'Size in memory.*' .foo ipmap.t.list1 +0 ./diff.sh .foo ipmap.t.list1 # Range: Flush test set 0 ipset -F test # Range: Delete test set @@ -91,9 +91,9 @@ # Network: Delete the same element 0 ipset -D test 2.0.0.128 # Network: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Network: Check listing -0 diff -u -I 'Size in memory.*' .foo ipmap.t.list2 +0 ./diff.sh .foo ipmap.t.list2 # Network: Flush test set 0 ipset -F test # Network: Delete test set @@ -127,9 +127,9 @@ # Subnets: Add a subnet of subnets 0 ipset -A test 10.8.0.0/16 # Subnets: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Subnets: Check listing -0 diff -u -I 'Size in memory.*' .foo ipmap.t.list3 +0 ./diff.sh .foo ipmap.t.list3 # Subnets: FLush test set 0 ipset -F test # Subnets: Delete test set @@ -153,9 +153,9 @@ # Full: Delete same element 0 ipset -D test 0.1.0.0 # Full: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Full: Check listing -0 diff -u -I 'Size in memory.*' .foo ipmap.t.list4 +0 ./diff.sh .foo ipmap.t.list4 # Full: Delete test set 0 ipset -X test # eof diff --git a/tests/ipmap.t.list0 b/tests/ipmap.t.list0 index d3b99a8..d2a7681 100644 --- a/tests/ipmap.t.list0 +++ b/tests/ipmap.t.list0 @@ -1,7 +1,8 @@ Name: test Type: bitmap:ip +Revision: 3 Header: range 2.0.0.1-2.1.0.0 -Size in memory: 8352 +Size in memory: 8320 References: 0 Number of entries: 6 Members: diff --git a/tests/ipmap.t.list1 b/tests/ipmap.t.list1 index f9b311d..6a97b10 100644 --- a/tests/ipmap.t.list1 +++ b/tests/ipmap.t.list1 @@ -1,7 +1,8 @@ Name: test Type: bitmap:ip +Revision: 3 Header: range 2.0.0.1-2.1.0.0 -Size in memory: 8352 +Size in memory: 8320 References: 0 Number of entries: 2 Members: diff --git a/tests/ipmap.t.list2 b/tests/ipmap.t.list2 index c2c5691..6fc78b5 100644 --- a/tests/ipmap.t.list2 +++ b/tests/ipmap.t.list2 @@ -1,7 +1,8 @@ Name: test Type: bitmap:ip +Revision: 3 Header: range 2.0.0.0-2.0.255.255 -Size in memory: 8352 +Size in memory: 8320 References: 0 Number of entries: 2 Members: diff --git a/tests/ipmap.t.list3 b/tests/ipmap.t.list3 index 3586211..f162e14 100644 --- a/tests/ipmap.t.list3 +++ b/tests/ipmap.t.list3 @@ -1,7 +1,8 @@ Name: test Type: bitmap:ip +Revision: 3 Header: range 10.0.0.0-10.255.255.255 netmask 24 -Size in memory: 8352 +Size in memory: 8320 References: 0 Number of entries: 258 Members: diff --git a/tests/ipmap.t.list4 b/tests/ipmap.t.list4 index 2042ee6..478382d 100644 --- a/tests/ipmap.t.list4 +++ b/tests/ipmap.t.list4 @@ -1,7 +1,8 @@ Name: test Type: bitmap:ip +Revision: 3 Header: range 0.0.0.0-255.255.255.255 netmask 16 -Size in memory: 8352 +Size in memory: 8320 References: 0 Number of entries: 2 Members: diff --git a/tests/ipmarkhash.t b/tests/ipmarkhash.t index e96bbfa..1276f72 100644 --- a/tests/ipmarkhash.t +++ b/tests/ipmarkhash.t @@ -31,9 +31,9 @@ # Try to add value after second random value 0 ipset -A test 2.1.0.1,0x80 # List set -0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo ipmarkhash.t.list0 +0 ./diff.sh .foo ipmarkhash.t.list0 # Flush test set 0 ipset -F test # Delete test set @@ -61,9 +61,9 @@ # Try to add value after second random value 0 ipset -A test 2.1.0.0,0x80 # List set -0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo ipmarkhash.t.list1 +0 ./diff.sh .foo ipmarkhash.t.list1 # Flush test set 0 ipset -F test # Delete test set diff --git a/tests/ipmarkhash.t.list0 b/tests/ipmarkhash.t.list0 index 9ebf116..7042bc6 100644 --- a/tests/ipmarkhash.t.list0 +++ b/tests/ipmarkhash.t.list0 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,mark -Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 -Size in memory: 384 +Revision: 3 +Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 bucketsize 12 initval 0x3ad108b0 +Size in memory: 528 References: 0 Number of entries: 4 Members: diff --git a/tests/ipmarkhash.t.list1 b/tests/ipmarkhash.t.list1 index af39998..30324c7 100644 --- a/tests/ipmarkhash.t.list1 +++ b/tests/ipmarkhash.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,mark -Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 -Size in memory: 384 +Revision: 3 +Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 bucketsize 12 initval 0xd0130277 +Size in memory: 528 References: 0 Number of entries: 4 Members: diff --git a/tests/ipporthash.t b/tests/ipporthash.t index 866c720..b8f3606 100644 --- a/tests/ipporthash.t +++ b/tests/ipporthash.t @@ -31,9 +31,9 @@ # Try to add value after second random value 0 ipset -A test 2.1.0.1,128 # List set -0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo ipporthash.t.list0 +0 ./diff.sh .foo ipporthash.t.list0 # Flush test set 0 ipset -F test # Delete test set @@ -61,9 +61,9 @@ # Try to add value after second random value 0 ipset -A test 2.1.0.0,128 # List set -0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo ipporthash.t.list1 +0 ./diff.sh .foo ipporthash.t.list1 # Flush test set 0 ipset -F test # Delete test set diff --git a/tests/ipporthash.t.list0 b/tests/ipporthash.t.list0 index 902160f..c87147e 100644 --- a/tests/ipporthash.t.list0 +++ b/tests/ipporthash.t.list0 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,port -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 384 +Revision: 6 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x7888c8ef +Size in memory: 528 References: 0 Number of entries: 4 Members: diff --git a/tests/ipporthash.t.list1 b/tests/ipporthash.t.list1 index d298cc0..5dac9fc 100644 --- a/tests/ipporthash.t.list1 +++ b/tests/ipporthash.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,port -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 384 +Revision: 6 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xcb19e607 +Size in memory: 528 References: 0 Number of entries: 4 Members: diff --git a/tests/ipportiphash.t b/tests/ipportiphash.t index 5632433..32f22d1 100644 --- a/tests/ipportiphash.t +++ b/tests/ipportiphash.t @@ -39,9 +39,9 @@ # Try to add value after second random value 0 ipset -A test 2.1.0.1,128,2.2.2.2 # List set -0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo ipportiphash.t.list0 +0 ./diff.sh .foo ipportiphash.t.list0 # Flush test set 0 ipset -F test # Delete test set @@ -71,9 +71,9 @@ # Try to del value before first random value 0 ipset -D test 1.255.255.255,5,1.1.1.1 # List set -0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo ipportiphash.t.list1 +0 ./diff.sh .foo ipportiphash.t.list1 # Flush test set 0 ipset -F test # Delete test set diff --git a/tests/ipportiphash.t.list0 b/tests/ipportiphash.t.list0 index bde5356..f031796 100644 --- a/tests/ipportiphash.t.list0 +++ b/tests/ipportiphash.t.list0 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,port,ip -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 456 +Revision: 6 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xf6f43069 +Size in memory: 568 References: 0 Number of entries: 4 Members: diff --git a/tests/ipportiphash.t.list1 b/tests/ipportiphash.t.list1 index d5cc29e..17877b8 100644 --- a/tests/ipportiphash.t.list1 +++ b/tests/ipportiphash.t.list1 @@ -1,7 +1,8 @@ Name: test Type: hash:ip,port,ip -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 296 +Revision: 6 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xcd2e539b +Size in memory: 456 References: 0 Number of entries: 2 Members: diff --git a/tests/iptables.sh b/tests/iptables.sh index bca3253..f101ab4 100755 --- a/tests/iptables.sh +++ b/tests/iptables.sh @@ -125,11 +125,21 @@ counter) ./sendip.sh -p ipv4 -id 10.255.255.254 -is 10.255.255.64 -p udp -ud 80 -us 1025 10.255.255.254 >/dev/null 2>&1 ./sendip.sh -p ipv4 -id 10.255.255.254 -is 10.255.255.64 -p udp -ud 80 -us 1025 10.255.255.254 >/dev/null 2>&1 ;; +resize) + $ipset n test hash:ip hashsize 4096 maxelem 655360 2>/dev/null + $cmd -t raw -A OUTPUT -j SET --add-set test src + $cmd -t raw -A OUTPUT -s 10.255.0.0/16 -j DROP + $cmd -t raw -A OUTPUT -s 10.254.0.0/16 -j DROP + ./resize_sendip.sh & + $ipset restore < resize_target.set + ;; stop) $cmd -F $cmd -X $cmd -F -t mangle $cmd -X -t mangle + $cmd -F -t raw + $cmd -X -t raw $ipset -F 2>/dev/null $ipset -X 2>/dev/null ;; diff --git a/tests/macipmap.t b/tests/macipmap.t index 45783d6..074e067 100644 --- a/tests/macipmap.t +++ b/tests/macipmap.t @@ -39,9 +39,9 @@ # Range: Delete the same element 0 ipset -D test 2.0.200.214 # Range: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Range: Check listing -0 diff -u -I 'Size in memory.*' .foo macipmap.t.list0 +0 ./diff.sh .foo macipmap.t.list0 # Range: Flush test set 0 ipset -F test # Range: Catch invalid (too long) MAC @@ -87,9 +87,9 @@ # Network: Add MAC to already added element 0 ipset -A test 2.0.255.255,00:11:22:33:44:56 # Network: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Network: Check listing -0 diff -u -I 'Size in memory.*' .foo macipmap.t.list1 +0 ./diff.sh .foo macipmap.t.list1 # Network: Flush test set 0 ipset -F test # Network: Delete test set @@ -127,15 +127,15 @@ # Range: Delete the same element 0 ipset -D test 2.0.200.214 # Range: List set -0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo +0 ipset -L test > .foo # Range: Check listing -0 diff -u -I 'Size in memory.*' .foo macipmap.t.list3 +0 ./diff.sh .foo macipmap.t.list3 # Range: sleep 5s so that elements can timeout 0 sleep 5 # Range: List set -0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo +0 ipset -L test > .foo # Range: Check listing -0 diff -u -I 'Size in memory.*' .foo macipmap.t.list2 +0 ./diff.sh .foo macipmap.t.list2 # Range: Flush test set 0 ipset -F test # Range: add element with 1s timeout diff --git a/tests/macipmap.t.list2 b/tests/macipmap.t.list2 index f6a78c7..eaa01ae 100644 --- a/tests/macipmap.t.list2 +++ b/tests/macipmap.t.list2 @@ -1,8 +1,9 @@ Name: test Type: bitmap:ip,mac -Header: range 2.0.0.1-2.1.0.0 timeout x -Size in memory: 1056920 +Revision: 3 +Header: range 2.0.0.1-2.1.0.0 timeout 5 +Size in memory: 1056888 References: 0 Number of entries: 1 Members: -2.1.0.0 timeout x +2.1.0.0 timeout 3 diff --git a/tests/macipmap.t.list3 b/tests/macipmap.t.list3 index 78c78d3..3262e64 100644 --- a/tests/macipmap.t.list3 +++ b/tests/macipmap.t.list3 @@ -1,10 +1,11 @@ Name: test Type: bitmap:ip,mac -Header: range 2.0.0.1-2.1.0.0 timeout x -Size in memory: 1056920 +Revision: 3 +Header: range 2.0.0.1-2.1.0.0 timeout 5 +Size in memory: 1056888 References: 0 Number of entries: 3 Members: -2.0.0.1,00:11:22:33:44:56 timeout x -2.0.0.2,00:11:22:33:44:55 timeout x -2.1.0.0 timeout x +2.0.0.1,00:11:22:33:44:56 timeout 3 +2.0.0.2,00:11:22:33:44:55 timeout 3 +2.1.0.0 timeout 3 diff --git a/tests/nethash.t b/tests/nethash.t index 05e64c3..8f98ffa 100644 --- a/tests/nethash.t +++ b/tests/nethash.t @@ -33,9 +33,9 @@ # Try to add IP address 0 ipset -A test 2.0.0.1 # List set -0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0 +0 ipset -L test > .foo0 && ./sort.sh .foo0 # Check listing -0 diff -u -I 'Size in memory.*' .foo nethash.t.list0 +0 ./diff.sh .foo nethash.t.list0 # Flush test set 0 ipset -F test # Add a non-matching IP address entry diff --git a/tests/nethash.t.list0 b/tests/nethash.t.list0 index 0aeb852..dad3dee 100644 --- a/tests/nethash.t.list0 +++ b/tests/nethash.t.list0 @@ -1,7 +1,8 @@ Name: test Type: hash:net -Header: family inet hashsize 128 maxelem 65536 -Size in memory: 640 +Revision: 7 +Header: family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0xdc096f08 +Size in memory: 784 References: 0 Number of entries: 4 Members: diff --git a/tests/netnetgen.sh b/tests/netnetgen.sh index f2a31cc..32aac18 100755 --- a/tests/netnetgen.sh +++ b/tests/netnetgen.sh @@ -6,7 +6,7 @@ while [ -n "$1" ]; do comment=" comment" ;; timeout) - timeout=" timeout 5" + timeout=" timeout 60" ;; *) ;; diff --git a/tests/portmap.t b/tests/portmap.t index 5eeaaff..819a59b 100644 --- a/tests/portmap.t +++ b/tests/portmap.t @@ -25,9 +25,9 @@ # Range: Delete the same element 0 ipset -D test 567 # Range: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Range: Check listing -0 diff -u -I 'Size in memory.*' .foo portmap.t.list0 +0 ./diff.sh .foo portmap.t.list0 # Range: Flush test set 0 ipset -F test # Range: Delete test set @@ -45,9 +45,9 @@ # Full: Test value not added to the set 1 ipset -T test 1 # Full: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Full: Check listing -0 diff -u -I 'Size in memory.*' .foo portmap.t.list1 +0 ./diff.sh .foo portmap.t.list1 # Full: Flush test set 0 ipset -F test # Full: Delete test set @@ -69,15 +69,15 @@ # Full: Delete the same element 0 ipset -D test 567 # Full: List set -0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo +0 ipset -L test > .foo # Full: Check listing -0 diff -u -I 'Size in memory.*' .foo portmap.t.list3 +0 ./diff.sh .foo portmap.t.list3 # Full: sleep 5s so that elements can timeout 0 sleep 5 # Full: List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Full: Check listing -# 0 diff -u -I 'Size in memory.*' .foo portmap.t.list2 +# 0 ./diff.sh .foo portmap.t.list2 # Full: Flush test set 0 ipset -F test # Full: add element with 1s timeout diff --git a/tests/portmap.t.list3 b/tests/portmap.t.list3 index d5756e6..cd3f831 100644 --- a/tests/portmap.t.list3 +++ b/tests/portmap.t.list3 @@ -1,9 +1,10 @@ Name: test Type: bitmap:port -Header: range 0-65535 timeout x -Size in memory: 532628 +Revision: 3 +Header: range 0-65535 timeout 5 +Size in memory: 532592 References: 0 Number of entries: 2 Members: -0 timeout x -65535 timeout x +0 timeout 4 +65535 timeout 0 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/restore.t.list0 b/tests/restore.t.list0 index 3c73ab3..022a0b5 100644 --- a/tests/restore.t.list0 +++ b/tests/restore.t.list0 @@ -1,7 +1,8 @@ Name: a Type: hash:ip -Header: family inet6 hashsize 1024 maxelem 65536 -Size in memory: 416 +Revision: 5 +Header: family inet6 hashsize 1024 maxelem 65536 bucketsize 12 initval 0xf366ace6 +Size in memory: 536 References: 0 Number of entries: 3 Members: diff --git a/tests/restore.t.list1 b/tests/restore.t.list1 index e2c1f8e..e270e52 100644 --- a/tests/restore.t.list1 +++ b/tests/restore.t.list1 @@ -1,7 +1,8 @@ Name: b Type: hash:ip -Header: family inet6 hashsize 1024 maxelem 65536 -Size in memory: 416 +Revision: 5 +Header: family inet6 hashsize 1024 maxelem 65536 bucketsize 12 initval 0xdcbd231e +Size in memory: 536 References: 0 Number of entries: 3 Members: diff --git a/tests/setlist.t b/tests/setlist.t index 7d14ec8..316daf8 100644 --- a/tests/setlist.t +++ b/tests/setlist.t @@ -45,9 +45,9 @@ # Restore saved sets 0 ipset -R < setlist.t.r # List set -0 ipset -L test | grep -v Revision: > .foo +0 ipset -L test > .foo # Check listing -0 diff -u -I 'Size in memory.*' .foo setlist.t.list0 +0 ./diff.sh .foo setlist.t.list0 # Flush all sets 0 ipset -F # Delete all sets @@ -61,9 +61,9 @@ # Add set a before b 0 ipset add test a before b # List test set -0 ipset list test | grep -v Revision: > .foo +0 ipset list test > .foo # Check listing -0 diff -u -I 'Size in memory.*' .foo setlist.t.list1 +0 ./diff.sh .foo setlist.t.list1 # Test a set before b 0 ipset test test a before b # Test c set after b @@ -71,19 +71,19 @@ # Delete b set before c 0 ipset del test b before c # List test set -0 ipset list test | grep -v Revision: > .foo +0 ipset list test > .foo # Check listing -0 diff -u -I 'Size in memory.*' .foo setlist.t.list2 +0 ./diff.sh .foo setlist.t.list2 # Delete c set after a 0 ipset del test c after a # List test set -0 ipset list test | grep -v Revision: > .foo +0 ipset list test > .foo # Check listing -0 diff -u -I 'Size in memory.*' .foo setlist.t.list3 +0 ./diff.sh .foo setlist.t.list3 # List all sets -0 sleep .1s; ipset list | grep -v Revision: > .foo +0 sleep .1s; ipset list > .foo # Check listing -0 diff -u -I 'Size in memory.*' .foo setlist.t.list4 +0 ./diff.sh .foo setlist.t.list4 # Flush sets 0 ipset flush # Destroy sets diff --git a/tests/setlist.t.list4 b/tests/setlist.t.list4 index 6b115d9..46c6a8c 100644 --- a/tests/setlist.t.list4 +++ b/tests/setlist.t.list4 @@ -1,39 +1,44 @@ Name: a Type: hash:ip -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 152 +Revision: 5 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x042092ea +Size in memory: 336 References: 1 Number of entries: 0 Members: Name: b Type: hash:ip -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 152 +Revision: 5 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x05db211b +Size in memory: 336 References: 0 Number of entries: 0 Members: Name: c Type: hash:ip -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 152 +Revision: 5 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xf3109e51 +Size in memory: 336 References: 0 Number of entries: 0 Members: Name: d Type: hash:ip -Header: family inet hashsize 1024 maxelem 65536 -Size in memory: 152 +Revision: 5 +Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x6c851a66 +Size in memory: 336 References: 0 Number of entries: 0 Members: Name: test Type: list:set +Revision: 3 Header: size 8 -Size in memory: 184 +Size in memory: 168 References: 0 Number of entries: 1 Members: 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 diff --git a/tests/sort.sh b/tests/sort.sh index c5edad1..904b216 100755 --- a/tests/sort.sh +++ b/tests/sort.sh @@ -1,5 +1,5 @@ #!/bin/sh -head -n 7 $1 > .foo -tail -n +8 $1 | grep '[[:alnum:]]' | sort >> .foo -rm $1 +sed '/Members:/q' $1 > .foo +awk '/Members:/,EOF' $1 | grep -v 'Members:' | sort >> .foo +rm -f $1 diff --git a/tests/xlate/ipset-translate b/tests/xlate/ipset-translate new file mode 120000 index 0000000..91980c1 --- /dev/null +++ b/tests/xlate/ipset-translate @@ -0,0 +1 @@ +../../src/ipset
\ No newline at end of file diff --git a/tests/xlate/runtest.sh b/tests/xlate/runtest.sh new file mode 100755 index 0000000..8b42f0b --- /dev/null +++ b/tests/xlate/runtest.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +DIFF=$(which diff) +if [ ! -x "$DIFF" ] ; then + echo "ERROR: missing diff" + exit 1 +fi + +ipset=${IPSET_BIN:-../../src/ipset} +ipset_xlate=${IPSET_XLATE_BIN:-$(dirname $0)/ipset-translate} + +$ipset restore < xlate.t +rc=$? +$ipset destroy +if [ $rc -ne 0 ] +then + echo -e "[\033[0;31mERROR\033[0m] invalid test input" + exit 1 +fi + +TMP=$(mktemp) +$ipset_xlate restore < xlate.t &> $TMP +if [ $? -ne 0 ] +then + cat $TMP + echo -e "[\033[0;31mERROR\033[0m] failed to run ipset-translate" + exit 1 +fi +${DIFF} -u xlate.t.nft $TMP +if [ $? -eq 0 ] +then + echo -e "[\033[0;32mOK\033[0m] tests are fine!" +else + echo -e "[\033[0;31mERROR\033[0m] unexpected ipset to nftables translation" +fi diff --git a/tests/xlate/xlate.t b/tests/xlate/xlate.t new file mode 100644 index 0000000..38cbc78 --- /dev/null +++ b/tests/xlate/xlate.t @@ -0,0 +1,57 @@ +create hip1 hash:ip +add hip1 192.168.10.2 +add hip1 192.168.10.3 +create hip2 hash:ip hashsize 128 bucketsize 255 timeout 4 +add hip2 192.168.10.3 +add hip2 192.168.10.4 timeout 10 +create hip3 hash:ip counters +add hip3 192.168.10.3 packets 5 bytes 3456 +create hip4 hash:ip netmask 24 +add hip4 192.168.10.0 +create hip5 hash:ip maxelem 24 +add hip5 192.168.10.0 +create hip6 hash:ip comment +add hip6 192.168.10.1 +add hip6 192.168.10.2 comment "this is a comment" +create ipp1 hash:ip,port +add ipp1 192.168.10.1,0 +add ipp1 192.168.10.2,5 +create ipp2 hash:ip,port timeout 4 +add ipp2 192.168.10.1,0 timeout 12 +add ipp2 192.168.10.2,5 +create ipp3 hash:ip,port counters +add ipp3 192.168.10.3,20 packets 5 bytes 3456 +create ipp4 hash:ip,port timeout 4 counters +add ipp4 192.168.10.3,20 packets 5 bytes 3456 +create bip1 bitmap:ip range 2.0.0.1-2.0.1.1 timeout 5 +create bip2 bitmap:ip range 10.0.0.0/8 netmask 24 timeout 5 +add bip2 10.10.10.0 +add bip2 10.10.20.0 timeout 12 +create net1 hash:net +add net1 192.168.10.0/24 +create net2 hash:net,net +add net2 192.168.10.0/24,192.168.20.0/24 +create hm1 hash:mac +add hm1 aa:bb:cc:dd:ee:ff +create him1 hash:ip,mac +add him1 1.1.1.1,aa:bb:cc:dd:ee:ff +create ni1 hash:net,iface +add ni1 1.1.1.0/24,eth0 +create nip1 hash:net,port +add nip1 1.1.1.0/24,22 +create npn1 hash:net,port,net +add npn1 1.1.1.0/24,22,2.2.2.0/24 +create nn1 hash:net,net +add nn1 1.1.1.0/24,2.2.2.0/24 +create ipn1 hash:ip,port,net +add ipn1 1.1.1.1,22,2.2.2.0/24 +create ipi1 hash:ip,port,ip +add ipi1 1.1.1.1,22,2.2.2.2 +create im1 hash:ip,mark +add im1 1.1.1.1,0x123456 +create bp1 bitmap:port range 1-1024 +add bp1 22 +create bim1 bitmap:ip,mac range 1.1.1.0/24 +add bim1 1.1.1.1,aa:bb:cc:dd:ee:ff +create hn6 hash:net family inet6 +add hn6 fe80::/64 diff --git a/tests/xlate/xlate.t.nft b/tests/xlate/xlate.t.nft new file mode 100644 index 0000000..8fb2a29 --- /dev/null +++ b/tests/xlate/xlate.t.nft @@ -0,0 +1,58 @@ +add table inet global +add set inet global hip1 { type ipv4_addr; } +add element inet global hip1 { 192.168.10.2 } +add element inet global hip1 { 192.168.10.3 } +add set inet global hip2 { type ipv4_addr; timeout 4s; } +add element inet global hip2 { 192.168.10.3 } +add element inet global hip2 { 192.168.10.4 timeout 10s } +add set inet global hip3 { type ipv4_addr; counter; } +add element inet global hip3 { 192.168.10.3 counter packets 5 bytes 3456 } +add set inet global hip4 { type ipv4_addr; flags interval; } +add element inet global hip4 { 192.168.10.0/24 } +add set inet global hip5 { type ipv4_addr; size 24; } +add element inet global hip5 { 192.168.10.0 } +add set inet global hip6 { type ipv4_addr; } +add element inet global hip6 { 192.168.10.1 } +add element inet global hip6 { 192.168.10.2 comment "this is a comment" } +add set inet global ipp1 { type ipv4_addr . inet_proto . inet_service; } +add element inet global ipp1 { 192.168.10.1 . tcp . 0 } +add element inet global ipp1 { 192.168.10.2 . tcp . 5 } +add set inet global ipp2 { type ipv4_addr . inet_proto . inet_service; timeout 4s; } +add element inet global ipp2 { 192.168.10.1 . tcp . 0 timeout 12s } +add element inet global ipp2 { 192.168.10.2 . tcp . 5 } +add set inet global ipp3 { type ipv4_addr . inet_proto . inet_service; counter; } +add element inet global ipp3 { 192.168.10.3 . tcp . 20 counter packets 5 bytes 3456 } +add set inet global ipp4 { type ipv4_addr . inet_proto . inet_service; counter; timeout 4s; } +add element inet global ipp4 { 192.168.10.3 . tcp . 20 counter packets 5 bytes 3456 } +add set inet global bip1 { type ipv4_addr; timeout 5s; } +add set inet global bip2 { type ipv4_addr; timeout 5s; flags interval; } +add element inet global bip2 { 10.10.10.0/24 } +add element inet global bip2 { 10.10.20.0/24 timeout 12s } +add set inet global net1 { type ipv4_addr; flags interval; } +add element inet global net1 { 192.168.10.0/24 } +add set inet global net2 { type ipv4_addr . ipv4_addr; flags interval; } +add element inet global net2 { 192.168.10.0/24 . 192.168.20.0/24 } +add set inet global hm1 { type ether_addr; } +add element inet global hm1 { aa:bb:cc:dd:ee:ff } +add set inet global him1 { type ipv4_addr . ether_addr; } +add element inet global him1 { 1.1.1.1 . aa:bb:cc:dd:ee:ff } +add set inet global ni1 { type ipv4_addr . ifname; flags interval; } +add element inet global ni1 { 1.1.1.0/24 . eth0 } +add set inet global nip1 { type ipv4_addr . inet_proto . inet_service; flags interval; } +add element inet global nip1 { 1.1.1.0/24 . tcp . 22 } +add set inet global npn1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; flags interval; } +add element inet global npn1 { 1.1.1.0/24 . tcp . 22 . 2.2.2.0/24 } +add set inet global nn1 { type ipv4_addr . ipv4_addr; flags interval; } +add element inet global nn1 { 1.1.1.0/24 . 2.2.2.0/24 } +add set inet global ipn1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; flags interval; } +add element inet global ipn1 { 1.1.1.1 . tcp . 22 . 2.2.2.0/24 } +add set inet global ipi1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; } +add element inet global ipi1 { 1.1.1.1 . tcp . 22 . 2.2.2.2 } +add set inet global im1 { type ipv4_addr . mark; } +add element inet global im1 { 1.1.1.1 . 0x00123456 } +add set inet global bp1 { type inet_service; } +add element inet global bp1 { 22 } +add set inet global bim1 { type ipv4_addr . ether_addr; } +add element inet global bim1 { 1.1.1.1 . aa:bb:cc:dd:ee:ff } +add set inet global hn6 { type ipv6_addr; flags interval; } +add element inet global hn6 { fe80::/64 } diff --git a/utils/ipset_bash_completion/README.md b/utils/ipset_bash_completion/README.md index ce5c47e..ecfd6b9 100644 --- a/utils/ipset_bash_completion/README.md +++ b/utils/ipset_bash_completion/README.md @@ -33,14 +33,57 @@ icmp[6] types and interface names when adding, deleting or testing elements. - Complete on filenames if the current option requires it. - Complete variable names and command substitution. - Do not complete if an invalid combination of options is used. -- Do not complete if an invalid value of an option argument is detected. +- Optionally do not complete if an invalid value of an option argument is detected. - Environment variables allow to modify completion behaviour. Installation ============ -Put it into ~/.bash_completion or /etc/bash_completion.d/. +Quote from bash-completion README: + + Install it in one of the directories pointed to by + bash-completion's pkgconfig file variables. There are two + alternatives: the recommended one is 'completionsdir' (get it with + "pkg-config --variable=completionsdir bash-completion") from which + completions are loaded on demand based on invoked commands' names, + so be sure to name your completion file accordingly, and to include + for example symbolic links in case the file provides completions + for more than one command. The other one which is present for + backwards compatibility reasons is 'compatdir' (get it with + "pkg-config --variable=compatdir bash-completion") from which files + are loaded when bash_completion is loaded. + + For packages using GNU autotools the installation can be handled + for example like this in configure.ac: + + PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], , + bashcompdir="${sysconfdir}/bash_completion.d") + AC_SUBST(bashcompdir) + + ...accompanied by this in Makefile.am: + + bashcompdir = @bashcompdir@ + dist_bashcomp_DATA = # completion files go here + + For cmake we ship the bash-completion-config.cmake and + bash-completion-config-version.cmake files. Example usage: + + find_package(bash-completion) + if(BASH_COMPLETION_FOUND) + message(STATUS + "Using bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}") + else() + set (BASH_COMPLETION_COMPLETIONSDIR "/etc/bash_completion.d") + message (STATUS + "Using fallback bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}") + endif() + + install(FILES your-completion-file DESTINATION + ${BASH_COMPLETION_COMPLETIONSDIR}) + +For backwards compatibility it is still possible +to put it into ~/.bash_completion or /etc/bash_completion.d/. Tip: To make tab completion more handsome put the following into either @@ -113,6 +156,7 @@ which will be used for hostname completion. For all *net* type of sets and the hash:ip,mark set type, if hostname completion is attempted, if the environment variable **_IPSET_COMP_NETWORKS** is set to a non-empty value, networks are retrieved from /etc/networks. +Means these two commands disable it: `_IPSET_COMP_NETWORKS=` or `_IPSET_COMP_NETWORKS=""` Also a list of ip addresses can be supplied using the environment variable **_IPSET_IPLIST_FILE**. Which should point to a file containing an ip address per line. @@ -139,13 +183,15 @@ the list of possible completions (this is the default). --- -When adding elements to a **bitmap:ip,mac** type of set, -the environment variable **_IPSET_MACLIST_FILE** will be queried +When completing on MAC addresses (bitmap:ip,mac, hash:mac type of set), +the environment variable **_IPSET_MAC_COMPL_MODE** is queried to decide how to complete. +If set to 'file' the variable **_IPSET_MACLIST_FILE** will be queried for a file containing a list of mac addresses. The file should contain one mac address per line. Empty lines and comments (also after the address) are supported. -If the variable is unset mac addresses are fetched from arp cache, -/etc/ethers and the output of `ip link show`. +If the variable **_IPSET_MAC_COMPL_MODE** is set to 'system' mac addresses are fetched +from arp cache, /etc/ethers and the output of `ip link show`. +If the variable is unset or set to 'both' (default) both methods are used). --- @@ -168,8 +214,8 @@ In that case it is recommended to disable input validation (see below). --- -If the environment variable **_IPSET_VALIDATE_INPUT** is set to a non empty value -validation of users input is disabled. +If the environment variable **_IPSET_VALIDATE_INPUT** is defined and set to a non empty value +validation of users input is enabled. --- @@ -183,7 +229,7 @@ Compatibility Compatible with ipset versions 6+. -Tested with ipset v6.20.1. +Tested with ipset v6.24, v6.27. bash v4+ is required. diff --git a/utils/ipset_bash_completion/ipset b/utils/ipset_bash_completion/ipset index b6d94c2..d258be2 100644 --- a/utils/ipset_bash_completion/ipset +++ b/utils/ipset_bash_completion/ipset @@ -7,7 +7,7 @@ # https://sourceforge.net/projects/ipset-bashcompl # ----------------------------------------------------------------- -# Copyright (C) 2013-2014 AllKind (AllKind@fastest.cc) +# Copyright (C) 2013-2016 Mart Frauenlob aka AllKind (AllKind@fastest.cc) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ # ----------------------------------------------------------------- # Compatible with ipset versions: 6+ # Tested with ipset versions: -# 6.22 +# 6.24, 6.27 # ----------------------------------------------------------------- # Requirements: # @@ -33,6 +33,7 @@ # # The bash completion package version 2.0 or greater is recommended. # http://bash-completion.alioth.debian.org/ +# Older version are not supported. # # If the package is not available, things might not be so reliable. # Also the colon (if there) is removed from COMP_WORDBREAKS. @@ -40,13 +41,54 @@ # if they don't take care of it themselves. # # ----------------------------------------------------------------- -# Installation: +# Installation (quote from bash-completion README): # -# Put it into ~/.bash_completion or /etc/bash_completion.d/ +# Install it in one of the directories pointed to by +# bash-completion's pkgconfig file variables. There are two +# alternatives: the recommended one is 'completionsdir' (get it with +# "pkg-config --variable=completionsdir bash-completion") from which +# completions are loaded on demand based on invoked commands' names, +# so be sure to name your completion file accordingly, and to include +# for example symbolic links in case the file provides completions +# for more than one command. The other one which is present for +# backwards compatibility reasons is 'compatdir' (get it with +# "pkg-config --variable=compatdir bash-completion") from which files +# are loaded when bash_completion is loaded. +# +# For packages using GNU autotools the installation can be handled +# for example like this in configure.ac: +# +# PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], , +# bashcompdir="${sysconfdir}/bash_completion.d") +# AC_SUBST(bashcompdir) +# +# ...accompanied by this in Makefile.am: +# +# bashcompdir = @bashcompdir@ +# dist_bashcomp_DATA = # completion files go here +# +# For cmake we ship the bash-completion-config.cmake and +# bash-completion-config-version.cmake files. Example usage: +# +# find_package(bash-completion) +# if(BASH_COMPLETION_FOUND) +# message(STATUS +# "Using bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}") +# else() +# set (BASH_COMPLETION_COMPLETIONSDIR "/etc/bash_completion.d") +# message (STATUS +# "Using fallback bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}") +# endif() +# +# install(FILES your-completion-file DESTINATION +# ${BASH_COMPLETION_COMPLETIONSDIR}) +# +# For backwards compatibility it is still possible to put it into +# ~/.bash_completion or /etc/bash_completion.d/. # # ----------------------------------------------------------------- # -# Version 2.6 +# Version 2.9.2 # # ----------------------------------------------------------------- @@ -56,14 +98,9 @@ shopt -s extglob # Functions # ----------------------------------------------------------------- -_ipset_colon_ltrim() { -((got_bashcompl)) || return 0 -__ltrim_colon_completions "$1" -} - _ipset_is_set() { local -i idx -((${#arr_sets[@]})) || arr_sets=( $(ipset list -n) ) +((${#arr_sets[@]})) || arr_sets=( $( ( "${words[0]}" list -n ) 2>/dev/null ) ) for idx in ${!arr_sets[@]}; do if [[ ${arr_sets[idx]} = $1 ]]; then return 0 @@ -76,34 +113,32 @@ _ipset_get_set_type() { local n d while read n d; do [[ $n = Type: ]] && printf '%s\n' $d && break -done < <(ipset -t list "$1" 2>/dev/null) +done < <( ( "${words[0]}" -t list "$1" ) 2>/dev/null) } _ipset_set_has_option() { while read -r; do [[ $REPLY = Header:*$1* ]] && return 0 -done < <(ipset -t list "$2") +done < <( ( "${words[0]}" -t list "$2" ) 2>/dev/null) return 1 } _ipset_get_supported_types() { ((${#arr_types[@]})) && return -local -i i=0 +local -i i=0 x while read -r; do [[ $REPLY = "Supported set types:"* ]] && ((!i)) && i=1 && continue ((i)) || continue if [[ $REPLY = *:* ]]; then set -- $REPLY - arr_types+=("$1") + for x in ${!arr_types[@]}; do # check if already registered + if [[ $1 = ${arr_types[x]} ]]; then + continue 2 + fi + done + arr_types+=("$1") # register type fi -done < <(ipset help) -for i in ${!arr_types[@]}; do # remove dupe entries - for ((x=i+1; x < ${#arr_types[@]}; x++)); do - if [[ ${arr_types[i]} = ${arr_types[x]} ]]; then - unset arr_types[x] - fi - done -done +done < <( ( "${words[0]}" help ) 2>/dev/null ) } _ipset_get_members() { @@ -120,7 +155,7 @@ while read -r; do else arr_members+=("$REPLY") fi -done < <(ipset list "$1" 2>/dev/null) +done < <( ( "${words[0]}" list "$1" ) 2>/dev/null) } _ipset_get_set_family() { @@ -128,7 +163,7 @@ while read -r; do [[ $REPLY = Header:*"family inet6"* ]] && printf "v6\n" && return [[ $REPLY = Header:*"family inet "* ]] && printf "v4\n" && return [[ $REPLY = Header:*"range "*.*.*.* ]] && printf "v4\n" && return -done < <(ipset -t list "$1") +done < <( ( "${words[0]}" -t list "$1" ) 2>/dev/null) } _ipset_dedupe_cmd_opts() { @@ -152,35 +187,28 @@ _ipset_get_options() { local str_list local -i idx oidx ridx if ((got_action)); then - case "$str_action" in - rename|e|swap|w|test|flush|destroy|x) - str_list='-q -quiet' - ;; - save) - str_list='-f -file -q -quiet' - ;; - create|n|add|del) - str_list='-! -exist -q -quiet' - ;; - restore) - str_list='-! -exist -f -file -q -quiet' - ;; - list) - str_list='-f -file -q -quiet' - if ((names_only || headers_only)); then - str_list+=' -o -output' - elif ((res_sort)); then - str_list+=' -o -output -r -resolve -s -sorted' - elif ((save_format == 1)); then - str_list+=' -r -resolve -s -sorted -t -terse' - elif ((save_format == 3)); then - str_list+=' -r -resolve -s -sorted' - else - str_list+=' -n -name -o -output -r -resolve \ - -s -sorted -t -terse' - fi - ;; - esac + if [[ $str_action = @(rename|e|swap|w|test|flush|destroy|x) ]]; then + str_list='-q -quiet' + elif [[ $str_action = save ]]; then + str_list='-f -file -q -quiet -o -output' + elif [[ $str_action = @(create|n|add|del) ]]; then + str_list='-! -exist -q -quiet' + elif [[ $str_action = restore ]]; then + str_list='-! -exist -f -file -q -quiet' + elif [[ $str_action = list ]]; then + str_list='-f -file -q -quiet' + if ((names_only || headers_only)); then + str_list+=' -o -output' + elif ((res_sort)); then + str_list+=' -o -output -r -resolve -s -sorted' + elif ((save_format == 1)); then + str_list+=' -r -resolve -s -sorted -t -terse' + elif ((save_format == 3)); then + str_list+=' -r -resolve -s -sorted' + else + str_list+=' -n -name -o -output -r -resolve -s -sorted -t -terse' + fi + fi else str_list='-f -file -q -quiet' if ((names_only || headers_only)) && ((save_format == 1)); then @@ -196,8 +224,8 @@ else elif ((ignore_errors)); then : elif ((use_file)); then - str_list='-! -exist -n -name -o -output -q -quiet -r \ - -resolve -s -sorted -t -terse' + str_list="-! -exist -n -name -o -output -q -quiet -r \ + -resolve -s -sorted -t -terse" else str_list='- ${arr_opts[@]}' fi @@ -334,7 +362,7 @@ _ipset_get_ifnames() { while read -r; do REPLY="${REPLY#*: }" printf "%s\n" ${REPLY%%:*} -done < <(PATH=${PATH}:/sbin command ip -o link show) +done < <(PATH=${PATH}:/sbin ( command ip -o link show ) 2>/dev/null) } _ipset_get_iplist() { @@ -412,7 +440,7 @@ fi if [[ $str_p ]]; then # we have a proto spec COMPREPLY=( $(compgen -P "$str_p:$str_lprefix" \ -W '$(_ipset_get_services -o $str_var -p $str_p)' -- "$lcur" ) ) - _ipset_colon_ltrim "$str_p:$str_lprefix$lcur" + __ltrim_colon_completions "$str_p:$str_lprefix$lcur" else if [[ $str_lprefix ]]; then COMPREPLY=( $(compgen -P "$str_lprefix" \ @@ -447,7 +475,6 @@ for idx in ${!COMPREPLY[@]}; do ((got_bracket)) && unset COMPREPLY[idx] fi done -#_ipset_colon_ltrim "$lcur" } _ipset_complete_iface_spec() { @@ -486,7 +513,7 @@ if [[ $lcur != *,* ]]; then COMPREPLY=( ${COMPREPLY[*]}, ${COMPREPLY[*]}- ) fi fi - _ipset_colon_ltrim "$str_lprefix$lcur" + __ltrim_colon_completions "$str_lprefix$lcur" elif [[ $lcur = *,* ]]; then str_lprefix="${lcur}" lcur="${lcur#*,}" str_var="" str_lprefix="${str_lprefix%"$lcur"}" @@ -499,7 +526,7 @@ elif [[ $lcur = *,* ]]; then COMPREPLY+=( $( compgen -P "$str_lprefix" -W \ '${str_var} $(_ipset_get_ifnames)' -- "$lcur" ) ) [[ ${COMPREPLY[0]} = *physdev: ]] && compopt -o nospace - _ipset_colon_ltrim "$str_lprefix" + __ltrim_colon_completions "$str_lprefix" fi } @@ -551,7 +578,7 @@ else COMPREPLY+=( $( compgen -W \ '$(_ipset_get_iplist "$(_ipset_get_set_family "$str_setname")")' \ -- "$lcur" ) ) - _ipset_colon_ltrim "$lcur" + __ltrim_colon_completions "$lcur" fi _ipset_complete_hostnames "$lcur" if [[ $str_lprefix ]]; then @@ -613,7 +640,7 @@ if [[ $lcur != *,* ]]; then -- "$lcur" ) ) if [[ $str_type = hash:net,port?(,net) ]]; then COMPREPLY+=( $( compgen -W '$(_ipset_get_networks)' -- "$lcur" ) ) - _ipset_colon_ltrim "$lcur" + __ltrim_colon_completions "$lcur" fi _ipset_complete_hostnames "$lcur" if [[ $str_lprefix ]]; then # range spec @@ -626,7 +653,7 @@ if [[ $lcur != *,* ]]; then COMPREPLY=( ${COMPREPLY[*]}, ) fi fi - _ipset_colon_ltrim "$str_lprefix$lcur" + __ltrim_colon_completions "$str_lprefix$lcur" elif [[ $lcur =~ $str_regex ]]; then compopt -o nospace str_glob='[^[]*-' # otherwise messes up my vim syntax highlightning @@ -653,7 +680,7 @@ elif [[ $lcur =~ $str_regex ]]; then if [[ $str_lprefix = *:* ]]; then str_lprefix="${str_lprefix%:*}:" fi - _ipset_colon_ltrim "${str_lprefix}" + __ltrim_colon_completions "${str_lprefix}" if ((${#COMPREPLY[@]} == 1)); then if [[ $str_lprefix && $str_type != hash:@(ip|net),port,@(ip|net) ]]; then compopt +o nospace @@ -676,7 +703,7 @@ elif [[ $lcur =~ $str_regex ]]; then COMPREPLY+=( $( compgen -P "$str_lprefix" -W \ '$(_ipset_get_services -p $str_var)' -- "$lcur" ) ) fi - _ipset_colon_ltrim "$str_lprefix" + __ltrim_colon_completions "$str_lprefix" elif [[ $lcur = *,* ]]; then # first attempt :/ long list str_lprefix="${lcur%,*}," lcur="${lcur#*,}" str_var="tcp: udp: sctp: udplite: icmp: icmp6:" @@ -686,7 +713,7 @@ elif [[ $lcur =~ $str_regex ]]; then # add the protocols COMPREPLY+=( $( compgen -P "$str_lprefix" -S ":0$str_suffix" -W \ '$(_ipset_get_protocols)' -- "$lcur" ) ) - _ipset_colon_ltrim "$str_lprefix$lcur" + __ltrim_colon_completions "$str_lprefix$lcur" compopt -o nospace fi elif [[ $lcur = *,*,* && $str_type = hash:@(ip,port,@(ip|net)|net,port,net) ]]; then @@ -727,7 +754,7 @@ elif [[ $lcur = *,*,* && $str_type = hash:@(ip,port,@(ip|net)|net,port,net) ]]; COMPREPLY=( $( compgen -P "$str_lprefix2" \ -W '${COMPREPLY[@]}' -- "$lcur2" ) ) fi - _ipset_colon_ltrim "$str_lprefix2$lcur2" + __ltrim_colon_completions "$str_lprefix2$lcur2" if ((${#COMPREPLY[@]} == 1)); then if [[ $str_type = hash:@(ip|net),port,net && \ ${COMPREPLY[*]##*,} != */* ]] @@ -802,7 +829,7 @@ if ((y)); then [[ $addr =~ $str_regex ]] && printf "%s\n" "$addr" done < /etc/ethers)" fi - printf "%s\n" "$str_tmp" + printf "%s\n" "$str_tmp" fi } @@ -811,6 +838,8 @@ fi # ----------------------------------------------------------------- _ipset_complete() { +# at least bash 4 is required +((${BASH_VERSINFO[0]} < 4)) && return 0 local cur prev cword words ips_version local str_action str_setname str_type str_filename local str_glob str_regex str_prefix str_suffix @@ -822,7 +851,7 @@ local -i i=x=y=0 local -i got_bashcompl=got_action=action_index=order_index=set_has_timeout=0 local -i got_bp_proto=0 local -i ignore_errors=use_file=names_only=headers_only=save_format=res_sort=0 -local arr_sets=() arr_types=() arr_members=() arr_unknown_opts=() +local arr_sets=() arr_types=() arr_members=() local arr_dupe_cmd_opts=() arr_used_opts=() arr_tmp=() local arr_opts=( "-! -exist" @@ -894,19 +923,45 @@ neigbour-advertisement redirect ) -# at least bash 4 is required -((${BASH_VERSINFO[0]} < 4)) && return 0 - COMPREPLY=() +# expecting _get_comp_words_by_ref() to exist from bash_completion +if declare -f _get_comp_words_by_ref &>/dev/null; then got_bashcompl=1 + _get_comp_words_by_ref -n : cur prev cword words || return +else got_bashcompl=0 # not so neat, but a workaround + COMP_WORDBREAKS="${COMP_WORDBREAKS//:/}" + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + cword=$COMP_CWORD + for i in ${!COMP_WORDS[@]}; do words[i]="${COMP_WORDS[i]}"; done +fi + # ipset version check 6.x upwards (to v?) is supported -ips_version="$(ipset version)" -ips_version="${ips_version#ipset v}" -ips_version="${ips_version%,+([[:blank:]])protocol*}" -read -a ips_version <<< ${ips_version//./ } -[[ ${ips_version[0]} = +([[:digit:]]) ]] || return 1 + +# All calls of ipset should be done in a subshell with stderr +# pointing to /dev/null, to avoid printing of +# `-bash command ipset not found' errors + +i=0 # for safety +if ((UID != 0)); then # not root user + "${words[0]}" version &>/dev/null # can we retrieve the version? + i=$? +fi +if ((i == 0)); then + ips_version="$("${words[0]}" version)" + ips_version="${ips_version#ipset v}" + ips_version="${ips_version%,+([[:blank:]])protocol*}" + read -a ips_version <<< ${ips_version//./ } + [[ ${ips_version[0]} = +([[:digit:]]) ]] || return 1 +else + # assume we have no permissions to run ipset + # set version to 6.22 = show all features + # though many things won't work, as of missing permissions + ips_version=( 6 22 ) +fi ((ips_version[0] < 6)) && return 1 + # ipset -ge v6.19 has counters flag # ipset -ge v6.20 has comment flag # ipset -ge v6.21 has hash:ip,mark markmask flag @@ -938,45 +993,22 @@ elif ((ips_version[0] == 6)); then str_bp_counters="bytes packets" fi else + # ipset versions -lt 6 are not supported return 0 fi -# expecting _get_comp_words_by_ref() to exist from bash_completion -if declare -f _get_comp_words_by_ref &>/dev/null; then got_bashcompl=1 - _get_comp_words_by_ref -n : cur prev cword words || return -else got_bashcompl=0 # not so neat, but a workaround - COMP_WORDBREAKS="${COMP_WORDBREAKS//:/}" - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - cword=$COMP_CWORD - for i in ${!COMP_WORDS[@]}; do words[i]="${COMP_WORDS[i]}"; done -fi - -if ((got_bashcompl)); then -# current bash completion got a bug i reported: -# https://alioth.debian.org/tracker/index.php?func=detail&aid=314056&group_id=100114&atid=413095 -# putting corrected function here, so things don't break -__ltrim_colon_completions() { - if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then - # Remove colon-word prefix from COMPREPLY items - local colon_word="${1%"${1##*:}"}" - local i=${#COMPREPLY[*]} - while [[ $((--i)) -ge 0 ]]; do - COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"} - done - fi -} - # construct own known_hosts function from origin # just remove the __ltrim_colon_completions call # to avoid unwanted ltrim if we need to work with the list of hosts # ugly hack - gimme better ;p -if ! declare -F _ipset_known_hosts &>/dev/null; then -eval '_ipset_known_hosts() { '$(declare -f _known_hosts_real | grep -v __ltrim_colon_completions | grep -Ev "^_known_hosts_real.*$" | grep -Ev "^(\{|\})")'; }' -fi +if ((got_bashcompl)); then + if ! declare -F _ipset_known_hosts &>/dev/null; then + eval '_ipset_known_hosts() { '$(declare -f _known_hosts_real | \ + grep -v __ltrim_colon_completions | \ + grep -Ev "^_known_hosts_real.*$" | grep -Ev "^(\{|\})")'; }' + fi fi -#_DEBUG_NF_COMPLETION=Y if [[ $_DEBUG_NF_COMPLETION ]]; then printf "\nCOMP_WORDBREAKS: <%s>\n" "$COMP_WORDBREAKS" printf "COMP_LINE: <%s>\n" "$COMP_LINE" @@ -991,78 +1023,66 @@ fi # collect information about used options for ((i=1; i < ${#words[@]}-1; i++)); do -case "${words[i]}" in - @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w|help|version)) - [[ ${words[i-1]} = @(-f|-file) ]] && continue # there could be a file named like a command - if ! ((got_action)); then - if [[ ${words[i]} != save ]]; then - got_action=1 action_index=$i str_action=${words[i]} - elif [[ ${words[i-1]} != @(-o|-output) ]]; then - got_action=1 action_index=$i str_action=${words[i]} - fi - if [[ $str_action = @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w) ]] - then str_setname=${words[i+1]} # register the set name - fi +if [[ ${words[i]} = @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w|help|version) ]] +then + [[ ${words[i-1]} = @(-f|-file) ]] && continue # could be a file named like a command + if ! ((got_action)); then + if [[ ${words[i]} != save ]]; then + got_action=1 action_index=$i str_action=${words[i]} + elif [[ ${words[i-1]} != @(-o|-output) ]]; then + got_action=1 action_index=$i str_action=${words[i]} fi - ;; - -\!|-exist) - [[ ${words[i-1]} != @(-f|-file) ]] &&\ - ignore_errors=1 arr_used_opts+=(${words[i]}) - ;; - -f|-file) - [[ ${words[i-1]} != @(-f|-file) ]] &&\ - use_file=1 str_filename="${words[i+1]}" \ - arr_used_opts+=(${words[i]}) - ;; - -n|-name) - [[ ${words[i-1]} != @(-f|-file) ]] &&\ - names_only=1 arr_used_opts+=(${words[i]}) - ;; - -t|-terse) - [[ ${words[i-1]} != @(-f|-file) ]] &&\ - headers_only=1 arr_used_opts+=(${words[i]}) - ;; - -o|-output) - if [[ ${words[i-1]} != @(-f|-file) ]]; then - arr_used_opts+=(${words[i]}) - if [[ $prev = @(-o|-output) ]]; then - save_format=2 # expecting opt-arg - elif [[ ${words[i+1]} = save ]]; then - save_format=3 # no -n/-t with -o save - else - save_format=1 - fi + if [[ $str_action = @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w) ]] + then + str_setname=${words[i+1]} # register the set name fi - ;; - -r|-resolve|-s|-sorted) - [[ ${words[i-1]} != @(-f|-file) ]] &&\ - res_sort=1 arr_used_opts+=(${words[i]}) - ;; - -q|-quiet) + fi +elif [[ ${words[i]} = @(-\!|-exist) ]]; then + if [[ ${words[i-1]} != @(-f|-file) ]]; then + ignore_errors=1 arr_used_opts+=(${words[i]}) + fi +elif [[ ${words[i]} = @(-f|-file) ]]; then + if [[ ${words[i-1]} != @(-f|-file) ]]; then + use_file=1 str_filename="${words[i+1]}" arr_used_opts+=(${words[i]}) + fi +elif [[ ${words[i]} = @(-n|-name) ]]; then + if [[ ${words[i-1]} != @(-f|-file) ]]; then + names_only=1 arr_used_opts+=(${words[i]}) + fi +elif [[ ${words[i]} = @(-t|-terse) ]]; then + if [[ ${words[i-1]} != @(-f|-file) ]]; then + headers_only=1 arr_used_opts+=(${words[i]}) + fi +elif [[ ${words[i]} = @(-o|-output) ]]; then + if [[ ${words[i-1]} != @(-f|-file) ]]; then arr_used_opts+=(${words[i]}) - ;; -# -?*) -# if [[ ${words[i]#-} != @(q|quiet) ]]; then -# # don't include filenames -# if [[ ${words[i-1]} != @(-f|-file|\>) || ${words[i+1]} != \< ]]; then -# arr_unknown_opts[${#arr_unknown_opts[@]}]="${words[i]}" -# fi -# fi -# ;; - before|after) - if ((got_action && ! order_index && i == action_index+3)); then - order_index=$i str_order="" - fi - ;; - timeout|range|maxelem|family|hashsize|size|netmask|nomatch|counters|bytes|packets|comment|markmask|forceadd|skbinfo|skbmark|skbprio|skbqueue) - if ((got_action && i > action_index+2)); then - str_tmp="$COMP_LINE" - [[ $str_setname = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}" - [[ $str_filename = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}" - [[ $str_tmp = *${words[i]}* ]] && arr_dupe_cmd_opts[${#arr_dupe_cmd_opts[@]}]="${words[i]}" + if [[ $prev = @(-o|-output) ]]; then + save_format=2 # expecting opt-arg + elif [[ ${words[i+1]} = save ]]; then + save_format=3 # no -n/-t with -o save + else + save_format=1 fi - ;; -esac + fi +elif [[ ${words[i]} = @(-r|-resolve|-s|-sorted) ]]; then + if [[ ${words[i-1]} != @(-f|-file) ]]; then + res_sort=1 arr_used_opts+=(${words[i]}) + fi +elif [[ ${words[i]} = @(-q|-quiet) ]]; then + arr_used_opts+=(${words[i]}) +elif [[ ${words[i]} = @(before|after) ]]; then + if ((got_action && ! order_index && i == action_index+3)); then + order_index=$i str_order="" + fi +elif [[ ${words[i]} = @(timeout|range|maxelem|family|hashsize|size|netmask|nomatch|counters|bytes|packets|comment|markmask|forceadd|skbinfo|skbmark|skbprio|skbqueue) ]] +then + if ((got_action && i > action_index+2)); then + str_tmp="$COMP_LINE" + [[ $str_setname = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}" + [[ $str_filename = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}" + [[ $str_tmp = *${words[i]}* ]] && arr_dupe_cmd_opts[${#arr_dupe_cmd_opts[@]}]="${words[i]}" + fi +fi done if [[ $_DEBUG_NF_COMPLETION ]]; then @@ -1076,7 +1096,6 @@ if [[ $_DEBUG_NF_COMPLETION ]]; then printf "ignore_errors: <%s>\n" "$ignore_errors" printf "names_only: <%s>\n" "$names_only" printf "headers_only: <%s>\n" "$headers_only" -# printf "arr_unknown_opts: <%s>\n" "${arr_unknown_opts[@]}" printf "arr_used_opts: <%s>\n" "${arr_used_opts[@]}" printf "arr_dupe_cmd_opts: <%s>\n" "${arr_dupe_cmd_opts[@]}" fi @@ -1094,13 +1113,6 @@ elif ((ignore_errors)); then fi fi -#case "$cur" in # depend on current -# \<|\>) # redirection operator -# compopt -o nospace -# COMPREPLY=( $( compgen -f ) ) # no $cur, so completion starts without space after redirection -# return 0 -# ;; -#esac # catch variables and command substitution if [[ $cur == \$\(* ]]; then # command substitution COMPREPLY=( $(compgen -c -P '$(' ${cur#??}) ) @@ -1113,28 +1125,26 @@ elif [[ $cur == \$* ]]; then # variables with a leading `$' return 0 fi -case "$prev" in # depend on previous option - -o|-output) - # make sure it's not a filename named -o or -output - if [[ $str_filename != $prev ]]; then - if ((names_only || headers_only)); then - COMPREPLY=( $( compgen -W 'plain xml' -- "$cur" ) ) - else - COMPREPLY=( $( compgen -W 'plain save xml' -- "$cur" ) ) - fi - return 0 - fi - ;; - -f|-file|\<|\>) - if ((got_bashcompl)); then - _filedir +# depend on previous option +if [[ $prev = @(-o|-output) ]]; then + # make sure it's not a filename named -o or -output + if [[ $str_filename != $prev ]]; then + if ((names_only || headers_only)); then + COMPREPLY=( $( compgen -W 'plain xml' -- "$cur" ) ) else - compopt -o nospace - COMPREPLY=( $( compgen -f -- "$cur" ) ) + COMPREPLY=( $( compgen -W 'plain save xml' -- "$cur" ) ) fi return 0 - ;; -esac + fi +elif [[ $prev = @(-f|-file|\<|\>) ]]; then + if ((got_bashcompl)); then + _filedir + else + compopt -o nospace + COMPREPLY=( $( compgen -f -- "$cur" ) ) + fi + return 0 +fi if ((got_action)); then # we got the main action # Disallow sets with names of options starting with a hyphen @@ -1147,412 +1157,374 @@ then fi if ((cword == action_index+1)) && [[ $str_action = $prev ]]; then # depend on previous option which should be the action - case "$str_action" in -# create|n|version) : -# ;; - help) - _ipset_get_supported_types - COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) ) - _ipset_colon_ltrim "$cur" - ;; - add|del|rename|e|swap|w|test) - COMPREPLY=( $( compgen -W '$(ipset list -n)' -- "$cur" ) ) - _ipset_colon_ltrim "$cur" - ;; - list|flush|save|destroy|x) - # we don't know if its an option request, could also be a set - # named `-*', if the latter is true, show sets and options - if [[ $cur = -* ]]; then - _ipset_get_options - if _ipset_is_set "${cur}*"; then - COMPREPLY=( $( compgen -W '${arr_sets[@]}' -- "$cur" ) ) - _ipset_colon_ltrim "$cur" - fi - else - COMPREPLY=( $( compgen -W '$(ipset list -n)' -- "$cur" ) ) - _ipset_colon_ltrim "$cur" - fi - ;; - restore) - if [[ $cur = -* ]]; then - _ipset_get_options - elif ! [[ $str_filename ]]; then - # don't show redirector if we have option -f - COMPREPLY=( \< ) + # create|n|version - take no aktion + if [[ $str_action = help ]]; then + _ipset_get_supported_types + COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) ) + __ltrim_colon_completions "$cur" + elif [[ $str_action = @(add|del|rename|e|swap|w|test) ]]; then + COMPREPLY=( $( compgen -W '$( ( "${words[0]}" list -n ) 2>/dev/null )' -- "$cur" ) ) + __ltrim_colon_completions "$cur" + elif [[ $str_action = @(list|flush|save|destroy|x) ]]; then + # we don't know if its an option request, could also be a set + # named `-*', if the latter is true, show sets and options + if [[ $cur = -* ]]; then + _ipset_get_options + if _ipset_is_set "${cur}*"; then + COMPREPLY=( $( compgen -W '${arr_sets[@]}' -- "$cur" ) ) + __ltrim_colon_completions "$cur" fi - ;; - esac + else + COMPREPLY=( $( compgen -W '$( ( "${words[0]}" list -n ) 2>/dev/null )' -- "$cur" ) ) + __ltrim_colon_completions "$cur" + fi + elif [[ $str_action = restore ]]; then + if [[ $cur = -* ]]; then + _ipset_get_options + elif ! [[ $str_filename ]]; then + # don't show redirector if we have option -f + COMPREPLY=( \< ) + fi + fi elif ((cword == action_index+2)) && [[ $str_setname = $prev ]]; then - case "$str_action" in -# rename|e) : -# ;; - save|restore|list|flush|destroy|x) - if [[ $cur = -* ]]; then - _ipset_get_options + # rename|e - take no aktion + if [[ $str_action = @(save|restore|list|flush|destroy|x) ]]; then + if [[ $cur = -* ]]; then + _ipset_get_options + fi + elif [[ $str_action = @(create|n) ]]; then + _ipset_get_supported_types + COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) ) + __ltrim_colon_completions "$cur" + elif [[ $str_action = @(swap|w) ]]; then # list two sets + COMPREPLY=( $( compgen -W '$( ( "${words[0]}" list -n ) 2>/dev/null )' -- "$cur" ) ) + for i in ${!COMPREPLY[@]}; do # remove the dupe setname from the list + [[ ${COMPREPLY[i]} = $str_setname ]] && unset COMPREPLY[i] && break + done + __ltrim_colon_completions "$cur" + elif [[ $str_action = add ]]; then + str_type=$(_ipset_get_set_type "$str_setname") + if [[ $str_type = bitmap:ip ]]; then + _ipset_complete_host_spec "$cur" --v4 + __ltrim_colon_completions "$cur" + elif [[ $str_type = @(hash:ip|hash:net|hash:ip,mark) ]]; then + _ipset_complete_host_spec "$cur" + __ltrim_colon_completions "$cur" + elif [[ $str_type = hash:net,iface ]]; then + _ipset_complete_iface_spec "$cur" + elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]] + then + _ipset_complete_hostport_spec "$cur" + elif [[ $str_type = hash:net,net ]]; then + _ipset_complete_netnet_spec "$cur" + __ltrim_colon_completions "$cur" + elif [[ $str_type = hash:mac ]]; then + COMPREPLY=( $( compgen -W '$(_ipset_complete_mac_spec)' -- "$cur" ) ) + __ltrim_colon_completions "$cur" + elif [[ $str_type = bitmap:ip,mac ]]; then + if [[ $cur = *,* ]]; then + str_prefix="$cur" cur="${cur#*,}" + str_prefix="${str_prefix%$cur}" + COMPREPLY+=( $( compgen -P "$str_prefix" -W '$(_ipset_complete_mac_spec)' \ + -- "$cur" ) ) + __ltrim_colon_completions "$str_prefix$cur" + else + compopt -o nospace + _ipset_complete_host_spec "$cur" --v4 --no-range + __ltrim_colon_completions "$cur" + if ((${#COMPREPLY[@]} == 1)); then + COMPREPLY=( ${COMPREPLY[*]}, ) + fi fi - ;; - @(create|n)) - _ipset_get_supported_types - COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) ) - _ipset_colon_ltrim "$cur" - ;; - @(swap|w)) # list two sets - COMPREPLY=( $( compgen -W '$(ipset list -n)' -- "$cur" ) ) - for i in ${!COMPREPLY[@]}; do # remove the dupe setname from the list - [[ ${COMPREPLY[i]} = $str_setname ]] && unset COMPREPLY[i] && break + elif [[ $str_type = bitmap:port ]]; then # complete port [range] + _ipset_complete_portrange "$cur" + elif [[ $str_type = list:* ]]; then + # show sets if the set to add is of type list:set + arr_tmp=() arr_sets=( $( ( "${words[0]}" list -n ) 2>/dev/null ) ) + _ipset_get_members --names-only "$str_setname" + for x in ${!arr_sets[@]}; do + [[ ${arr_sets[x]} = $str_setname ]] && continue + for y in ${!arr_members[@]}; do + [[ ${arr_sets[x]} = ${arr_members[y]} ]] && continue 2 + done + arr_tmp+=("${arr_sets[x]}") done - _ipset_colon_ltrim "$cur" - ;; - add) - str_type=$(_ipset_get_set_type "$str_setname") - case "$str_type" in - bitmap:ip) - _ipset_complete_host_spec "$cur" --v4 - _ipset_colon_ltrim "$cur" - ;; - hash:ip|hash:net|hash:ip,mark) - _ipset_complete_host_spec "$cur" - _ipset_colon_ltrim "$cur" - ;; - hash:net,iface) - _ipset_complete_iface_spec "$cur" - ;; - hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net)) - _ipset_complete_hostport_spec "$cur" - ;; - hash:net,net) - _ipset_complete_netnet_spec "$cur" - _ipset_colon_ltrim "$cur" - ;; - hash:mac) - COMPREPLY=( $( compgen -W '$(_ipset_complete_mac_spec)' -- "$cur" ) ) - _ipset_colon_ltrim "$cur" - ;; - bitmap:ip,mac) - if [[ $cur = *,* ]]; then - str_prefix="$cur" cur="${cur#*,}" - str_prefix="${str_prefix%$cur}" - COMPREPLY+=( $( compgen -P "$str_prefix" -W '$(_ipset_complete_mac_spec)' \ - -- "$cur" ) ) - _ipset_colon_ltrim "$str_prefix$cur" - else - compopt -o nospace - _ipset_complete_host_spec "$cur" --v4 --no-range - _ipset_colon_ltrim "$cur" - if ((${#COMPREPLY[@]} == 1)); then - COMPREPLY=( ${COMPREPLY[*]}, ) + COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) ) + __ltrim_colon_completions "$cur" + fi + elif [[ $str_action = del ]]; then + str_type=$(_ipset_get_set_type "$str_setname") + if [[ $str_type = bitmap:ip ]]; then + str_prefix="" + if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" + elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then + _ipset_complete_host_spec "$cur" --v4 + __ltrim_colon_completions "$cur" + else + _ipset_complete_host_spec "$cur" --v4 + _ipset_complete_elements "$cur" + __ltrim_colon_completions "$cur" + fi + elif [[ $str_type = bitmap:port ]]; then + str_prefix="" + if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" + elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then + _ipset_complete_portrange "$cur" + else + _ipset_complete_portrange "$cur" + _ipset_get_members --names-only "$str_setname" + str_glob='?(tcp:|udp:)@([![]*-*|\[?*\]-*)' + if [[ $cur = $str_glob ]]; then + str_var="${cur#?(tcp:|udp:)}" # offset + str_tmp="${cur%"$str_var"}" # proto + # identify service number by name, to find the offset + if [[ $str_var != +([[:digit:]]) ]]; then + if [[ $str_var = \[+([![])\]-* ]]; then + str_var="${str_var%%\]*}" + str_var="${str_var#\[}" + elif [[ $str_var = *-* ]]; then + str_var="${str_var%%-*}" fi + str_var=$(_ipset_get_svnum -p "${str_tmp:-all}" -o "$str_var") fi - ;; - bitmap:port) - # complete port [range] - _ipset_complete_portrange "$cur" - ;; - # show sets if the set to add is of type list:set - list:*) arr_tmp=() arr_sets=( $(ipset list -n) ) - _ipset_get_members --names-only "$str_setname" - for x in ${!arr_sets[@]}; do - [[ ${arr_sets[x]} = $str_setname ]] && continue - for y in ${!arr_members[@]}; do - [[ ${arr_sets[x]} = ${arr_members[y]} ]] && continue 2 + if [[ $str_var = +([[:digit:]]) ]]; then + for i in ${!arr_members[@]}; do + ((${arr_members[i]} <= $str_var)) && \ + unset arr_members[i] || break done - arr_tmp+=("${arr_sets[x]}") - done - COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) ) - _ipset_colon_ltrim "$cur" - ;; - esac - ;; - del) - str_type=$(_ipset_get_set_type "$str_setname") - if [[ $str_type = bitmap:ip ]]; then - str_prefix="" - if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" - elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then - _ipset_complete_host_spec "$cur" --v4 - _ipset_colon_ltrim "$cur" - else - _ipset_complete_host_spec "$cur" --v4 - _ipset_complete_elements "$cur" - _ipset_colon_ltrim "$cur" - fi - elif [[ $str_type = bitmap:port ]]; then - str_prefix="" - if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" - elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then - _ipset_complete_portrange "$cur" - else - _ipset_complete_portrange "$cur" - _ipset_get_members --names-only "$str_setname" - str_glob='?(tcp:|udp:)@([![]*-*|\[?*\]-*)' - if [[ $cur = $str_glob ]]; then - str_var="${cur#?(tcp:|udp:)}" # offset - str_tmp="${cur%"$str_var"}" # proto - # identify service number by name, to find the offset - if [[ $str_var != +([[:digit:]]) ]]; then - if [[ $str_var = \[+([![])\]-* ]]; then - str_var="${str_var%%\]*}" - str_var="${str_var#\[}" - elif [[ $str_var = *-* ]]; then - str_var="${str_var%%-*}" - fi - str_var=$(_ipset_get_svnum -p "${str_tmp:-all}" -o "$str_var") - fi - if [[ $str_var = +([[:digit:]]) ]]; then - for i in ${!arr_members[@]}; do - ((${arr_members[i]} <= $str_var)) && \ - unset arr_members[i] || break - done - fi - str_prefix="${cur%-*}-" cur="${cur##*-}" fi - COMPREPLY+=( $( compgen -P "$str_prefix" -W '${arr_members[@]}' -- "$cur" ) ) - fi - elif [[ $str_type = bitmap:ip,mac ]]; then - str_prefix="" - if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" - elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then - _ipset_complete_host_spec "$cur" --v4 --no-range - _ipset_colon_ltrim "$cur" - else - _ipset_complete_host_spec "$cur" --v4 --no-range - _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" - fi - elif [[ $str_type = hash:@(ip?(,mark)|net) ]]; then - str_prefix="" - if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" - _ipset_colon_ltrim "$cur" - elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then - _ipset_complete_host_spec "$cur" - _ipset_colon_ltrim "$cur" - else - _ipset_complete_host_spec "$cur" - _ipset_complete_elements "$cur" - _ipset_colon_ltrim "$cur" - fi - elif [[ $str_type = hash:net,net ]]; then - if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" - _ipset_colon_ltrim "$cur" - elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then - _ipset_complete_netnet_spec "$cur" - _ipset_colon_ltrim "$cur" - else - _ipset_complete_netnet_spec "$cur" - _ipset_complete_elements "$cur" - _ipset_colon_ltrim "$cur" - fi - elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]] - then - if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" - elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then - _ipset_complete_hostport_spec "$cur" - else - _ipset_complete_elements "$cur" --no-range - _ipset_complete_hostport_spec "$cur" - _ipset_colon_ltrim "$cur" - fi - elif [[ $str_type = hash:net,iface ]]; then - if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" - elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then - _ipset_complete_iface_spec "$cur" - else - _ipset_complete_elements "$cur" --no-range - _ipset_complete_iface_spec "$cur" - _ipset_colon_ltrim "$cur" + str_prefix="${cur%-*}-" cur="${cur##*-}" fi + COMPREPLY+=( $( compgen -P "$str_prefix" -W '${arr_members[@]}' -- "$cur" ) ) + fi + elif [[ $str_type = bitmap:ip,mac ]]; then + str_prefix="" + if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" --no-range + __ltrim_colon_completions "$cur" + elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then + _ipset_complete_host_spec "$cur" --v4 --no-range + __ltrim_colon_completions "$cur" else + _ipset_complete_host_spec "$cur" --v4 --no-range _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" + __ltrim_colon_completions "$cur" fi - ;; - test) - str_type=$(_ipset_get_set_type "$str_setname") - if [[ $str_type = bitmap:ip ]]; then - if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" --no-range - elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then - _ipset_complete_host_spec "$cur" --no-range --v4 - else - _ipset_complete_elements "$cur" --no-range - if ! _ipset_complete_host_spec "$cur" --no-range --v4; then - COMPREPLY=() - fi - fi - elif [[ $str_type = hash:ip?(,mark) ]]; then - if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" - elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then - _ipset_complete_host_spec "$cur" --no-range - _ipset_colon_ltrim "$cur" - else - _ipset_complete_elements "$cur" --no-range - if ! _ipset_complete_host_spec "$cur" --no-range; then - COMPREPLY=() - fi - _ipset_colon_ltrim "$cur" - fi - elif [[ $str_type = hash:net ]]; then - if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" - elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then - _ipset_complete_host_spec "$cur" - _ipset_colon_ltrim "$cur" - else - _ipset_complete_elements "$cur" --no-range - if ! _ipset_complete_host_spec "$cur"; then - COMPREPLY=() - fi - _ipset_colon_ltrim "$cur" - fi - elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]] - then - if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" - elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then - _ipset_complete_hostport_spec "$cur" - else - _ipset_complete_elements "$cur" --no-range - _ipset_complete_hostport_spec "$cur" - _ipset_colon_ltrim "$cur" - fi - elif [[ $str_type = hash:net,iface ]]; then - if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" - elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then - _ipset_complete_iface_spec "$cur" - else - _ipset_complete_elements "$cur" --no-range - _ipset_complete_iface_spec "$cur" - _ipset_colon_ltrim "$cur" - fi - elif [[ $str_type = bitmap:port ]]; then - str_prefix="" str_tmp="$cur" - if [[ $cur = @(tcp|udp):* ]]; then - ((got_bp_proto)) || return 0 # supported since ipset v6.20 - str_prefix="${cur%:*}" - str_tmp="${str_tmp#${str_prefix}:}" - fi - if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then - _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" - elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then - if ((got_bp_proto)); then # supported since ipset v6.20 - COMPREPLY=( $(compgen -W \ - 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) ) - [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace - _ipset_colon_ltrim "$cur" - else # only tcp services prior to ipset v6.20 - COMPREPLY=( $(compgen \ - -W '$(_ipset_get_services -p tcp)' -- "$cur" ) ) - fi - else - if ((got_bp_proto)); then # supported since ipset v6.20 - COMPREPLY=( $(compgen -W \ - 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) ) - [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace - _ipset_colon_ltrim "$cur" - else # only tcp services prior to ipset v6.20 - COMPREPLY=( $(compgen \ - -W '$(_ipset_get_services -p tcp)' -- "$cur" ) ) - fi - _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" + elif [[ $str_type = hash:@(ip?(,mark)|net) ]]; then + str_prefix="" + if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" + __ltrim_colon_completions "$cur" + elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then + _ipset_complete_host_spec "$cur" + __ltrim_colon_completions "$cur" + else + _ipset_complete_host_spec "$cur" + _ipset_complete_elements "$cur" + __ltrim_colon_completions "$cur" + fi + elif [[ $str_type = hash:net,net ]]; then + if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" + __ltrim_colon_completions "$cur" + elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then + _ipset_complete_netnet_spec "$cur" + __ltrim_colon_completions "$cur" + else + _ipset_complete_netnet_spec "$cur" + _ipset_complete_elements "$cur" + __ltrim_colon_completions "$cur" + fi + elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]] + then + if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" --no-range + __ltrim_colon_completions "$cur" + elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then + _ipset_complete_hostport_spec "$cur" + else + _ipset_complete_elements "$cur" --no-range + _ipset_complete_hostport_spec "$cur" + __ltrim_colon_completions "$cur" + fi + elif [[ $str_type = hash:net,iface ]]; then + if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" --no-range + __ltrim_colon_completions "$cur" + elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then + _ipset_complete_iface_spec "$cur" + else + _ipset_complete_elements "$cur" --no-range + _ipset_complete_iface_spec "$cur" + __ltrim_colon_completions "$cur" + fi + else + _ipset_complete_elements "$cur" --no-range + __ltrim_colon_completions "$cur" + fi + elif [[ $str_action = test ]]; then + str_type=$(_ipset_get_set_type "$str_setname") + if [[ $str_type = bitmap:ip ]]; then + if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" --no-range + elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then + _ipset_complete_host_spec "$cur" --no-range --v4 + else + _ipset_complete_elements "$cur" --no-range + if ! _ipset_complete_host_spec "$cur" --no-range --v4; then + COMPREPLY=() fi + fi + elif [[ $str_type = hash:ip?(,mark) ]]; then + if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" --no-range + __ltrim_colon_completions "$cur" + elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then + _ipset_complete_host_spec "$cur" --no-range + __ltrim_colon_completions "$cur" else _ipset_complete_elements "$cur" --no-range - _ipset_colon_ltrim "$cur" + if ! _ipset_complete_host_spec "$cur" --no-range; then + COMPREPLY=() + fi + __ltrim_colon_completions "$cur" fi - ;; - esac -elif ((cword == action_index+3)) && [[ $cur != -* ]]; then - case "$str_action" in - add) - str_type=$(_ipset_get_set_type "$str_setname") - if _ipset_set_has_option timeout "$str_setname"; then - str_timeout=timeout + elif [[ $str_type = hash:net ]]; then + if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" --no-range + __ltrim_colon_completions "$cur" + elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then + _ipset_complete_host_spec "$cur" + __ltrim_colon_completions "$cur" else - str_timeout="" + _ipset_complete_elements "$cur" --no-range + if ! _ipset_complete_host_spec "$cur"; then + COMPREPLY=() + fi + __ltrim_colon_completions "$cur" fi - if ! _ipset_set_has_option counters "$str_setname"; then - str_bp_counters="" + elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]] + then + if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" --no-range + __ltrim_colon_completions "$cur" + elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then + _ipset_complete_hostport_spec "$cur" + else + _ipset_complete_elements "$cur" --no-range + _ipset_complete_hostport_spec "$cur" + __ltrim_colon_completions "$cur" fi - if ! _ipset_set_has_option comment "$str_setname"; then - str_comment="" + elif [[ $str_type = hash:net,iface ]]; then + if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" --no-range + __ltrim_colon_completions "$cur" + elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then + _ipset_complete_iface_spec "$cur" + else + _ipset_complete_elements "$cur" --no-range + _ipset_complete_iface_spec "$cur" + __ltrim_colon_completions "$cur" fi - if ! _ipset_set_has_option skbinfo "$str_setname"; then - str_skbflags="" + elif [[ $str_type = bitmap:port ]]; then + str_prefix="" str_tmp="$cur" + if [[ $cur = @(tcp|udp):* ]]; then + ((got_bp_proto)) || return 0 # supported since ipset v6.20 + str_prefix="${cur%:*}" + str_tmp="${str_tmp#${str_prefix}:}" fi - case "$str_type" in - hash:*net*) - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \ - -- "$cur" ) ) - ;; - hash:*!(net)*|bitmap:*) - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_skbflags $str_comment)' \ - -- "$cur" ) ) - ;; - list:*) - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_skbflags $str_comment)' \ - -- "$cur" ) ) - ;; - esac - ;; - create|n) - case "$prev" in - hash:ip,mark) - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_markmask $str_comment $str_forceadd)' \ - -- "$cur" ) ) - ;; - hash:*) - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_comment $str_forceadd)' \ - -- "$cur" ) ) - ;; - bitmap:ip) - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_skbinfo $str_comment)' \ - -- "$cur" ) ) - ;; - bitmap:!(ip)?*) - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_skbinfo $str_comment)' \ - -- "$cur" ) ) - ;; - list:*) - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_skbinfo $str_comment)' \ - -- "$cur" ) ) - ;; - esac - ;; - del|test) - str_type=$(_ipset_get_set_type "$str_setname") - if [[ $str_type = list:* ]]; then - COMPREPLY=( $( compgen -W '$str_order' -- "$cur" ) ) - elif [[ $str_action = test && $str_type = hash:*net* ]]; then - COMPREPLY=( $( compgen -W 'nomatch' -- "$cur" ) ) + if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then + _ipset_complete_elements "$cur" --no-range + __ltrim_colon_completions "$cur" + elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then + if ((got_bp_proto)); then # supported since ipset v6.20 + COMPREPLY=( $(compgen -W \ + 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) ) + [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace + __ltrim_colon_completions "$cur" + else # only tcp services prior to ipset v6.20 + COMPREPLY=( $(compgen \ + -W '$(_ipset_get_services -p tcp)' -- "$cur" ) ) + fi + else + if ((got_bp_proto)); then # supported since ipset v6.20 + COMPREPLY=( $(compgen -W \ + 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) ) + [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace + __ltrim_colon_completions "$cur" + else # only tcp services prior to ipset v6.20 + COMPREPLY=( $(compgen -W '$(_ipset_get_services -p tcp)' -- "$cur" ) ) + fi + _ipset_complete_elements "$cur" --no-range + __ltrim_colon_completions "$cur" fi - ;; - esac + else + _ipset_complete_elements "$cur" --no-range + __ltrim_colon_completions "$cur" + fi + fi +elif ((cword == action_index+3)) && [[ $cur != -* ]]; then + if [[ $str_action = add ]]; then + str_type=$(_ipset_get_set_type "$str_setname") + if _ipset_set_has_option timeout "$str_setname"; then + str_timeout=timeout + else + str_timeout="" + fi + if ! _ipset_set_has_option counters "$str_setname"; then + str_bp_counters="" + fi + if ! _ipset_set_has_option comment "$str_setname"; then + str_comment="" + fi + if ! _ipset_set_has_option skbinfo "$str_setname"; then + str_skbflags="" + fi + if [[ $str_type = hash:*net* ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \ + -- "$cur" ) ) + elif [[ $str_type = @(hash:*!(net)*|bitmap:*) ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_skbflags $str_comment)' \ + -- "$cur" ) ) + elif [[ $str_type = list:* ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_skbflags $str_comment)' \ + -- "$cur" ) ) + fi + elif [[ $str_action = @(create|n) ]]; then + if [[ $prev = hash:ip,mark ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_markmask $str_comment $str_forceadd)' \ + -- "$cur" ) ) + elif [[ $prev = hash:* ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_comment $str_forceadd)' \ + -- "$cur" ) ) + elif [[ $prev = bitmap:ip ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_skbinfo $str_comment)' \ + -- "$cur" ) ) + elif [[ $prev = bitmap:!(ip)?* ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_skbinfo $str_comment)' \ + -- "$cur" ) ) + elif [[ $prev = list:* ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_skbinfo $str_comment)' \ + -- "$cur" ) ) + fi + elif [[ $str_action = @(del|test) ]]; then + str_type=$(_ipset_get_set_type "$str_setname") + if [[ $str_type = list:* ]]; then + COMPREPLY=( $( compgen -W '$str_order' -- "$cur" ) ) + elif [[ $str_action = test && $str_type = hash:*net* ]]; then + COMPREPLY=( $( compgen -W 'nomatch' -- "$cur" ) ) + fi + fi elif ((cword == action_index+3)) && [[ $cur = -* ]]; then _ipset_get_options elif ((cword >= action_index+4)) && [[ $cur = -* ]]; then # add all following hyphen options @@ -1561,207 +1533,180 @@ elif ((cword >= action_index+4)) && [[ $cur = -* ]]; then # add all following hy _ipset_get_options fi elif ((cword >= action_index+4)); then # add all following non-hyphen options - case "$str_action" in - add) - str_type=$(_ipset_get_set_type "$str_setname") - if _ipset_set_has_option timeout "$str_setname"; then - str_timeout=timeout - else - str_timeout="" - fi - if ! _ipset_set_has_option counters "$str_setname"; then - str_bp_counters="" + if [[ $str_action = add ]]; then + str_type=$(_ipset_get_set_type "$str_setname") + if _ipset_set_has_option timeout "$str_setname"; then + str_timeout=timeout + else + str_timeout="" + fi + if ! _ipset_set_has_option counters "$str_setname"; then + str_bp_counters="" + fi + if ! _ipset_set_has_option comment "$str_setname"; then + str_comment="" + fi + if ! _ipset_set_has_option skbinfo "$str_setname"; then + str_skbflags="" + fi + # validate option argument values + if [[ $_IPSET_VALIDATE_INPUT ]]; then + for ((x=$action_index+3; x < ${#words[@]}; x++)); do + if [[ ${words[x]} = @(timeout|bytes|packets) ]]; then + [[ ${words[x+1]} = @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] || return 0 + elif [[ ${words[x]} = skbmark ]]; then + if [[ ${words[x+1]} = 0[xX]+([[:xdigit:]])?(/0[xX]+([[:xdigit:]])) ]]; then + (( ${words[x+1]%/*} >= 0 && ${words[x+1]%/*} <= 0xFFFFFFFF )) || return 0 + (( ${words[x+1]#*/} >= 0 && ${words[x+1]#*/} <= 0xFFFFFFFF )) || return 0 + else + return 0 + fi + elif [[ ${words[x]} = skbprio ]]; then + [[ ${words[x+1]} = +([[:xdigit:]]):?(+([[:xdigit:]])) ]] || return 0 + elif [[ ${words[x]} = skbqueue ]]; then + [[ ${words[x+1]} = +([[:digit:]]) ]] || return 0 + fi + done + fi + if [[ $str_type = hash:*net* ]]; then + if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \ + -- "$cur" ) ) fi - if ! _ipset_set_has_option comment "$str_setname"; then - str_comment="" + elif [[ $str_type = @(hash:*!(net)*|bitmap:*) ]]; then + if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags)' \ + -- "$cur" ) ) fi - if ! _ipset_set_has_option skbinfo "$str_setname"; then - str_skbflags="" + elif [[ $str_type = list:* ]]; then + if [[ $prev = @(before|after) ]] && ((cword-1 == order_index)); then + _ipset_complete_elements "$cur" + __ltrim_colon_completions "$cur" + elif [[ $prev != @(timeout|bytes|packets|skbmark|skbprio|skbqueue) ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_comment $str_skbflags)' \ + -- "$cur" ) ) fi - # validate option argument values - if [[ ${_IPSET_VALIDATE_INPUT-1} ]]; then - for ((x=$action_index+3; x < ${#words[@]}; x++)); do - if [[ ${words[x]} = @(timeout|bytes|packets) ]]; then - [[ ${words[x+1]} = @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] || return 0 - elif [[ ${words[x]} = skbmark ]]; then - if [[ ${words[x+1]} = 0[xX]+([[:xdigit:]])?(/0[xX]+([[:xdigit:]])) ]]; then - (( ${words[x+1]%/*} >= 0 && ${words[x+1]%/*} <= 0xFFFFFFFF )) || return 0 - (( ${words[x+1]#*/} >= 0 && ${words[x+1]#*/} <= 0xFFFFFFFF )) || return 0 + fi + elif [[ $str_action = @(create|n) ]]; then + # validate option argument values + if [[ $_IPSET_VALIDATE_INPUT ]]; then + for ((x=$action_index+3; x < ${#words[@]}; x++)); do + if [[ ${words[x+1]} && ${words[x+1]} != $cur ]]; then + if [[ ${words[x]} = @(hashsize|timeout|size|maxelem|markmask) ]]; then + [[ ${words[x+1]} != @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] && return 0 + elif [[ ${words[x]} = family ]]; then + [[ ${words[x+1]} != inet?(6) ]] && return 0 + elif [[ ${words[x]} = range ]]; then + if [[ $str_type = bitmap:port ]]; then + [[ ${words[x+1]} != *-* ]] && return 0 else - return 0 + [[ ${words[x+1]} != @(*-*|*/+([[:digit:]])) ]] && return 0 fi - elif [[ ${words[x]} = skbprio ]]; then - [[ ${words[x+1]} = +([[:xdigit:]]):?(+([[:xdigit:]])) ]] || return 0 - elif [[ ${words[x]} = skbqueue ]]; then - [[ ${words[x+1]} = +([[:digit:]]) ]] || return 0 fi - done + fi + done + fi + if [[ ${words[action_index+2]} = hash:ip,mark ]]; then # must be the set type + if [[ $prev = family ]]; then + COMPREPLY=( $( compgen -W '$(_ipset_dedupe_cmd_opts inet inet6)' \ + -- "$cur" ) ) + elif [[ $prev != @(hashsize|timeout|maxelem|markmask) ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_markmask $str_comment $str_forceadd $str_skbinfo)' \ + -- "$cur" ) ) fi - case "$str_type" in - hash:*net*) - if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \ - -- "$cur" ) ) - fi - ;; - hash:*!(net)*|bitmap:*) - if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags)' \ - -- "$cur" ) ) - fi - ;; - list:*) - if [[ $prev = @(before|after) ]] && ((cword-1 == order_index)); then - _ipset_complete_elements "$cur" - _ipset_colon_ltrim "$cur" - elif [[ $prev != @(timeout|bytes|packets|skbmark|skbprio|skbqueue) ]]; then - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_comment $str_skbflags)' \ - -- "$cur" ) ) - fi - ;; - esac - ;; - create|n) - # validate option argument values - if [[ ${_IPSET_VALIDATE_INPUT-1} ]]; then - for ((x=$action_index+3; x < ${#words[@]}; x++)); do - if [[ ${words[x+1]} && ${words[x+1]} != $cur ]]; then - case "${words[x]}" in - @(hashsize|timeout|size|maxelem|markmask)) - [[ ${words[x+1]} != @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] && return 0 - ;; - family) - [[ ${words[x+1]} != inet?(6) ]] && return 0 - ;; - range) - case "$str_type" in - bitmap:port) - [[ ${words[x+1]} != *-* ]] && return 0 - ;; - *) - [[ ${words[x+1]} != @(*-*|*/+([[:digit:]])) ]] && return 0 - ;; - esac - ;; - esac - fi - done + elif [[ ${words[action_index+2]} = hash:* ]]; then + if [[ $prev = family ]]; then + COMPREPLY=( $( compgen -W '$(_ipset_dedupe_cmd_opts inet inet6)' \ + -- "$cur" ) ) + elif [[ $prev != @(hashsize|timeout|maxelem) ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_comment $str_forceadd $str_skbinfo)' \ + -- "$cur" ) ) fi - case "${words[action_index+2]}" in # must be the set type - hash:ip,mark) - if [[ $prev = family ]]; then - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts inet inet6)' \ - -- "$cur" ) ) - elif [[ $prev != @(hashsize|timeout|maxelem|markmask) ]]; then - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_markmask $str_comment $str_forceadd $str_skbinfo)' \ - -- "$cur" ) ) - fi - ;; - hash:*) - if [[ $prev = family ]]; then - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts inet inet6)' \ - -- "$cur" ) ) - elif [[ $prev != @(hashsize|timeout|maxelem) ]]; then - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_comment $str_forceadd $str_skbinfo)' \ - -- "$cur" ) ) - fi - ;; - bitmap:ip) - if [[ $prev != @(range|netmask|timeout) ]]; then - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_comment $str_skbinfo)' \ - -- "$cur" ) ) - fi - ;; - bitmap:!(ip)?*) - if [[ $prev != @(range|timeout) ]]; then - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_comment $str_skbinfo)' \ - -- "$cur" ) ) - fi - ;; - list:*) - if [[ $prev != @(size|timeout) ]]; then - COMPREPLY=( $( compgen -W \ - '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_comment $str_skbinfo)' \ - -- "$cur" ) ) - fi - ;; - esac - if [[ ${words[action_index+2]} = bitmap:port && $prev = range ]]; then - # complete port ranges - _ipset_complete_portrange "$cur" - elif [[ ${words[action_index+2]} = bitmap:* && $prev = range ]]; then - str_prefix="" - if [[ $cur = @(""|+([[:word:]])) ]]; then # empty or [:word:] - : - elif [[ $cur = [\[]*-*[\]] ]]; then # host with hyphen - : - elif [[ $cur = [[]*([!]]) ]]; then # incomplete host with dash - : - elif [[ $cur = *-[[]+([!]]) ]]; then # incomplete range - host with dash - str_prefix="${cur%\-[*}-" - elif [[ $cur = \[*\]-* ]]; then # first part of hostname range - str_prefix="${cur%\]-*}]-" - elif [[ $cur != *-* ]]; then # no hypen - : - else # ip-range - str_prefix="${cur%-*}-" + elif [[ ${words[action_index+2]} = bitmap:ip ]]; then + if [[ $prev != @(range|netmask|timeout) ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_comment $str_skbinfo)' \ + -- "$cur" ) ) + fi + elif [[ ${words[action_index+2]} = bitmap:!(ip)?* ]]; then + if [[ $prev != @(range|timeout) ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_comment $str_skbinfo)' \ + -- "$cur" ) ) + fi + elif [[ ${words[action_index+2]} = list:* ]]; then + if [[ $prev != @(size|timeout) ]]; then + COMPREPLY=( $( compgen -W \ + '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_comment $str_skbinfo)' \ + -- "$cur" ) ) + fi + fi + if [[ ${words[action_index+2]} = bitmap:port && $prev = range ]]; then + # complete port ranges + _ipset_complete_portrange "$cur" + elif [[ ${words[action_index+2]} = bitmap:* && $prev = range ]]; then + str_prefix="" + if [[ $cur = @(""|+([[:word:]])) ]]; then # empty or [:word:] + : + elif [[ $cur = [\[]*-*[\]] ]]; then # host with hyphen + : + elif [[ $cur = [[]*([!]]) ]]; then # incomplete host with dash + : + elif [[ $cur = *-[[]+([!]]) ]]; then # incomplete range - host with dash + str_prefix="${cur%\-[*}-" + elif [[ $cur = \[*\]-* ]]; then # first part of hostname range + str_prefix="${cur%\]-*}]-" + elif [[ $cur != *-* ]]; then # no hypen + : + else # ip-range + str_prefix="${cur%-*}-" + fi + _ipset_complete_host_spec "$cur" --v4 + if ((${#COMPREPLY[@]} == 1)); then + if [[ -z $str_prefix && ${COMPREPLY[*]} != */* ]]; then + compopt -o nospace + COMPREPLY=( $( compgen -W '${COMPREPLY[*]}/ ${COMPREPLY[*]}-' -- "$cur" ) ) fi - _ipset_complete_host_spec "$cur" --v4 - if ((${#COMPREPLY[@]} == 1)); then - if [[ -z $str_prefix && ${COMPREPLY[*]} != */* ]]; then - compopt -o nospace - COMPREPLY=( $( compgen -W '${COMPREPLY[*]}/ ${COMPREPLY[*]}-' -- "$cur" ) ) - fi + fi + fi + elif [[ $str_action = @(del|test) ]]; then + str_type=$(_ipset_get_set_type "$str_setname") + if [[ $str_type = list:* ]]; then + arr_tmp=() + _ipset_get_members --names-only "$str_setname" + if [[ $prev = @(before|after) ]] && ((cword-1 == order_index)) + then + if [[ $prev = before ]]; then + for x in ${!arr_members[@]}; do + if [[ ${arr_members[x]} = ${words[action_index+2]} ]] + then + if [[ ${arr_members[x+1]} ]]; then + arr_tmp+=(${arr_members[x+1]}) + break + fi + fi + done + elif [[ $prev = after ]]; then + for x in ${!arr_members[@]}; do + if [[ ${arr_members[x]} = ${words[action_index+2]} ]] + then + if ((x>0)) && [[ ${arr_members[x-1]} ]]; then + arr_tmp+=(${arr_members[x-1]}) + break + fi + fi + done fi + COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) ) + __ltrim_colon_completions "$cur" fi - ;; - del|test) - str_type=$(_ipset_get_set_type "$str_setname") - case "$str_type" in - list:*) arr_tmp=() - _ipset_get_members --names-only "$str_setname" - if [[ $prev = @(before|after) ]] && ((cword-1 == order_index)) - then - case "$prev" in - before) - for x in ${!arr_members[@]}; do - if [[ ${arr_members[x]} = ${words[action_index+2]} ]] - then - if [[ ${arr_members[x+1]} ]]; then - arr_tmp+=(${arr_members[x+1]}) - break - fi - fi - done - ;; - after) - for x in ${!arr_members[@]}; do - if [[ ${arr_members[x]} = ${words[action_index+2]} ]] - then - if ((x>0)) && [[ ${arr_members[x-1]} ]]; then - arr_tmp+=(${arr_members[x-1]}) - break - fi - fi - done - ;; - esac - COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) ) - _ipset_colon_ltrim "$cur" - fi - ;; - esac - ;; - esac + fi + fi fi else # we don't have the main action yet if [[ $prev = - ]] && ((cword == 2)); then @@ -1771,7 +1716,9 @@ if [[ $cur = -* ]]; then # any option is requested _ipset_get_options else # we don't have the action yet, check options to display appropiate actions - if ((save_format || names_only || headers_only)); then + if ((save_format && !headers_only && !names_only)); then + COMPREPLY=( $( compgen -W 'list save' -- "$cur" ) ) + elif ((save_format || names_only || headers_only)); then COMPREPLY=( $( compgen -W 'list' -- "$cur" ) ) elif ((res_sort)); then COMPREPLY=( $( compgen -W 'list save' -- "$cur" ) ) @@ -1782,8 +1729,8 @@ else elif ((use_file)); then COMPREPLY=( $( compgen -W 'list save restore' -- "$cur" ) ) else - COMPREPLY=( $( compgen -W 'create n add del test destroy x list save \ - restore flush rename e swap w help version' -- "$cur" ) ) + COMPREPLY=( $( compgen -W 'create n add del test destroy x list save \ + restore flush rename e swap w help version' -- "$cur" ) ) fi fi fi diff --git a/utils/ipset_list/ipset_list b/utils/ipset_list/ipset_list index ad15f18..306ddac 100755..100644 --- a/utils/ipset_list/ipset_list +++ b/utils/ipset_list/ipset_list @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # ----------------------------------------------------------------- # ipset set listing wrapper script @@ -7,7 +7,7 @@ # https://sourceforge.net/projects/ipset-list/ # ----------------------------------------------------------------- -# Copyright (C) 2013-2014 AllKind (AllKind@fastest.cc) +# Copyright (C) 2013-2019 Mart Frauenlob aka AllKind (AllKind@fastest.cc) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -23,1050 +23,353 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # ----------------------------------------------------------------- -# Compatible with ipset version 6+ -# Tested with ipset versions: -# 6.16.1, 6.20.1, 6.22 -# ----------------------------------------------------------------- - -# ----------------------------------------------------------------- -# Features (in addition to the native ipset options): -# - Calculate sum of set members (and match on that count). -# - List only members of a specified set. -# - Choose a delimiter character for separating members. -# - Show only sets containing a specific (glob matching) header. -# - Arithmetic comparison on headers with an integer value. -# - Arithmetic comparison on flags of the headers 'Header' field. -# - Arithmetic comparison on member options with an integer value. -# - Match members using a globbing or regex pattern. -# - Suppress listing of (glob matching) sets. -# - Suppress listing of (glob matching) headers. -# - Suppress listing of members matching a glob or regex pattern. -# - Calculate the total size in memory of all matching sets. -# - Calculate the amount of matching, excluded and traversed sets. -# - Colorize the output. -# - Operate on a single, selected, or all sets. -# - Programmable completion is included to make usage easier and faster. -# ----------------------------------------------------------------- - -# ----------------------------------------------------------------- -# Examples: -# $0 - no args, just list set names -# $0 -c - show all set names and their member sum -# $0 -t - show all sets, but headers only -# $0 -c -t setA - show headers and member sum of setA -# $0 -i setA - show only members entries of setA -# $0 -c -m setA setB - show members and sum of setA & setB -# $0 -a -c -d : - show all sets members, sum and use `:' as entry delimiter -# $0 -a -c setA - show all info of setA and its members sum -# $0 -c -m -d $'\n' setA - show members and sum of setA, delim with newline -# $0 -m -r -s setA - show members of setA resolved and sorted -# $0 -Ts - show all set names and total count of sets. -# $0 -Tm - calculate total size in memory of all sets. -# $0 -Mc 0 - show sets with zero members -# $0 -Fi References:0 - show all sets with 0 references -# $0 -Hr 0 - shortcut for `-Fi References:0' -# $0 -Xs setA -Xs setB - show all set names, but exclude setA and setB. -# $0 -Xs "set[AB]" - show all set names, but exclude setA and setB. -# $0 -Cs -Ht "hash:*" - find sets of any hash type, count their amount. -# $0 -Ht "!(hash:ip)" - show sets which are not of type hash:ip -# $0 -Ht "!(bitmap:*)" - show sets wich are not of any bitmap type -# $0 -i -Fr "^210\..*" setA - show only members of setA matching the regex "^210\..*" -# $0 -Mc \>=100 -Mc \<=150 - show sets with a member count greater or equal to 100 -#+ and not greater than 150. -# $0 -a -c -Fh "Type:hash:ip" -Fr "^210\..*" -#+ - show all information of sets with type hash:ip, -#+ matching the regex "^210\..*", show match and members sum. # -# $0 -m -Fg "!(210.*)" setA -#+ show members of setA excluding the elements matching the negated glob. +# This is the bash programmable completion for ipset_list # -# $0 -Hr \>=1 -Hv 0 -Hs \>10000 - find sets with at least one reference, -#+ revision of 0 and size in memory greater than 10000 -# -# $0 -Fh Type:hash:ip -Fh "Header:family inet *" -#+ - show all set names, which are of type hash:ip and header of ipv4. -# -# $0 -t -Xh "Revision:*" -Xh "References:*" -#+ - show all sets headers, but exclude Revision and References entries. -# -# $0 -t -Ht "!(@(bit|port)map):*" -Xh "!(Type):*" - show all sets that are -#+ neither of type bitmap or portmap, suppress all but the type header. -# -# $0 -c -m -Xg "210.*" setA - show members of setA, but suppress listing of entries -#+ matching the glob pattern "210.*", show count of excluded and total members. +# ----------------------------------------------------------------- +# Requirements: # -# $0 -t -Tm -Xh "@(Type|Re*|Header):*" -#+ show all sets headers, but suppress all but name and memsize entry, -#+ calculate the total memory size of all sets. +# The bash completion package version 2.0 or greater is recommended. +# https://github.com/scop/bash-completion # -# $0 -t -Tm -Xh "!(Size*|Type):*" -Ts -Co -# + List all sets headers, but suppress all but name, type and memsize entry, -# + count amount of sets, calculate total memory usage, colorize the output. +# If the package is not available, things might not be so reliable. +# Also the colon (if there) is removed from COMP_WORDBREAKS. +# This alteration is globally. Which might affect other completions +# if they don't take care of it themselves. # -# $0 -c -t -Cs -Ts -Xh "@(Size*|Re*|Header):*" -Ht "!(bitmap:*)" -#+ find all sets not of any bitmap type, count their members sum, -#+ display only the 'Type' header, -#+ count amount of matching and traversed sets. +# ----------------------------------------------------------------- +# Installation (quote from bash-completion README): # -# $0 -a -Xh "@(@(H|R|M)e*):*" - show all info of all sets, -#+ but suppress Header, References, Revision and Member header entries. -#+ (headers existing as per ipset 6.x -> tested version). +# Install it in one of the directories pointed to by +# bash-completion's pkgconfig file variables. There are two +# alternatives: the recommended one is 'completionsdir' (get it with +# "pkg-config --variable=completionsdir bash-completion") from which +# completions are loaded on demand based on invoked commands' names, +# so be sure to name your completion file accordingly, and to include +# for example symbolic links in case the file provides completions +# for more than one command. The other one which is present for +# backwards compatibility reasons is 'compatdir' (get it with +# "pkg-config --variable=compatdir bash-completion") from which files +# are loaded when bash_completion is loaded. # -# $0 -Co -c -Ts -Tm - show all set names, count their members, -# + count total amount of sets, show total memory usage of all sets, -# + colorize the output +# For packages using GNU autotools the installation can be handled +# for example like this in configure.ac: # -# $0 -m -r -To 0 - show members of all sets, try to resolve hosts, -# set the timeout to 0 (effectivly disabling it). +# PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], , +# bashcompdir="${sysconfdir}/bash_completion.d") +# AC_SUBST(bashcompdir) # -# $0 -m -Xo setA - show members of setA, -# + but suppress displaying of the elements options. +# ...accompanied by this in Makefile.am: # -# $0 -m -Oi packets:0 -# + show members of all sets which have a packet count of 0. +# bashcompdir = @bashcompdir@ +# dist_bashcomp_DATA = # completion files go here # -# $0 -m -Oi "packets:>100" -Oi "bytes:>1024" -# + show members of all sets which have a -# + packet count greater than 100 and a byte count greater than 1024. +# For cmake we ship the bash-completion-config.cmake and +# bash-completion-config-version.cmake files. Example usage: # -# $0 -m -Oi "skbmark:>0x123/0XFF" -Oi skbprio:\>=2:<=3 -Oi skbqueue:\!1 -# + show members of all sets which have the following member options set: -# + skbmark greater than 0x123/0xFF, skbprio major greater or equal to 2 -# + and minor lower or equal to 3, skbqueue not of value 1. +# find_package(bash-completion) +# if(BASH_COMPLETION_FOUND) +# message(STATUS +# "Using bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}") +# else() +# set (BASH_COMPLETION_COMPLETIONSDIR "/etc/bash_completion.d") +# message (STATUS +# "Using fallback bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}") +# endif() # -# $0 -n -Ca "foo*" -# + show only set names matching the glob "foo*" and enable all counters. +# install(FILES your-completion-file DESTINATION +# ${BASH_COMPLETION_COMPLETIONSDIR}) # -# $0 -Hi "markmask:>=0x0000beef" -Hi timeout:\!10000` -# + show only sets with the header 'Header' fields containing a markmask -# + greater or equal to 0x0000beef and a timeout which is not 10000. +# For backwards compatibility it is still possible to put it into +# ~/.bash_completion or /etc/bash_completion.d/. # ----------------------------------------------------------------- -# ----------------------------------------------------------------- -# Modify here -# ----------------------------------------------------------------- - -# modify your PATH variable -# by default the path is only set if the PATH variable is not already set in the environment -# PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin -: ${PATH:=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin} - -# path to ipset. -# defaults to `/sbin/ipset' if unset. -#ipset="/sbin/ipset" -# find in path if not declared in parent environment -: ${ipset:=$(command -v ipset)} - -# default delimiter character for set members (elements). -# defaults to whitespace if unset. -# use delim=$'\n' to use the ipset default newline as delimiter. -delim=" " - -# default read timeout (for reading sets - esp. with the -r switch). -# the command line option -To overrides this. -TMOUT=30 - -# colorize the output (bool 0/1). -colorize=0 - -# path to cl (to colorize the output). -# http://sourceforge.net/projects/colorize-shell/ or -# https://github.com/AllKind/cl -# defaults to `/usr/local/bin/cl' if unset. -cl="/usr/local/bin/cl" - -# define colors -# run `cl --list' to retrieve the valid color names -# -# default foreground color -# defaults to: white -col_fg="white" - -# default background color -# defaults to: black -col_bg="black" +# Name may be modified +ipset_list=ipset_list -# color for headers -# defaults to: cyan -col_headers="cyan" - -# color for members -# defaults to: yellow -col_members="yellow" - -# color for matches -# defaults to: red -col_match="red" - -# color for displaying of memsize -# defaults to: green -col_memsize="green" - -# color for counting of matched sets -# defaults to: magenta -col_set_count="magenta" - -# color for counting of traversed sets -# defaults to: blue -col_set_total="blue" - -# general higlightning color -# defaults to: white -col_highlight="white" +# ----------------------------------------------------------------- # ----------------------------------------------------------------- # DO NOT MODIFY ANYTHING BEYOND THIS LINE! # ----------------------------------------------------------------- - -# bash check -if [ -z "$BASH" ]; then - printf "\`BASH' variable is not available. Not running bash?\n" >&2 - exit 1 -fi - -# shell settings shopt -s extglob -set -f -set +o posix -set +u - -# variables -export LC_ALL=C -readonly version=3.2.1 -readonly me="${0//*\//}" -readonly oIFS="$IFS" -declare ips_version="" str_search="" str_xclude="" opt str_name str_val str_op -declare -i show_all=show_count=show_members=headers_only=names_only=isolate=calc_mem=count_sets=sets_total=0 -declare -i match_on_header=glob_search=regex_search=member_count=match_count=do_count=opt_int_search=0 -declare -i exclude_header=glob_xclude_element=glob_xclude_element=exclude_set=xclude_member_opts=0 -declare -i in_header=found_set=found_member_opt=found_hxclude=found_sxclude=xclude_count=mem_total=mem_tmp=set_count=sets_sum=i=x=y=idx=0 -declare -a arr_sets=() arr_par=() arr_hcache=() arr_mcache=() arr_hsearch=() arr_tmp=() -declare -a arr_hsearch_int=() arr_hsearch_xint=() arr_hxclude=() arr_sxclude=() arr_match_on_msum=() arr_opt_int_search=() # ----------------------------------------------------------------- -# functions +# Functions # ----------------------------------------------------------------- -ex_miss_optarg() { -printf "%s of option \`%s' is missing\n" "$2" "$1" >&2 -exit 2 -} - -ex_invalid_usage() { -printf "%s\n" "$*" >&2 -exit 2 -} - -is_int() { -[[ $1 = +([[:digit:]]) ]] -} - -is_digit_or_xigit() { -[[ $1 = @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] -} - -is_compare_str() { - [[ $1 = ?(\!|<|>|<=|>=)@(+([[:digit:]])|0[x|X]+([[:xdigit:]])) ]] -} - -is_compare_str_complex() { - [[ $1 = ?(\!|<|>|<=|>=)@(+([[:digit:]])|0@(x|X)+([[:xdigit:]])?(/0@(x|X)+([[:xdigit:]]))|+([[:xdigit:]]):?(\!|<|>|<=|>=)+([[:xdigit:]])) ]] -} - -add_search_to_member_cache() { -if ((show_members || show_all || isolate)); then - arr_mcache[i++]="$REPLY" -fi -} - -arith_elem_opt_search() { -local str_opt_val str_val2 str_op2 str_cg='?(\!|<|>|<=|>=)' str_xdig='0[xX]+([[:xdigit:]])' -found_member_opt=0 -for y in ${!arr_opt_int_search[@]}; do - str_val="${arr_opt_int_search[y]#*:}" - if [[ $str_val = ${str_cg}@(+([[:digit:]])|$str_xdig) ]]; then # i.e. timeout or skbqueue - str_op="${str_val//[![:punct:]]}" - str_val="${str_val//[=\!\>\<]}" - elif [[ $str_val = ${str_cg}${str_xdig}/$str_xdig ]]; then # i.e. skbmark - str_op="${str_val//[![:punct:]]}" - str_op="${str_op//\/}" - str_val="${str_val//[=\!\>\<]}" - elif [[ $str_val = ${str_cg}+([[:xdigit:]]):${str_cg}+([[:xdigit:]]) ]]; then # i.e. skbprio - str_op="${str_val%:*}" - str_op="${str_op%%+([[:xdigit:]])}" - str_op2="${str_val#*:}" - str_op2="${str_op2%%+([[:xdigit:]])}" - str_val="${str_val##+([[:punct:]])}" - str_val2="${str_val#*:}" - str_val2="${str_val2//[[:punct:]]}" - fi - # compare operator defaults to `==' - # if it's a '!' set it to '!=' - [[ ${str_op:===} = \! ]] && str_op='!=' - [[ ${str_op2:===} = \! ]] && str_op2='!=' - set -- $REPLY - shift - while (($# > 1)); do # cycle through options - if [[ $1 = ${arr_opt_int_search[y]%%:*} ]]; then str_opt_val="$2" - if [[ $str_val = @(+([[:digit:]])|$str_xdig) && $str_opt_val = @(+([[:digit:]])|$str_xdig) ]]; then # i.e. timeout or skbqueue - if (( $str_opt_val $str_op $str_val )); then - let found_member_opt+=1 - fi - shift - elif [[ $str_val = $str_xdig && $str_opt_val = ${str_xdig}/$str_xdig ]]; then # i.e. skbmark - if (( $str_opt_val $str_op $(( ${str_val%/*} & ${str_val#*/} )) )); then # logicaly AND mark/mask - let found_member_opt+=1 - fi - shift - elif [[ $str_val = ${str_xdig}/$str_xdig && $str_opt_val = ${str_xdig}/$str_xdig ]]; then # i.e. skbmark - if (( $(( ${str_opt_val%/*} & ${str_opt_val#*/} )) $str_op $(( ${str_val%/*} & ${str_val#*/} )) )); then # logicaly AND mark/mask - let found_member_opt+=1 - fi - shift - elif [[ $str_val = +([[:xdigit:]]):${str_cg}+([[:xdigit:]]) && $str_opt_val = +([[:xdigit:]]):+([[:xdigit:]]) ]]; then # i.e. skbprio - if (( ${str_opt_val%:*} $str_op ${str_val%:*} && ${str_opt_val#*:} $str_op2 $str_val2 )); then - let found_member_opt+=1 - fi - shift - fi - fi - shift - done +_ipset_list_show_sets() { +COMPREPLY=( $( compgen -W '${sets[@]}' -- "$cur" ) ) +# dedupe sets listing +for ((i=set_index; i < ${#words[@]}-1; i++)); do + _ipset_list_remove_reply_entry "${words[i]}" done -if ((opt_int_search == found_member_opt)); then - let match_count+=1 - add_search_to_member_cache -fi } -xclude_elem_search() { -if ((glob_xclude_element)); then # exclude matching members - if [[ $REPLY = $str_xclude ]]; then - let xclude_count+=1 - return 0 - fi -elif ((regex_xclude_element)); then # exclude matching members - if [[ $REPLY =~ $str_xclude ]]; then - let xclude_count+=1 - return 0 - else - if (($? == 2)); then - printf "Invalid regex pattern \`%s'.\n" "$str_xclude" >&2 - exit 1 - fi - fi -fi -return 1 +_ipset_list_remove_reply_entry() { +local -i x +while (($#)); do + for x in ${!COMPREPLY[@]}; do + if [[ ${COMPREPLY[x]} = $1 ]]; then + if [[ $_DEBUG_NF_COMPLETION ]]; then + printf "removing dupe entry COMPREPLY[$x]: %s\n" \ + "${COMPREPLY[x]}" + fi + unset COMPREPLY[x] + break + fi + done + shift +done } # ----------------------------------------------------------------- -# main +# Main # ----------------------------------------------------------------- -# validate value of colorize -if [[ ${colorize:=0} != [01] ]]; then - ex_invalid_usage "value of variable \`colorize' \`$colorize' is not 0 or 1." -fi +_ipset_list_complete() { +local -i i=x=got_bashcompl=iactive=0 +local -i show_all=isolate=show_members=resolve=headers_only=names_only=0 +local -i header_operation=set_index=0 +local cur prev cword words str_tmp +local sets=( $(command "${ipset_list:-ipset_list}" -n 2>/dev/null) ) 2>/dev/null +local opts=(- -- -? -a -c -d -h -i -m -n -r -s -t -v) +local Copts=(-Ca -Cs -Co) +local Fopts=(-Fh -Fi -Fg -Fr -Oi) +local Gopts=(-Gp -Gs -Gx) +local Iopts=(-- -d -r -s -G ${Gopts[@]} -To) +local Hopts=(-Hi -Hr -Hs -Ht -Hv) +local Topts=(-T -Tm -To -Ts) +local Xopts=(-Xh -Xg -Xr -Xs -Xo) +local arr_types=() arr_tmp=() -# parse cmd-line options -while (($#)); do - case "$1" in - -\?|-h) printf "\n\tipset set listing wrapper script\n\n" - printf '%s [option [opt-arg]] [set-name-glob] [...]\n\n' "$me" - printf '%s %s\n' "$me" "{-?|-h} | -v" - printf '%s %s\n\t%s\n\t%s\n' "$me"\ - "[-i|-r|-s|-Co|-Xo] [-d char] [-To value]"\ - "[-Fg|-Fr pattern] [-Xg|-Xr pattern]"\ - "[-Oi option-glob:[!|<|>|<=|>=]value] [...] -- set-name" - printf '%s %s\n\t%s\n\t%s\n\t%s\n' "$me"\ - "[-n|-c|-Ca|-Co|-Cs|-Tm|-Ts|-Xs] [-To value]"\ - "[-Fh header-glob:value-glob] [...] [-Fg|-Fr pattern]"\ - "[-Hi glob:[!|<|>|<=|>=]value] [...]"\ - "[-Oi option-glob:[!|<|>|<=|>=]value] [...] -- [set-name-glob] [...]" - printf '%s %s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n' "$me"\ - "[-t|-c|-Ca|-Co|-Cs|-Tm|-Ts]"\ - "[-Fh header-glob:value-glob] [...]"\ - "[-Fi header-glob:[!|<|>|<=|>=]value] [...]"\ - "[-Fg|-Fr pattern] [-Ht type-glob]"\ - "[-Hi glob:[!|<|>|<=|>=]value] [...]"\ - "[-Hr|-Hs|-Hv [!|<|>|<=|>=]value]"\ - "[-Mc [!|<|>|<=|>=]value] [...] [-To value]"\ - "[-Oi option-glob:[!|<|>|<=|>=]value] [...]"\ - "[-Xh header-glob:value-glob] [...]"\ - "[-Xs set-name-glob] [...] -- [set-name-glob] [...]" - printf '%s %s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n' "$me"\ - "[-a|-c|-m|-r|-s|-Ca|-Co|-Cs|-Tm|-Ts|-Xo] [-d char]"\ - "[-Fh header-glob:value-glob] [...]"\ - "[-Fi header-glob:[!|<|>|<=|>=]value] [...]"\ - "[-Fg|-Fr pattern] [-Ht type-glob]"\ - "[-Hi glob:[!|<|>|<=|>=]value] [...]"\ - "[-Hr|-Hs|-Hv [!|<|>|<=|>=]value]"\ - "[-Mc [!|<|>|<=|>=]value] [...]"\ - "[-Oi option-glob:[!|<|>|<=|>=]value] [...]"\ - "[-To value] [-Xh header-glob:value-glob] [...]"\ - "[-Xg|-Xr pattern] [-Xs set-name-glob] [...] -- [set-name-glob] [...]" - printf 'options:\n' - printf '%-13s%s\n' '-a' 'show all information but with default delim (whitespace).'\ - '-c' 'calculate members and match sum.'\ - '-d delim' 'delimiter character for separating member entries.'\ - '-h|-?' 'show this help text.'\ - '-i' 'show only the members of a single set.'\ - '-m' 'show set members.'\ - '-n' "show set names only."\ - '-r' 'try to resolve ip addresses in the output (slow!).'\ - '-s' 'print elements sorted (if supported by the set type).'\ - '-t' 'show set headers only.'\ - '-v' 'version information.'\ - '-Ca' "shortcut for -c -Cs -Ts -Tm (enable all counters)."\ - '-Co' "colorize output (requires \`cl')."\ - '-Cs' 'count amount of matching sets.'\ - '-Fg pattern' 'match on members using a [ext]glob pattern.'\ - '-Fr pattern' 'match on members using a regex (=~ operator) pattern.' - printf '%s\n\t%s\n' '-Fh header-glob:value-glob [...]'\ - 'show sets containing one or more [ext]glob matching headers.' - printf '%s\n\t%s\n' '-Fi header-glob:[!|<|>|<=|>=]value [...]'\ - 'show sets matching one or more integer valued header entries.' - printf '%s\n\t%s\n' '-Hi header-glob:[!|<|>|<=|>=]value [...]'\ - "match one or more integer valued headers \`Header' entries." - printf '%-24s%s\n' '-Ht set-type-glob' 'match on set type.'\ - '-Hr [!|<|>|<=|>=]value' 'match on number of references (value=int).'\ - '-Hs [!|<|>|<=|>=]value' 'match on size in memory (value=int).'\ - '-Hv [!|<|>|<=|>=]value' 'match on revision number (value=int).' - printf '%-30s%s\n' '-Mc [!|<|>|<=|>=]value [...]' 'match on member count (value=int).' - printf '%s\n\t%s\n' '-Oi option-glob:[!|<|>|<=|>=]value [...]'\ - 'match member options (value=int | 0xhex[/0xhex] | hex:[!|<|>|<=|>=]hex).' - printf '%-13s%s\n' '-Tm' 'calculate total memory usage of all matching sets.'\ - '-To' 'set timeout value (int) for read (listing sets).'\ - '-Ts' 'count amount of traversed sets.'\ - '-Xo' 'suppress display of member options.' - printf '%s\n\t%s\n' '-Xh header-glob:value-glob [...]'\ - 'exclude one or more [ext]glob matching header entries.' - printf '%-13s%s\n' '-Xg pattern' 'exclude members matching a [ext]glob pattern.'\ - '-Xr pattern' 'exclude members matching a regex pattern.'\ - '-Xs pattern' 'exclude sets matching a [ext]glob pattern.' - printf '%-13s%s\n' '--' 'stop further option processing.' - exit 0 - ;; - -a) show_all=1 # like `ipset list', but with $delim as delim - ;; - -c) show_count=1 # show sum of member entries - ;; - -i) isolate=1 # show only members of a single set - ;; - -m) show_members=1 # show set members - ;; - -n) names_only=1 # only list set names - ;; - -t) headers_only=1 # show only set headers - ;; - -s|-r) arr_par[i++]="$1" # ipset sort & resolve options are passed on - ;; - -d) # delimiter char for separating member entries - [[ $2 ]] || ex_miss_optarg $1 "delim character" - if ((${#2} > 1)); then - ex_invalid_usage "only one character is allowed as delim" - fi - delim="$2" - shift - ;; - -o) if [[ $2 != plain ]]; then - ex_invalid_usage "only plain output is supported" - fi - ;; - -Ca) # shortcut for -c -Cs -Ts -Tm - show_count=1 count_sets=1 calc_mem=1 sets_total=1 - ;; - -Cs) count_sets=1 # calculate total count of matching sets - ;; - -Co) colorize=1 # colorize the output (requires cl) - ;; - -Fg) glob_search=1 # find entry with globbing pattern - [[ $2 ]] || ex_miss_optarg $1 "glob pattern" - str_search="$2" - shift - ;; - -Fr) regex_search=1 # find entry with regex pattern - [[ $2 ]] || ex_miss_optarg $1 "regex pattern" - str_search="$2" - shift - ;; - -Oi) let opt_int_search+=1 - [[ $2 ]] || ex_miss_optarg $1 "pattern" - if [[ $2 = *:* ]] && is_compare_str_complex "${2#*:}"; then - arr_opt_int_search[y++]="$2" - shift - else - ex_invalid_usage "invalid format of header descriptor. expecting: \`glob:[!|<|>|<=|>=]value'" - fi - ;; - -Fh) let match_on_header+=1 # show only sets, which contain a matching header entry - [[ $2 ]] || ex_miss_optarg $1 "header pattern" - if [[ $2 = *:* ]]; then - arr_hsearch[x++]="$2" - shift - else - ex_invalid_usage "invalid format of header descriptor. expecting: \`*:*'" - fi - ;; - -Fi) let match_on_header+=1 # show only sets, containing a matching (int compare) header entry - [[ $2 ]] || ex_miss_optarg $1 "header pattern" - if [[ $2 = *:* ]] && is_compare_str "${2#*:}"; then - arr_hsearch_int[idx++]="$2" - shift - else - ex_invalid_usage "invalid format of header descriptor. expecting: \`name:[!|<|>|<=|>=]value'" - fi - ;; - -Hi) let match_on_header+=1 # match on name + integer (digit & xdigit) inside of headers 'Header' flag - [[ $2 ]] || ex_miss_optarg $1 "header pattern" - if [[ $2 = *:?(\!|<|>|<=|>=)@(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]]; then - arr_hsearch_xint[${#arr_hsearch_xint[@]}]="$2" - shift - else - ex_invalid_usage "invalid format of headers \'Header' flag descriptor. expecting: \`name:[!|<|>|<=|>=]value'" - fi - ;; - -Hr) let match_on_header+=1 # shortcut for -Fi References:... - [[ $2 ]] || ex_miss_optarg $1 "header pattern" - if is_compare_str "$2"; then - arr_hsearch_int[idx++]="References:$2" - shift - else - ex_invalid_usage "invalid format of references header descriptor. expecting: \`[!|<|>|<=|>=]value'" - fi - ;; - -Hs) let match_on_header+=1 # shortcut for -Fi "Size in Memory:..." - [[ $2 ]] || ex_miss_optarg $1 "header pattern" - if is_compare_str "$2"; then - arr_hsearch_int[idx++]="Size in memory:$2" - shift - else - ex_invalid_usage "invalid format of memsize header descriptor. expecting: \`[!|<|>|<=|>=]value'" - fi - ;; - -Ht) let match_on_header+=1 # shortcut for -Fh Type:x:y - [[ $2 ]] || ex_miss_optarg $1 "header pattern" - if [[ $2 = *:* ]]; then - arr_hsearch[x++]="Type:$2" - shift - else - ex_invalid_usage "invalid format of set type descriptor. expecting: \`*:*'." - fi - ;; - -Hv) let match_on_header+=1 # shortcut for -Fi Revision:... - [[ $2 ]] || ex_miss_optarg $1 "header pattern" - if is_compare_str "$2"; then - arr_hsearch_int[idx++]="Revision:$2" - shift - else - ex_invalid_usage "invalid format of revision header descriptor. expecting: \`[!|<|>|<=|>=]value'" - fi - ;; - -Mc) do_count=1 # match on the count of members - [[ $2 ]] || ex_miss_optarg $1 "value pattern" - if is_compare_str "$2"; then - arr_match_on_msum[${#arr_match_on_msum[@]}]="$2" - shift - else - ex_invalid_usage "invalid format of match on member count value. expecting: \`[!|<|>|<=|>=]value'" - fi - ;; - -To) # set the timeout for read (limited to integer) - [[ $2 ]] || ex_miss_optarg $1 "value" - TMOUT=$2 - shift - ;; - -Tm) calc_mem=1 # caculate total memory usage of all matching sets - ;; - -Ts) sets_total=1 # caculate sum of all traversed sets - ;; - -Xh) exclude_header=1 # don't show certain headers - [[ $2 ]] || ex_miss_optarg $1 "header pattern" - if [[ $2 = *:* ]]; then - arr_hxclude[${#arr_hxclude[@]}]="$2" - shift - else - ex_invalid_usage "invalid format of header descriptor. expecting: \`*:*'" - fi - ;; - -Xg) glob_xclude_element=1 # suppress printing of matching members using a globbing pattern - [[ $2 ]] || ex_miss_optarg $1 "glob pattern" - str_xclude="$2" - shift - ;; - -Xr) regex_xclude_element=1 # suppress printing of matching members using a regex pattern - [[ $2 ]] || ex_miss_optarg $1 "regex pattern" - str_xclude="$2" - shift - ;; - -Xo) xclude_member_opts=1 # don't show elements options - ;; - -Xs) exclude_set=1 # don't show certain sets - [[ $2 ]] || ex_miss_optarg $1 "set name ([ext]glob pattern)" - arr_sxclude[${#arr_sxclude[@]}]="$2" - shift - ;; - -\!|-f) ex_invalid_usage "unsupported option: \`$1'" - ;; - -v) printf "%s version %s\n" "$me" "$version" - exit 0 - ;; - --) break - ;; - *) break - esac - shift -done -declare -i i=x=y=idx=0 +: ${PATH:=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin} -# check for ipset program and version -[[ -x ${ipset:=/sbin/ipset} ]] || { - printf "ipset binary \`%s' does not exist, or is not executable. check \`ipset' variable\n" "$ipset" >&2 - exit 1 -} -ips_version="$("$ipset" version)" -ips_version="${ips_version#ipset v}" -ips_version="${ips_version%%.*}" -if ! is_int "$ips_version"; then - printf "failed retrieving ipset version. expected digits, got: \`%s'\n" "$ips_version" >&2 - exit 1 -fi -if ((ips_version < 6)); then - printf "found version \`%s' - ipset versions from 6.x and upwards are supported\n" "$ips_version" >&2 - exit 1 +COMPREPLY=() + +# expecting _get_comp_words_by_ref() to exist from bash_completion +if declare -f _get_comp_words_by_ref &>/dev/null; then got_bashcompl=1 + _get_comp_words_by_ref -n : cur prev cword words || return +else got_bashcompl=0 # not so neat, but a workaround + COMP_WORDBREAKS="${COMP_WORDBREAKS//:/}" + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + cword=$COMP_CWORD + for i in ${!COMP_WORDS[@]}; do words[i]="${COMP_WORDS[i]}"; done fi -# validate TMOUT variable -if [[ $TMOUT ]] && ! is_int "$TMOUT"; then - ex_invalid_usage "timeout value \`$TMOUT' is not an integer" +#_DEBUG_NF_COMPLETION=Y +if [[ $_DEBUG_NF_COMPLETION ]]; then + printf "\nCOMP_WORDBREAKS: <%s>\n" "$COMP_WORDBREAKS" + printf "COMP_LINE: <%s>\n" "$COMP_LINE" + printf "COMP_TYPE: <%s>\n" "$COMP_TYPE" + printf "COMP_POINT: <%s>\n" "$COMP_POINT" + printf "COMP_KEY: <%s>\n" "$COMP_KEY" + printf "COMP_CWORD: <%s>\n" "$COMP_CWORD" + printf "\ncur: <%s> prev: <%s>\n" "$cur" "$prev" + printf "words:\n" + printf "<%s>\n" "${words[@]}" fi -# option logic +# collect info of cmdline +for ((i=1; i < ${#words[@]}-1; i++)); do + case "${words[i]}" in + -) ((set_index)) && break || iactive=1 ;; + -a) ((set_index)) && break || show_all=1 ;; + -i) ((set_index)) && break || isolate=1 Copts=(-Co) ;; + -m) ((set_index)) && break || show_members=1 ;; + -n) ((set_index)) && break || names_only=1 ;; + -r) ((set_index)) && break || resolve=1 ;; + -t) ((set_index)) && break || headers_only=1 Xopts=(-Xh -Xs) Fopts=(${Fopts[*]/-Oi/}) ;; + --) ((set_index)) && break || set_index=$((i+1)) ;; + -\?|-h|-v) + ((set_index)) || return 0 + ;; + @(-Fh|-Fi|-Hi|-Xh)) ((set_index)) && break || header_operation=1 ;; + *) + ((set_index)) && break + # options expecting an opt arg + str_tmp="-@(d|Fg|Fh|Fi|Fr|Gp|Gs|Gx|Hi|Ht|Hr|Hs|Hv|Mc|Oi|T|To|Xg|Xh|Xr|Xs)" + if [[ ${words[i-1]} = $str_tmp ]]; then + continue + elif [[ ${words[i-1]} = @(-Gp|-Gs|-Gx) && ${words[i]} != -* ]]; then + continue + fi + # if not an option, register set index + str_tmp="-@(-|?|a|c|d|h|i|m|n|r|s|t|v|Ca|Cs|Co|Fg|Fh|Fi|Fr|Gp|Gs|Gx|Hi|Ht|Hr|Hs|Hv|Mc|Oi|T|To|Tm|Ts|Xg|Xh|Xo|Xr)" + if [[ ${words[i]} != $str_tmp ]]; then + for x in ${!sets[@]}; do + if [[ ${sets[x]} = ${words[i]} ]]; then + set_index=$i + break + fi + done + fi + esac +done + +# invalid combinations of options if ((names_only)); then - if ((headers_only||show_members||show_all||isolate||\ - glob_xclude_element||regex_xclude_element||xclude_member_opts)) - then - ex_invalid_usage "option -n does not allow this combination of options" - fi -fi -if ((headers_only)); then - if ((show_members || show_all || isolate)); then - ex_invalid_usage "options -t and -a|-i|-m are mutually exclusive" - fi + if ((headers_only)); then + return 0 + fi fi -if ((headers_only)); then - if ((xclude_member_opts||glob_xclude_element||regex_xclude_element)); then - ex_invalid_usage "options -t and -Xg|-Xr|-Xo are mutually exclusive" - fi +if ((headers_only||names_only)); then + if ((show_all || show_members || isolate || resolve)); then + return 0 + fi +elif ((isolate)); then + if ((show_all || header_operation)); then + return 0 + fi fi -if ((isolate)); then - if ((show_count||show_all||calc_mem||count_sets||sets_total||exclude_set)); then - ex_invalid_usage "options -i and -a|-c|-Ca|-Cs|-Tm|-Ts|-Xs are mutually exclusive" - fi - if ((match_on_header)); then - ex_invalid_usage "option -i does not allow matching on header entries" - fi -fi -if ((glob_search || regex_search)); then - if ((glob_search && regex_search)); then - ex_invalid_usage "options -Fg and -Fr are mutually exclusive" - fi -fi -if ((exclude_header)); then - if ! ((headers_only || show_all)); then - ex_invalid_usage "option -Xh requires -a or -t" - fi -fi -if ((glob_xclude_element || regex_xclude_element)); then - if ! ((show_members || show_all || isolate)); then - ex_invalid_usage "options -Xg|-Xr require any of -a|-i|-m" - fi -fi -if ((colorize)); then - if ! [[ -x ${cl:=/usr/local/bin/cl} ]]; then - printf "\ncl program \`%s' does not exist, or is not executable.\ncheck \`cl' variable.\n\n" "$cl" >&2 - printf "If you do not have the program, you can download it from:\n" - printf "%s\n" "http://sourceforge.net/projects/colorize-shell/" \ - "https://github.com/AllKind/cl" >&2 - printf "\n" - exit 1 - fi - # set color defaults if unset - : ${col_fg:=white} - : ${col_bg:=black} - : ${col_headers:=cyan} - : ${col_members:=yellow} - : ${col_match:=red} - : ${col_memsize:=green} - : ${col_set_count:=magenta} - : ${col_set_total:=blue} - : ${col_highlight:=white} - # check if color defines are valid - for opt in col_fg col_bg col_headers col_members col_match col_memsize \ - col_set_count col_set_total col_highlight - do - ("$cl" ${!opt}) || ex_invalid_usage "variable \`$opt' has an invalid color value: \`${!opt}'" - done - [[ -t 1 ]] || colorize=0 # output is not a terminal -fi - -# sets to work on (no arg means all sets) -while IFS=$'\n' read -r; do - arr_sets[idx++]="$REPLY" -done < <("$ipset" list -n) -if ! ((${#arr_sets[@]})); then - printf "Cannot find any sets\n" >&2 - exit 1 -fi -if [[ $1 ]]; then # there are remaining arg(s) - for opt; do found_set=0 # check if the sets exist - for idx in ${!arr_sets[@]}; do - if [[ ${arr_sets[idx]} = $opt ]]; then found_set=1 - # match could be a glob, thus multiple matches possible - # save to temp array - arr_tmp[${#arr_tmp[@]}]="${arr_sets[idx]}" - unset arr_sets[idx] - fi - done - if ! ((found_set)); then - ex_invalid_usage "\`$opt' is not a valid option nor an existing set name" - fi - done - if ((isolate)); then - if (($# != 1)); then - ex_invalid_usage "option -i is only valid for a single set" - fi - fi - arr_sets=("${arr_tmp[@]}") # reassign matched sets - if ((isolate && ${#arr_sets[@]} > 1)); then - ex_invalid_usage "option -i is only valid for a single set" - fi +# start setting compreply +# all depends on $set_index +if ((set_index)); then + if ((isolate && cword > set_index)); then + return 0 # allow only one set with isolate + fi + # dont' allow an option after the set name(s) + # allows to list sets which start with an hyphen + # and also handles those who have the name of ipset_list options + _ipset_list_show_sets else - if ((isolate)); then - ex_invalid_usage "option -i is only valid for a single set" +if [[ $prev = -@(\?|d|h|v|Fg|Fi|Fr|Hi|Oi|T|To|Xg|Xr) ]]; then + return 0 +elif [[ $prev = -Xs ]]; then + # list sets if user does not want to enter a glob + _ipset_list_show_sets +elif [[ $prev = -Ht ]]; then i=0 + # show supported set types + while read -r; do + [[ $REPLY = "Supported set types:"* ]] && ((!i)) && \ + i=1 && continue + ((i)) || continue + if [[ $REPLY = *:* ]]; then + set -- $REPLY + arr_types[${#arr_types[@]}]="$1" + fi + done < <(ipset help) + for i in ${!arr_types[@]}; do # remove dupe entries + for x in ${!arr_tmp[@]}; do + [[ ${arr_tmp[x]} = ${arr_types[i]} ]] && continue 2 + done + arr_tmp[${#arr_tmp[@]}]="${arr_types[i]}" + done + arr_types=( "${arr_tmp[@]}" ) + COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) ) +elif [[ $prev = @(-Fh|-Xh) ]]; then + # retrieve list of headers + if ((${#sets[*]} > 0)); then + while read -r; do + [[ $REPLY = Name ]] && continue + COMPREPLY[${#COMPREPLY[@]}]="$REPLY" + done < <(command "$ipset_list" -t "${sets[0]}" 2>/dev/null|command awk -F: '{print $1}') + compopt -o nospace + local IFS=$'\n' + if [[ $prev = -Xh ]]; then + COMPREPLY=( $( compgen -P '"' -S ':*"' \ + -W '${COMPREPLY[@]}' -- "$cur" ) ) + elif [[ $prev = -Fh ]]; then + COMPREPLY=( $( compgen -P '"' -S ':"' \ + -W '${COMPREPLY[@]}' -- "$cur" ) ) + fi + fi +elif [[ $prev = @(-@(Hr|Hs|Hv|Mc)) ]]; then + # options making use of arithmetic comparison + compopt -o nospace + COMPREPLY=( $( compgen -P '\' -W '\! \< \> \<= \>=' -- "$cur" ) ) +elif [[ $prev = @(-Gp|-Gs|-Gx) && $cur != -* ]]; then # fails on files starting with a dash. I don't care. + if ((got_bashcompl)); then + _filedir + COMPREPLY=( $( compgen -W 'auto none ${COMPREPLY[@]}' -- "$cur" ) ) + else + COMPREPLY=( $( compgen -f -- "$cur" ) ) fi +elif [[ $cur = -* ]]; then + # any option is requested + case "$prev" in + -@(-|\?|d|h|v|Fg|Fh|Fi|Fr|Hi|Ht|Hr|Hs|Hv|Mc|Oi|T|To|Xg|Xh|Xr)) + # options that exclude any other option, + # or need a value we can't predict + return 0 + ;; + esac + if ((${#words[@]} > 2)); then + # these options don't allow any other - remove them + opts=("${opts[@]/@(-v|-h|-\?)/}") + fi + # some options allow only a subset of other options + if ((iactive)); then + COMPREPLY=( $(compgen -W '${Iopts[@]} ${Gopts[@]}' -- $cur ) ) + elif ((isolate)); then + COMPREPLY=( $(compgen -W '-- -Co -d -r -s -Fg -Fr ${Gopts[@]} -Oi -T -To -Xg -Xo -Xr' -- $cur ) ) + elif ((names_only)); then + COMPREPLY=( $(compgen -W \ + '-- -c ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} -Xs' \ + -- $cur ) ) + elif ((headers_only)); then + COMPREPLY=( $(compgen -W \ + '-- -c ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} ${Xopts[@]}' \ + -- $cur ) ) + elif ((show_members)); then + COMPREPLY=( $(compgen -W \ + '-- -c -d -r -s ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} -Xg -Xr -Xo' \ + -- $cur ) ) + elif ((show_all)); then + COMPREPLY=( $(compgen -W \ + '-- -c -d -r -s ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} ${Xopts[@]}' \ + -- $cur ) ) + elif ((resolve)); then + COMPREPLY=( $(compgen -W \ + '-- -a -c -d -s -m ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} ${Xopts[@]}' \ + -- $cur ) ) + elif ((header_operation)); then + COMPREPLY=( $(compgen -W \ + '-- -a -c -d -s -m -t ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} ${Xopts[@]}' \ + -- $cur ) ) + else + COMPREPLY=( $(compgen -W \ + '${opts[@]} ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} ${Xopts[@]}' \ + -- $cur ) ) + fi + # post process the reply + if ((${#COMPREPLY[@]})); then + x=$((set_index ? set_index : ${#words[*]}-1)) + # mutual exclusive options + for ((i=1; i < x; i++)); do + case "${words[i]}" in + -Fg) _ipset_list_remove_reply_entry "-Fr" ;; + -Fr) _ipset_list_remove_reply_entry "-Fg" ;; + -Xg) _ipset_list_remove_reply_entry "-Xr" ;; + -Xr) _ipset_list_remove_reply_entry "-Xg" ;; + esac + # options allowed multiple times + if [[ ${words[i]} = @(""|-|-@(Fh|Fi|Hi|Mc|Oi|T|Xh|Xs)) ]]; then + continue + else # remove dupe + _ipset_list_remove_reply_entry "${words[i]}" + fi + done + fi +elif [[ $cur = * ]]; then + # non option request + # default to sets listing + # except we are in interactive mode + if ! ((iactive)); then + _ipset_list_show_sets + fi +fi fi -# read sets -for idx in "${!arr_sets[@]}"; do found_set=0 arr_hcache=() arr_mcache=() - while read -r || { - (($? > 128)) && \ - printf "timeout reached or signal received, while reading set \`%s'.\n" \ - "${arr_sets[idx]}" >&2 && continue 2; - }; do - case "$REPLY" in - "") : ;; - Name:*) # header opened (set found) - if ((in_header)); then - printf "unexpected entry: \`%s' - header not closed?\n" "$REPLY" >&2 - exit 1 - fi - let sets_sum+=1 - if ((exclude_set)); then # don't show certain sets - for y in ${!arr_sxclude[@]}; do - if [[ ${arr_sets[idx]} = ${arr_sxclude[y]} ]]; then let found_sxclude+=1 - continue 3 # don't unset, as user could list sets multiple times - fi - done - fi - in_header=1 found_set=1 found_header=0 member_count=0 match_count=0 xclude_count=0 mem_tmp=0 i=0 x=0 - if ! ((isolate)); then # if showing members only, continue without saving any header data - if ((names_only)); then - if ((colorize)); then - arr_hcache[x++]="$("$cl" bold $col_headers)${REPLY#*:+([[:blank:]])}$("$cl" normal $col_fg $col_bg)" - else - arr_hcache[x++]="${REPLY#*:+([[:blank:]])}" - fi - elif ! ((headers_only||show_members||show_all||show_count||match_on_header||do_count||calc_mem||glob_search||regex_search||opt_int_search)) - then - in_header=0 - if ((colorize)); then - arr_hcache[x++]="$("$cl" bold $col_headers)${REPLY}$("$cl" normal $col_fg $col_bg)" - else - arr_hcache[x++]="$REPLY" - fi - break # nothing to show but the names - else - if ((colorize)); then - arr_hcache[x++]=$'\n'"$("$cl" bold $col_headers)${REPLY}$("$cl" normal $col_fg $col_bg)" - else - arr_hcache[x++]=$'\n'"$REPLY" - fi - fi - fi - ;; - Members:*) # closes header (if not `ipset -t') - if ! ((in_header)); then - printf "unexpected entry: \`%s' - header not opened?\n" "$REPLY" >&2 - exit 1 - fi - in_header=0 found_hxclude=0 - if ((match_on_header)); then - if ((found_header != match_on_header)); then found_set=0 - break # set does not contain wanted header - fi - fi - if ((exclude_header)); then # don't show certain headers - for y in ${!arr_hxclude[@]}; do - if [[ ${REPLY%%:*} = ${arr_hxclude[y]%%:*} && ${REPLY#*: } = ${arr_hxclude[y]#*:} ]] - then found_hxclude=1 - break - fi - done - fi - if ((show_all && ! found_hxclude)); then - if ((colorize)); then - arr_hcache[x++]="$("$cl" bold $col_headers)${REPLY}$("$cl" normal $col_fg $col_bg)" - else - arr_hcache[x++]="$REPLY" - fi - fi - ;; - *) # either in-header, or member entry - if ! ((found_set)); then - printf "no set opened by \`Name:'. unexpected entry \`%s'.\n" "$REPLY" >&2 - exit 1 - fi - if ((in_header)); then # we should be in the header - if ((match_on_header && found_header < match_on_header)); then # match on an header entry - for y in ${!arr_hsearch[@]}; do # string compare - if [[ ${REPLY%%:*} = ${arr_hsearch[y]%%:*} && ${REPLY#*: } = ${arr_hsearch[y]#*:} ]] - then let found_header+=1 - fi - done - for y in ${!arr_hsearch_int[@]}; do # int compare - if [[ ${REPLY%%:*} = ${arr_hsearch_int[y]%%:*} ]]; then # header name matches - if ! is_int "${REPLY#*: }"; then - printf "header value \`%s' is not an integer.\n" "${REPLY#*: }" >&2 - exit 1 - fi - str_val="${arr_hsearch_int[y]#*:}" - str_op="${str_val//[[:digit:]]}" # compare operator defaults to `==' - [[ ${str_op:===} = \! ]] && str_op='!=' - if ((${REPLY#*: } $str_op ${str_val//[[:punct:]]})); then - let found_header+=1 - fi - fi - done - # search and arithmetic compare values of the headers 'Header' flag - if ((${#arr_hsearch_xint[@]})) && [[ ${REPLY%%:*} = Header ]]; then - set -- ${REPLY#*:} - while (($#)); do - if is_digit_or_xigit "$1"; then - shift - continue - fi - for y in ${!arr_hsearch_xint[@]}; do - str_name="${arr_hsearch_xint[y]%%:*}" - str_val="${arr_hsearch_xint[y]#*:}" - if [[ $str_val = ??0[xX]+([[:xdigit:]]) ]]; then - str_op="${str_val%0[xX]*}" - elif [[ $str_val = ??+([[:digit:]]) ]]; then - str_op="${str_val//[[:digit:]]}" - fi - str_val="${str_val#"${str_op}"}" - [[ ${str_op:===} = \! ]] && str_op='!=' - if [[ $1 = $str_name ]]; then - if is_digit_or_xigit "$2"; then - if (($2 $str_op $str_val)); then - let found_header+=1 - shift - break - fi - fi - fi - done - shift - done - fi - fi - if ((calc_mem)); then - if [[ ${REPLY%%:*} = "Size in memory" ]]; then - if ! is_int "${REPLY#*: }"; then - printf "header value \`%s' is not an integer.\n" "${REPLY#*: }" >&2 - exit 1 - fi - # save to temp, in case we throw away the set, if it doesn't match other criteria - mem_tmp=${REPLY#*: } - fi - fi - if ((headers_only || show_all)); then found_hxclude=0 - if ((exclude_header)); then # don't show certain headers - for y in ${!arr_hxclude[@]}; do - if [[ ${REPLY%%:*} = ${arr_hxclude[y]%%:*} && ${REPLY#*: } = ${arr_hxclude[y]#*:} ]] - then found_hxclude=1 - break - fi - done - fi - if ! ((found_hxclude)); then - arr_hcache[x++]="$REPLY" - fi - fi - else # this should be a member entry - if ((show_members || show_all || isolate || glob_search || regex_search || opt_int_search)); then - if ((glob_search)); then # show sets with glob pattern matching members - if ! xclude_elem_search; then - if [[ $REPLY = $str_search ]]; then - if ((opt_int_search)); then - arith_elem_opt_search - else - let match_count+=1 - add_search_to_member_cache - fi - fi - fi - elif ((regex_search)); then # show sets with regex pattern matching members - if ! xclude_elem_search; then - if [[ $REPLY =~ $str_search ]]; then - if ((opt_int_search)); then - arith_elem_opt_search - else - let match_count+=1 - add_search_to_member_cache - fi - else - if (($? == 2)); then - printf "Invalid regex pattern \`%s'.\n" "$str_search" >&2 - exit 1 - fi - fi - fi - elif ((opt_int_search)); then # show sets with matching member options - if ! xclude_elem_search; then - arith_elem_opt_search - fi - else - if ((glob_xclude_element)); then # exclude matching members - if ! [[ $REPLY = $str_xclude ]]; then - add_search_to_member_cache - else let xclude_count+=1 - fi - elif ((regex_xclude_element)); then # exclude matching members - if [[ $REPLY =~ $str_xclude ]]; then - let xclude_count+=1 - else - if (($? == 2)); then - printf "Invalid regex pattern \`%s'.\n" "$str_xclude" >&2 - exit 1 - fi - add_search_to_member_cache - fi - else - arr_mcache[i++]="$REPLY" - fi - fi - else # nothing to show or search for, do we need to count members? - if ! ((show_count || do_count)); then - break # nothing more to do for this set - fi - fi - let member_count+=1 - fi - esac - done < <("$ipset" list "${arr_sets[idx]}" "${arr_par[@]}") - if ((found_set)); then # print gathered information - if ((glob_search || regex_search || opt_int_search)) && ((match_count == 0)); then - continue # glob, regex or option-integer search didn't match - fi - if ((${#arr_match_on_msum[@]} > 0)); then # match on member sum (do_count=1) - for i in ${!arr_match_on_msum[@]}; do - str_op="${arr_match_on_msum[i]//[[:digit:]]}" - [[ ${str_op:===} = \! ]] && str_op='!=' - if ! (($member_count $str_op ${arr_match_on_msum[i]//[[:punct:]]})); then - continue 2 # does not match - fi - done - fi - let set_count+=1 # count amount of matching sets - if ((calc_mem)); then - let mem_total+=$mem_tmp - fi - if ((${#arr_hcache[@]})); then # print header - if ((colorize)); then - printf "$("$cl" $col_headers)%b$("$cl" normal $col_fg $col_bg)\n" "${arr_hcache[@]}" - else - printf "%s\n" "${arr_hcache[@]}" - fi - fi - if ((${#arr_mcache[@]})); then # print members - if ((xclude_member_opts)); then - arr_mcache=( "${arr_mcache[@]%% *}" ) - fi - IFS="${delim:= }" - if ((colorize)); then - printf "$("$cl" $col_members)%s$("$cl" normal $col_fg $col_bg)" "${arr_mcache[*]}" - else - printf "%s" "${arr_mcache[*]}" - fi - IFS="$oIFS" - printf "\n" - fi - if ((show_count)); then # print counters - if ((glob_search || regex_search || opt_int_search)); then - if ((colorize)); then - printf "$("$cl" $col_match)Match count$("$cl" normal $col_fg $col_bg):\ - $("$cl" bold $col_match)%d$("$cl" normal $col_fg $col_bg)\n" $match_count - else - printf "Match count: %d\n" $match_count - fi - fi - if ((glob_xclude_element || regex_xclude_element)); then - if ((colorize)); then - printf "$("$cl" $col_match)Exclude count$("$cl" normal $col_fg $col_bg):\ - $("$cl" bold $col_match)%d$("$cl" normal $col_fg $col_bg)\n" $xclude_count - else - printf "Exclude count: %d\n" $xclude_count - fi - fi - if ((colorize)); then - printf "$("$cl" bold $col_highlight)Member count$("$cl" normal $col_fg $col_bg):\ - $("$cl" bold $col_members)%d$("$cl" normal $col_fg $col_bg)\n" $member_count - else - printf "Member count: %d\n" $member_count - fi - fi - fi -done +((got_bashcompl)) && __ltrim_colon_completions "$cur" -# print global counters -if ((count_sets || calc_mem || sets_total || exclude_set)); then - printf "\n" - if ((count_sets)); then - if ((colorize)); then - printf "$("$cl" bold $col_highlight)Count$("$cl" normal $col_fg $col_bg) of all\ - $("$cl" bold $col_set_count)matched sets$("$cl" normal $col_fg $col_bg):\ - $("$cl" bold $col_set_count)%d$("$cl" normal $col_fg $col_bg)\n" $set_count - else - printf "Count of all matched sets: %d\n" $set_count - fi - if ((exclude_set)); then - if ((colorize)); then - printf "$("$cl" bold $col_highlight)Count$("$cl" normal $col_fg $col_bg) of all\ - $("$cl" bold $col_match)excluded sets$("$cl" normal $col_fg $col_bg):\ - $("$cl" bold $col_match)%d$("$cl" normal $col_fg $col_bg)\n" $found_sxclude - else - printf "Count of all excluded sets: %d\n" $found_sxclude - fi - fi - fi - if ((sets_total)); then - if ((colorize)); then - printf "$("$cl" bold $col_highlight)Count$("$cl" normal $col_fg $col_bg) of all\ - $("$cl" bold $col_set_total)traversed sets$("$cl" normal $col_fg $col_bg):\ - $("$cl" bold $col_set_total)%d$("$cl" normal $col_fg $col_bg)\n" $sets_sum - else - printf "Count of all traversed sets: %d\n" $sets_sum - fi - fi - if ((calc_mem)); then - if ((colorize)); then - printf "$("$cl" bold $col_memsize)Total memory size$("$cl" normal $col_fg $col_bg)\ - of all matched sets: $("$cl" bold $col_memsize)%d$("$cl" normal $col_fg $col_bg)\n" $mem_total - else - printf "Total memory size of all matched sets: %d\n" $mem_total - fi - fi +if [[ $_DEBUG_NF_COMPLETION ]]; then + printf "COMPREPLY:\n" + printf "<%s>\n" "${COMPREPLY[@]}" fi +} +complete -F _ipset_list_complete "${ipset_list:-ipset_list}" + |