summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--ChangeLog126
-rw-r--r--Make_global.am2
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac242
-rw-r--r--include/libipset/Makefile.am3
-rw-r--r--include/libipset/args.h3
-rw-r--r--include/libipset/data.h8
-rw-r--r--include/libipset/debug.h2
-rw-r--r--include/libipset/ip_set_compiler.h15
-rw-r--r--include/libipset/linux_ip_set.h8
-rw-r--r--include/libipset/list_sort.h4
-rw-r--r--include/libipset/parse.h2
-rw-r--r--include/libipset/print.h3
-rw-r--r--include/libipset/session.h3
-rw-r--r--include/libipset/xlate.h6
-rw-r--r--kernel/ChangeLog167
-rw-r--r--kernel/include/linux/jhash.h27
-rw-r--r--kernel/include/linux/netfilter/ipset/ip_set.h42
-rw-r--r--kernel/include/linux/netfilter/ipset/ip_set_compat.h.in214
-rw-r--r--kernel/include/linux/netfilter/ipset/ip_set_compiler.h.in15
-rw-r--r--kernel/include/linux/netfilter/ipset/ip_set_getport.h2
-rw-r--r--kernel/include/linux/netfilter/ipset/ip_set_hash.h2
-rw-r--r--kernel/include/uapi/linux/netfilter/ipset/ip_set.h12
-rw-r--r--kernel/net/netfilter/ipset/Kconfig2
-rw-r--r--kernel/net/netfilter/ipset/ip_set_bitmap_gen.h22
-rw-r--r--kernel/net/netfilter/ipset/ip_set_bitmap_ip.c21
-rw-r--r--kernel/net/netfilter/ipset/ip_set_bitmap_ipmac.c10
-rw-r--r--kernel/net/netfilter/ipset/ip_set_bitmap_port.c10
-rw-r--r--kernel/net/netfilter/ipset/ip_set_core.c478
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_gen.h839
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_ip.c45
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_ipmac.c6
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_ipmark.c24
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_ipport.c39
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_ipportip.c17
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c17
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_mac.c6
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_net.c17
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_netiface.c45
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_netnet.c40
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_netport.c17
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_netportnet.c34
-rw-r--r--kernel/net/netfilter/ipset/ip_set_list_set.c55
-rw-r--r--kernel/net/netfilter/ipset/pfxlen.c2
-rw-r--r--kernel/net/netfilter/xt_set.c2
-rw-r--r--kernel/net/sched/em_ipset.c7
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/args.c24
-rw-r--r--lib/data.c39
-rw-r--r--lib/debug.c5
-rw-r--r--lib/errcode.c4
-rw-r--r--lib/ipset.c612
-rw-r--r--lib/ipset_hash_ip.c171
-rw-r--r--lib/ipset_hash_ipmac.c85
-rw-r--r--lib/ipset_hash_ipmark.c99
-rw-r--r--lib/ipset_hash_ipport.c214
-rw-r--r--lib/ipset_hash_ipportip.c117
-rw-r--r--lib/ipset_hash_ipportnet.c125
-rw-r--r--lib/ipset_hash_mac.c69
-rw-r--r--lib/ipset_hash_net.c85
-rw-r--r--lib/ipset_hash_netiface.c99
-rw-r--r--lib/ipset_hash_netnet.c200
-rw-r--r--lib/ipset_hash_netport.c104
-rw-r--r--lib/ipset_hash_netportnet.c122
-rw-r--r--lib/libipset.map15
-rw-r--r--lib/mnl.c2
-rw-r--r--lib/parse.c121
-rw-r--r--lib/print.c79
-rw-r--r--lib/session.c160
-rw-r--r--m4/ax_cflags_gcc_option.m420
-rw-r--r--src/Makefile.am8
-rw-r--r--src/ipset-translate.891
-rw-r--r--src/ipset.8112
-rw-r--r--src/ipset.c10
-rw-r--r--src/ui.c2
-rw-r--r--tests/bitmap:ip.t28
-rw-r--r--tests/bitmap:ip.t.list417
-rw-r--r--tests/bitmap:ip.t.list59
-rw-r--r--tests/bitmap:ip.t.list6521
-rwxr-xr-xtests/cidr.sh35
-rw-r--r--tests/comment.t34
-rw-r--r--tests/comment.t.list111025
-rw-r--r--tests/comment.t.list12517
-rw-r--r--tests/comment.t.list25
-rw-r--r--tests/comment.t.list211029
-rw-r--r--tests/comment.t.list22517
-rw-r--r--tests/comment.t.list318
-rwxr-xr-xtests/diff.sh7
-rw-r--r--tests/hash:ip,mark.t8
-rw-r--r--tests/hash:ip,mark.t.list013
-rw-r--r--tests/hash:ip,mark.t.list15
-rw-r--r--tests/hash:ip,port,ip.t8
-rw-r--r--tests/hash:ip,port,ip.t.list013
-rw-r--r--tests/hash:ip,port,ip.t.list13
-rw-r--r--tests/hash:ip,port,net.t4
-rw-r--r--tests/hash:ip,port,net.t.list013
-rw-r--r--tests/hash:ip,port.t138
-rw-r--r--tests/hash:ip,port.t.list013
-rw-r--r--tests/hash:ip,port.t.list15
-rw-r--r--tests/hash:ip,port.t.list27
-rw-r--r--tests/hash:ip,port.t.list311
-rw-r--r--tests/hash:ip,port.t.list49
-rw-r--r--tests/hash:ip,port.t.list511
-rw-r--r--tests/hash:ip,port.t.list69
-rw-r--r--tests/hash:ip,port.t.list79
-rw-r--r--tests/hash:ip.t98
-rw-r--r--tests/hash:ip.t.list04
-rw-r--r--tests/hash:ip.t.list15
-rw-r--r--tests/hash:ip.t.list29
-rw-r--r--tests/hash:ip.t.list311
-rw-r--r--tests/hash:ip.t.list411
-rw-r--r--tests/hash:ip.t.list59
-rw-r--r--tests/hash:ip.t.list69
-rw-r--r--tests/hash:ip6,mark.t8
-rw-r--r--tests/hash:ip6,mark.t.list013
-rw-r--r--tests/hash:ip6,mark.t.list15
-rw-r--r--tests/hash:ip6,port,ip6.t8
-rw-r--r--tests/hash:ip6,port,ip6.t.list014
-rw-r--r--tests/hash:ip6,port,ip6.t.list15
-rw-r--r--tests/hash:ip6,port,net6.t4
-rw-r--r--tests/hash:ip6,port,net6.t.list05
-rw-r--r--tests/hash:ip6,port.t8
-rw-r--r--tests/hash:ip6,port.t.list013
-rw-r--r--tests/hash:ip6,port.t.list15
-rw-r--r--tests/hash:ip6.t28
-rw-r--r--tests/hash:ip6.t.list05
-rw-r--r--tests/hash:ip6.t.list15
-rw-r--r--tests/hash:ip6.t.list29
-rw-r--r--tests/hash:ip6.t.list311
-rw-r--r--tests/hash:mac.t16
-rw-r--r--tests/hash:mac.t.list05
-rw-r--r--tests/hash:mac.t.list15
-rw-r--r--tests/hash:mac.t.list29
-rw-r--r--tests/hash:mac.t.list35
-rw-r--r--tests/hash:net,iface.t16
-rw-r--r--tests/hash:net,iface.t.list05
-rw-r--r--tests/hash:net,iface.t.list15
-rw-r--r--tests/hash:net,iface.t.list25
-rw-r--r--tests/hash:net,net.t118
-rw-r--r--tests/hash:net,net.t.list013
-rw-r--r--tests/hash:net,net.t.list15
-rw-r--r--tests/hash:net,net.t.list25
-rw-r--r--tests/hash:net,net.t.list311
-rw-r--r--tests/hash:net,net.t.list49
-rw-r--r--tests/hash:net,net.t.list511
-rw-r--r--tests/hash:net,net.t.list69
-rw-r--r--tests/hash:net,net.t.list79
-rw-r--r--tests/hash:net,port,net.t10
-rw-r--r--tests/hash:net,port,net.t.list013
-rw-r--r--tests/hash:net,port.t8
-rw-r--r--tests/hash:net,port.t.list015
-rw-r--r--tests/hash:net,port.t.list15
-rw-r--r--tests/hash:net.t16
-rw-r--r--tests/hash:net.t.list013
-rw-r--r--tests/hash:net.t.list15
-rw-r--r--tests/hash:net.t.list25
-rw-r--r--tests/hash:net.t.list35
-rw-r--r--tests/hash:net6,net6.t8
-rw-r--r--tests/hash:net6,net6.t.list013
-rw-r--r--tests/hash:net6,net6.t.list15
-rw-r--r--tests/hash:net6,port,net6.t4
-rw-r--r--tests/hash:net6,port,net6.t.list05
-rw-r--r--tests/hash:net6,port.t12
-rw-r--r--tests/hash:net6,port.t.list015
-rw-r--r--tests/hash:net6,port.t.list15
-rw-r--r--tests/hash:net6.t8
-rw-r--r--tests/hash:net6.t.list013
-rw-r--r--tests/hash:net6.t.list15
-rwxr-xr-xtests/ignore.sh4
-rw-r--r--tests/iphash.t16
-rw-r--r--tests/iphash.t.large2
-rw-r--r--tests/iphash.t.list05
-rw-r--r--tests/iphash.t.list15
-rw-r--r--tests/iphash.t.restore.sorted4
-rw-r--r--tests/ipmap.t20
-rw-r--r--tests/ipmap.t.list03
-rw-r--r--tests/ipmap.t.list13
-rw-r--r--tests/ipmap.t.list23
-rw-r--r--tests/ipmap.t.list33
-rw-r--r--tests/ipmap.t.list43
-rw-r--r--tests/ipmarkhash.t8
-rw-r--r--tests/ipmarkhash.t.list05
-rw-r--r--tests/ipmarkhash.t.list15
-rw-r--r--tests/ipporthash.t8
-rw-r--r--tests/ipporthash.t.list05
-rw-r--r--tests/ipporthash.t.list15
-rw-r--r--tests/ipportiphash.t8
-rw-r--r--tests/ipportiphash.t.list05
-rw-r--r--tests/ipportiphash.t.list15
-rwxr-xr-xtests/iptables.sh10
-rw-r--r--tests/macipmap.t16
-rw-r--r--tests/macipmap.t.list27
-rw-r--r--tests/macipmap.t.list311
-rw-r--r--tests/nethash.t4
-rw-r--r--tests/nethash.t.list05
-rwxr-xr-xtests/netnetgen.sh2
-rw-r--r--tests/portmap.t16
-rw-r--r--tests/portmap.t.list39
-rwxr-xr-xtests/resize.sh4
-rwxr-xr-xtests/resizec.sh32
-rwxr-xr-xtests/resizen.sh49
-rwxr-xr-xtests/resizet.sh40
-rw-r--r--tests/restore.t24
-rw-r--r--tests/restore.t.list05
-rw-r--r--tests/restore.t.list15
-rwxr-xr-xtests/runtest.sh12
-rw-r--r--tests/setlist.t22
-rw-r--r--tests/setlist.t.list423
-rwxr-xr-xtests/setlist_ns.sh22
-rwxr-xr-xtests/setlist_resize.sh47
-rwxr-xr-xtests/sort.sh6
l---------tests/xlate/ipset-translate1
-rwxr-xr-xtests/xlate/runtest.sh35
-rw-r--r--tests/xlate/xlate.t57
-rw-r--r--tests/xlate/xlate.t.nft58
-rw-r--r--utils/ipset_bash_completion/README.md64
-rw-r--r--utils/ipset_bash_completion/ipset1507
-rw-r--r--[-rwxr-xr-x]utils/ipset_list/ipset_list1299
219 files changed, 8849 insertions, 4927 deletions
diff --git a/.gitignore b/.gitignore
index a2aeac6..3ce7819 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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/
diff --git a/ChangeLog b/ChangeLog
index 60d6acc..21653e0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,129 @@
+7.24
+ - Improve fixing commas in sorted json output
+ - Fix extra quotes around elements in json output
+ (bugzilla #1793, issue 3.)
+ - Fix commas in sorted json output (bugzilla #1793, issue 4)
+ - Fix unquoted port range in json output (bugzilla #1793, issue 1)
+ - Fix extraneous comma in terse list json output (Joachim,
+ bugzilla #1793, issue 2)
+ - bash-completion: restore fix for syntax error (Jeremy Sowden)
+ - Correct typo in man-page (Jeremy Sowden)
+
+7.23
+ - tests: runtest.sh: Keep running, print summary of failed tests
+ (Phil Sutter)
+ - tests: cidr.sh: Fix for quirks in RHEL's ipcalc (Phil Sutter)
+ - tests: cidr.sh: Respect IPSET_BIN env var (Phil Sutter)
+ - ipset: Fix implicit declaration of function basename (Mike Pagano)
+ - tests: Reduce testsuite run-time (Phil Sutter)
+ - lib: ipset: Avoid 'argv' array overstepping (Phil Sutter)
+ - lib: data: Fix for global-buffer-overflow warning by ASAN
+ (Phil Sutter)
+
+7.22
+ - ipset: fix json output format for IPSET_OPT_IP (Z. Liu)
+ - tests: add namespace test and take into account delayed
+ set removal at module remove
+ - Update autoconfig tools to build cleanly on Debian bookworm
+
+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..f6e1c36 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.24],[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])
+AC_CONFIG_HEADERS([config.h])
+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" != ""
@@ -180,7 +182,7 @@ dnl Checks for programs
AC_PROG_CC
AM_PROG_CC_C_O
-AC_PROG_LIBTOOL
+LT_INIT
AC_PROG_INSTALL
AC_PROG_LN_S
@@ -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])
@@ -371,7 +401,7 @@ fi
AC_MSG_CHECKING([kernel source for id in struct pernet_operations])
if test -f $ksourcedir/include/net/net_namespace.h && \
- $AWK '/^struct pernet_operations /,/^}/' $ksourcedir/include/net/net_namespace.h | $GREP -q 'int \*id;'; then
+ $AWK '/^struct pernet_operations /,/^}/' $ksourcedir/include/net/net_namespace.h | $GREP -qE 'int \*( const )?id;'; then
AC_MSG_RESULT(yes)
AC_SUBST(HAVE_NET_OPS_ID, define)
else
@@ -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,139 @@ 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 second arg of nf_bridge_get_physindev() in netfilter_bridge.h])
+if test -f $ksourcedir/include/linux/netfilter_bridge.h && \
+ $GREP 'nf_bridge_get_physindev' $ksourcedir/include/linux/netfilter_bridge.h | $GREP -q ' struct net '; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_NF_BRIDGE_GET_PYSINDEV_NET, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_NF_BRIDGE_GET_PYSINDEV_NET, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for rcupdate_wait.h])
+if test -f $ksourcedir/include/linux/rcupdate_wait.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_RCUPDATE_WAIT_H, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_RCUPDATE_WAIT_H, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for lockdep_set_class in lockdep.h])
+if test -f $ksourcedir/include/linux/lockdep.h && \
+ $GREP -q 'define lockdep_set_class' $ksourcedir/include/linux/lockdep.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_LOCKDEP_SET_CLASS, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_LOCKDEP_SET_CLASS, 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 +974,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..33d2dd3 100644
--- a/kernel/ChangeLog
+++ b/kernel/ChangeLog
@@ -1,3 +1,170 @@
+7.24
+ - netfilter: ipset: fix region locking in hash types
+ - Handle "netfilter: ipset: Fix for recursive locking warning"
+ patch for backward compatibility
+ - netfilter: ipset: Fix for recursive locking warning
+
+7.23
+ - netfilter: ipset: Hold module reference while requesting a module
+ (Phil Sutter)
+ - netfilter: ipset: add missing range check in bitmap_ip_uadt
+ (Jeongjun Park)
+ - netfilter: ipset: Fix suspicious rcu_dereference_protected()
+ - Replace BUG_ON() with WARN_ON_ONCE() according to usage policy.
+
+7.22
+ - netfilter: ipset: Fix race between namespace cleanup and gc
+ in the list:set type
+ - netfilter: ipset: Add list flush to cancel_gc (Alexander Maltsev)
+ - Kill sched.h dependency on rcupdate.h (Kent Overstreet)
+ - Handle "netfilter: propagate net to nf_bridge_get_physindev" patch
+ - netfilter: propagate net to nf_bridge_get_physindev (Pavel Tikhomirov)
+ - Revert "netfilter: ipset: remove set destroy at ip_set module removal"
+
+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..32a8348 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,27 @@
#@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
+#@HAVE_NF_BRIDGE_GET_PYSINDEV_NET@ HAVE_NF_BRIDGE_GET_PYSINDEV_NET
+#@HAVE_RCUPDATE_WAIT_H@ HAVE_RCUPDATE_WAIT_H
+#@HAVE_LOCKDEP_SET_CLASS@ HAVE_LOCKDEP_SET_CLASS
#ifdef HAVE_EXPORT_SYMBOL_GPL_IN_MODULE_H
#include <linux/module.h>
@@ -150,6 +170,7 @@ do { \
#endif
#endif
+#ifndef HAVE_RCUPDATE_WAIT_H
#ifndef HAVE_COND_RESCHED_RCU
static inline void cond_resched_rcu(void)
{
@@ -160,12 +181,21 @@ static inline void cond_resched_rcu(void)
#endif
}
#endif
+#endif
#if defined(CONFIG_NETFILTER_NETLINK) || defined(CONFIG_NETFILTER_NETLINK_MODULE)
#else
#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 +283,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 +360,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, 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 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 SET_NFNL_CALLBACK_TYPE(t)
#endif
#ifndef HAVE_TC_SKB_PROTOCOL
@@ -347,7 +413,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 +425,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 +442,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 +512,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 +590,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/linux/netfilter/ipset/ip_set_hash.h b/kernel/include/linux/netfilter/ipset/ip_set_hash.h
index 838abab..56e8836 100644
--- a/kernel/include/linux/netfilter/ipset/ip_set_hash.h
+++ b/kernel/include/linux/netfilter/ipset/ip_set_hash.h
@@ -6,7 +6,7 @@
#define IPSET_DEFAULT_HASHSIZE 1024
-#define IPSET_MIMINAL_HASHSIZE 64
+#define IPSET_MINIMAL_HASHSIZE 64
#define IPSET_DEFAULT_MAXELEM 65536
#define IPSET_DEFAULT_PROBES 4
#define IPSET_DEFAULT_RESIZE 100
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..9db4db9 100644
--- a/kernel/net/netfilter/ipset/ip_set_bitmap_gen.h
+++ b/kernel/net/netfilter/ipset/ip_set_bitmap_gen.h
@@ -5,6 +5,10 @@
#ifndef __IP_SET_BITMAP_IP_GEN_H
#define __IP_SET_BITMAP_IP_GEN_H
+#ifdef HAVE_RCUPDATE_WAIT_H
+#include <linux/rcupdate_wait.h>
+#endif
+
#define mtype_do_test IPSET_TOKEN(MTYPE, _do_test)
#define mtype_gc_test IPSET_TOKEN(MTYPE, _gc_test)
#define mtype_is_filled IPSET_TOKEN(MTYPE, _is_filled)
@@ -29,6 +33,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 +63,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 +78,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 +292,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 +314,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..ed99bf9 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));
};
@@ -165,11 +165,8 @@ bitmap_ip_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)
swap(ip, ip_to);
- if (ip < map->first_ip)
- return -IPSET_ERR_BITMAP_RANGE;
- }
} else if (tb[IPSET_ATTR_CIDR]) {
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
@@ -180,7 +177,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
ip_to = ip;
}
- if (ip_to > map->last_ip)
+ if (ip < map->first_ip || ip_to > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;
for (; !before(ip_to, ip); ip += map->hosts) {
@@ -222,7 +219,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 +309,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 +323,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..37a78d5 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 */
@@ -53,14 +54,17 @@ MODULE_DESCRIPTION("ip_set: protocol " __stringify(IPSET_PROTOCOL));
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
/* When the nfnl mutex or ip_set_ref_lock is held: */
-#define ip_set_dereference(p) \
- rcu_dereference_protected(p, \
+#define ip_set_dereference(inst) \
+ rcu_dereference_protected((inst)->ip_set_list, \
lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \
- lockdep_is_held(&ip_set_ref_lock))
+ lockdep_is_held(&ip_set_ref_lock) || \
+ (inst)->is_deleted)
#define ip_set(inst, id) \
- ip_set_dereference((inst)->ip_set_list)[id]
+ ip_set_dereference(inst)[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 +90,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) &&
@@ -100,14 +105,19 @@ find_set_type(const char *name, u8 family, u8 revision)
static bool
load_settype(const char *name)
{
+ if (!try_module_get(THIS_MODULE))
+ return false;
+
nfnl_unlock(NFNL_SUBSYS_IPSET);
pr_debug("try to load ip_set_%s\n", name);
if (request_module("ip_set_%s", name) < 0) {
pr_warn("Can't find ip_set type %s\n", name);
nfnl_lock(NFNL_SUBSYS_IPSET);
+ module_put(THIS_MODULE);
return false;
}
nfnl_lock(NFNL_SUBSYS_IPSET);
+ module_put(THIS_MODULE);
return true;
}
@@ -249,22 +259,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 +280,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 +362,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 +453,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 +645,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 +692,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 +717,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 +751,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 +787,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 +809,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 +884,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);
@@ -961,20 +973,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 +1045,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 +1055,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 +1091,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 +1113,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;
@@ -1144,7 +1149,7 @@ IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl,
if (!list)
goto cleanup;
/* nfnl mutex is held, both lists are valid */
- tmp = ip_set_dereference(inst->ip_set_list);
+ tmp = ip_set_dereference(inst);
memcpy(list, tmp, sizeof(struct ip_set *) * inst->ip_set_max);
rcu_assign_pointer(inst->ip_set_list, list);
/* Make sure all current packets have passed through */
@@ -1165,6 +1170,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 +1188,60 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = {
.len = IPSET_MAXNAMELEN - 1 },
};
+/* In order to return quickly when destroying a single set, it is split
+ * into two stages:
+ * - Cancel garbage collector
+ * - Destroy the set itself via call_rcu()
+ */
+
static void
-ip_set_destroy_set(struct ip_set *set)
+ip_set_destroy_set_rcu(struct rcu_head *head)
{
- pr_debug("set: %s\n", set->name);
+ struct ip_set *set = container_of(head, struct ip_set, rcu);
- /* Must call it without holding any lock */
set->variant->destroy(set);
module_put(set->type->me);
kfree(set);
}
+static void
+_destroy_all_sets(struct ip_set_net *inst)
+{
+ struct ip_set *set;
+ ip_set_id_t i;
+ bool need_wait = false;
+
+ /* First cancel gc's: set:list sets are flushed as well */
+ for (i = 0; i < inst->ip_set_max; i++) {
+ set = ip_set(inst, i);
+ if (set) {
+ set->variant->cancel_gc(set);
+ if (set->type->features & IPSET_TYPE_NAME)
+ need_wait = true;
+ }
+ }
+ /* Must wait for flush to be really finished */
+ if (need_wait)
+ rcu_barrier();
+ for (i = 0; i < inst->ip_set_max; i++) {
+ set = ip_set(inst, i);
+ if (set) {
+ ip_set(inst, i) = NULL;
+ set->variant->destroy(set);
+ module_put(set->type->me);
+ kfree(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,21 +1249,18 @@ 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
- * ip_set_put|get_nfnl_* functions, that way we
+ * ip_set_nfnl_get_* functions, that way we
* can safely check references here.
*
* list:set timer can only decrement the reference
* 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]) {
+ 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)) {
@@ -1231,29 +1270,34 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl,
}
inst->is_destroyed = true;
read_unlock_bh(&ip_set_ref_lock);
- for (i = 0; i < inst->ip_set_max; i++) {
- s = ip_set(inst, i);
- if (s) {
- ip_set(inst, i) = NULL;
- ip_set_destroy_set(s);
- }
- }
+ _destroy_all_sets(inst);
/* 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);
+ /* Must cancel garbage collectors */
+ s->variant->cancel_gc(s);
+ if (features & IPSET_TYPE_NAME) {
+ /* Must wait for flush to be really finished */
+ rcu_barrier();
+ }
+ call_rcu(&s->rcu, ip_set_destroy_set_rcu);
}
return 0;
out:
@@ -1268,18 +1312,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 +1363,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 +1395,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 +1415,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 +1453,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 +1537,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 +1586,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 +1608,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 +1695,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 +1746,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 +1786,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 +1795,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 +1829,13 @@ 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 +1850,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 +1858,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 +1894,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 +1905,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 +1918,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 +1941,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 +1965,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 +1980,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 +2000,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 +2012,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 +2034,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 +2058,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 +2071,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 +2091,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 +2104,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 +2114,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 +2129,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 +2150,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 +2160,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 +2178,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 +2202,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 +2211,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 +2223,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,
},
@@ -2423,24 +2498,19 @@ err_alloc:
}
static void __net_exit
-ip_set_net_exit(struct net *net)
+ip_set_net_pre_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);
+static void __net_exit
+ip_set_net_exit(struct net *net)
+{
+ struct ip_set_net *inst = ip_set_pernet(net);
+
+ _destroy_all_sets(inst);
kvfree(rcu_dereference_protected(inst->ip_set_list, 1));
#ifndef HAVE_NET_OPS_ID
kvfree(inst);
@@ -2449,6 +2519,7 @@ ip_set_net_exit(struct net *net)
static struct pernet_operations ip_set_net_ops = {
.init = ip_set_net_init,
+ .pre_exit = ip_set_net_pre_exit,
.exit = ip_set_net_exit,
#ifdef HAVE_NET_OPS_ID
.id = &ip_set_net_id,
@@ -2505,8 +2576,11 @@ ip_set_fini(void)
{
nf_unregister_sockopt(&so_set);
nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
-
UNREGISTER_PERNET_SUBSYS(&ip_set_net_ops);
+
+ /* Wait for call_rcu() in destroy */
+ rcu_barrier();
+
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..c37d09b 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/kernel/net/netfilter/ipset/ip_set_hash_gen.h
@@ -6,15 +6,26 @@
#define _IP_SET_HASH_GEN_H
#include <linux/rcupdate.h>
+#ifdef HAVE_RCUPDATE_WAIT_H
+#include <linux/rcupdate_wait.h>
+#endif
#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 +41,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 +55,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) / jhash_size(HTABLE_REGION_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 +111,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 +159,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 +217,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 +262,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 +293,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 +339,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 +348,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 +378,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 +402,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 +435,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 +444,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 +453,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 +474,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 +483,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 +493,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 +514,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 +626,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 +634,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 +644,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 +790,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 +847,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 +903,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 +994,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 +1042,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 +1069,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 +1077,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 +1122,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 +1131,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 +1226,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 +1258,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 +1270,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 +1288,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 +1336,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 +1386,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 +1452,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 +1466,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 +1507,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,13 +1514,40 @@ 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
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
- if (hashsize < IPSET_MIMINAL_HASHSIZE)
- hashsize = IPSET_MIMINAL_HASHSIZE;
+ if (hashsize < IPSET_MINIMAL_HASHSIZE)
+ hashsize = IPSET_MINIMAL_HASHSIZE;
}
if (tb[IPSET_ATTR_MAXELEM])
@@ -1286,7 +1558,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 +1573,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 +1631,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..293d095 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 */
@@ -138,10 +139,15 @@ hash_netiface4_data_next(struct hash_netiface4_elem *next,
#include "ip_set_hash_gen.h"
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+#ifdef HAVE_NF_BRIDGE_GET_PYSINDEV_NET
+static const char *get_physindev_name(const struct sk_buff *skb, struct net *net)
+{
+ struct net_device *dev = nf_bridge_get_physindev(skb, net);
+#else
static const char *get_physindev_name(const struct sk_buff *skb)
{
struct net_device *dev = nf_bridge_get_physindev(skb);
-
+#endif
return dev ? dev->name : NULL;
}
@@ -177,16 +183,21 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+#ifdef HAVE_NF_BRIDGE_GET_PYSINDEV_NET
+ const char *eiface = SRCDIR ? get_physindev_name(skb, xt_net(par)) :
+ get_physoutdev_name(skb);
+#else
const char *eiface = SRCDIR ? get_physindev_name(skb) :
get_physoutdev_name(skb);
+#endif
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 +213,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 +237,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 +271,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);
@@ -390,16 +406,21 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+#ifdef HAVE_NF_BRIDGE_GET_PYSINDEV_NET
+ const char *eiface = SRCDIR ? get_physindev_name(skb, xt_net(par)) :
+ get_physoutdev_name(skb);
+#else
const char *eiface = SRCDIR ? get_physindev_name(skb) :
get_physoutdev_name(skb);
+#endif
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 +464,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 +492,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..0162e1d 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)
@@ -82,7 +82,7 @@ list_set_kadd(struct ip_set *set, const struct sk_buff *skb,
struct set_elem *e;
int ret;
- list_for_each_entry(e, &map->members, list) {
+ list_for_each_entry_rcu(e, &map->members, list) {
if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, set)))
continue;
@@ -102,7 +102,7 @@ list_set_kdel(struct ip_set *set, const struct sk_buff *skb,
struct set_elem *e;
int ret;
- list_for_each_entry(e, &map->members, list) {
+ list_for_each_entry_rcu(e, &map->members, list) {
if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, set)))
continue;
@@ -191,9 +191,10 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext,
struct list_set *map = set->data;
struct set_adt_elem *d = value;
struct set_elem *e, *next, *prev = NULL;
- int ret;
+ int ret = 0;
- list_for_each_entry(e, &map->members, list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(e, &map->members, list) {
if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, set)))
continue;
@@ -204,6 +205,7 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext,
if (d->before == 0) {
ret = 1;
+ goto out;
} else if (d->before > 0) {
next = list_next_entry(e, list);
ret = !list_is_last(&e->list, &map->members) &&
@@ -211,9 +213,11 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext,
} else {
ret = prev && prev->id == d->refid;
}
- return ret;
+ goto out;
}
- return 0;
+out:
+ rcu_read_unlock();
+ return ret;
}
static void
@@ -242,7 +246,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
/* Find where to add the new entry */
n = prev = next = NULL;
- list_for_each_entry(e, &map->members, list) {
+ list_for_each_entry_rcu(e, &map->members, list) {
if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, set)))
continue;
@@ -319,9 +323,9 @@ list_set_udel(struct ip_set *set, void *value, const struct ip_set_ext *ext,
{
struct list_set *map = set->data;
struct set_adt_elem *d = value;
- struct set_elem *e, *next, *prev = NULL;
+ struct set_elem *e, *n, *next, *prev = NULL;
- list_for_each_entry(e, &map->members, list) {
+ list_for_each_entry_safe(e, n, &map->members, list) {
if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, set)))
continue;
@@ -427,17 +431,8 @@ static void
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);
- ip_set_ext_destroy(set, e);
- kfree(e);
- }
+ WARN_ON_ONCE(!list_empty(&map->members));
kfree(map);
set->data = NULL;
@@ -548,6 +543,18 @@ 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);
+
+ /* Flush list to drop references to other ipsets */
+ list_set_flush(set);
+}
+
static const struct ip_set_type_variant set_variant = {
.kadt = list_set_kadt,
.uadt = list_set_uadt,
@@ -561,6 +568,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
@@ -607,6 +615,10 @@ init_list_set(struct net *net, struct ip_set *set, u32 size)
return true;
}
+#ifdef HAVE_LOCKDEP_SET_CLASS
+static struct lock_class_key list_set_lockdep_key;
+#endif
+
static int
list_set_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
u32 flags)
@@ -623,6 +635,9 @@ list_set_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
if (size < IP_SET_LIST_MIN_SIZE)
size = IP_SET_LIST_MIN_SIZE;
+#ifdef HAVE_LOCKDEP_SET_CLASS
+ lockdep_set_class(&set->lock, &list_set_lockdep_key);
+#endif
set->variant = &set_variant;
set->dsize = ip_set_elem_len(set, tb, sizeof(struct set_elem),
__alignof__(struct set_elem));
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
diff --git a/lib/args.c b/lib/args.c
index c25bb80..e47105c 100644
--- a/lib/args.c
+++ b/lib/args.c
@@ -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 *
diff --git a/lib/data.c b/lib/data.c
index f28d1d3..64cad7a 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -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,10 @@ ipset_strlcpy(char *dst, const char *src, size_t len)
assert(dst);
assert(src);
- strncpy(dst, src, len);
+ if (strlen(src) < len)
+ len = strlen(src) + 1;
+
+ memcpy(dst, src, len);
dst[len - 1] = '\0';
}
@@ -286,8 +290,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 +305,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 +508,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 +518,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 +606,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 +621,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 +638,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..3bf1c5f 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\".",
@@ -328,9 +343,9 @@ ipset_shift_argv(int *argc, char *argv[], int from)
assert(*argc >= from + 1);
- for (i = from + 1; i <= *argc; i++)
+ for (i = from + 1; i < *argc; i++)
argv[i-1] = argv[i];
- (*argc)--;
+ argv[--(*argc)] = NULL;
return;
}
@@ -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;
diff --git a/lib/mnl.c b/lib/mnl.c
index cc5124d..d1f5ba5 100644
--- a/lib/mnl.c
+++ b/lib/mnl.c
@@ -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..a95ee4f 100644
--- a/lib/print.c
+++ b/lib/print.c
@@ -261,11 +261,12 @@ ipset_print_ip(char *buf, unsigned int len,
uint8_t family, cidr;
int flags, size, offset = 0;
enum ipset_opt cidropt;
+ const char *quoted = env & IPSET_ENV_QUOTED ? "\"" : "";
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);
@@ -277,20 +278,26 @@ ipset_print_ip(char *buf, unsigned int len,
cidr = family == NFPROTO_IPV6 ? 128 : 32;
flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
+ size = snprintf(buf, len, "%s", quoted);
+ SNPRINTF_FAILURE(size, len, offset);
+
ip = ipset_data_get(data, opt);
assert(ip);
if (family == NFPROTO_IPV4)
- size = snprintf_ipv4(buf, len, flags, ip, cidr);
+ size = snprintf_ipv4(buf + offset, len, flags, ip, cidr);
else if (family == NFPROTO_IPV6)
- size = snprintf_ipv6(buf, len, flags, ip, cidr);
+ size = snprintf_ipv6(buf + offset, len, flags, ip, cidr);
else
return -1;
D("size %i, len %u", size, len);
SNPRINTF_FAILURE(size, len, offset);
D("len: %u, offset %u", len, offset);
- if (!ipset_data_test(data, IPSET_OPT_IP_TO))
+ if (!ipset_data_test(data, IPSET_OPT_IP_TO)) {
+ size = snprintf(buf + offset, len, "%s", quoted);
+ SNPRINTF_FAILURE(size, len, offset);
return offset;
+ }
size = snprintf(buf + offset, len, "%s", IPSET_RANGE_SEPARATOR);
SNPRINTF_FAILURE(size, len, offset);
@@ -304,6 +311,10 @@ ipset_print_ip(char *buf, unsigned int len,
return -1;
SNPRINTF_FAILURE(size, len, offset);
+
+ size = snprintf(buf + offset, len, "%s", quoted);
+ SNPRINTF_FAILURE(size, len, offset);
+
return offset;
}
@@ -397,6 +408,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
@@ -462,10 +518,12 @@ int
ipset_print_port(char *buf, unsigned int len,
const struct ipset_data *data,
enum ipset_opt opt ASSERT_UNUSED,
- uint8_t env UNUSED)
+ uint8_t env)
{
const uint16_t *port;
int size, offset = 0;
+ const char *quoted = ipset_data_test(data, IPSET_OPT_PORT_TO) &&
+ env & IPSET_ENV_QUOTED ? "\"" : "";
assert(buf);
assert(len > 0);
@@ -477,14 +535,14 @@ ipset_print_port(char *buf, unsigned int len,
port = ipset_data_get(data, IPSET_OPT_PORT);
assert(port);
- size = snprintf(buf, len, "%u", *port);
+ size = snprintf(buf, len, "%s%u", quoted, *port);
SNPRINTF_FAILURE(size, len, offset);
if (ipset_data_test(data, IPSET_OPT_PORT_TO)) {
port = ipset_data_get(data, IPSET_OPT_PORT_TO);
size = snprintf(buf + offset, len,
- "%s%u",
- IPSET_RANGE_SEPARATOR, *port);
+ "%s%u%s",
+ IPSET_RANGE_SEPARATOR, *port, quoted);
SNPRINTF_FAILURE(size, len, offset);
}
@@ -932,6 +990,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 +999,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..a8f99a7 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[] = {
@@ -849,7 +853,7 @@ safe_dprintf(struct ipset_session *session, ipset_printfn fn,
}
static int
-list_adt(struct ipset_session *session, struct nlattr *nla[])
+list_adt(struct ipset_session *session, struct nlattr *nla[], const bool first_in_list)
{
const struct ipset_data *data = session->data;
const struct ipset_type *type;
@@ -890,6 +894,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 (!session->sort && !first_in_list)
+ safe_snprintf(session, ",");
+
+ safe_snprintf(session, "\n {\n \"elem\" : \"");
+ break;
case IPSET_LIST_PLAIN:
default:
break;
@@ -898,6 +909,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 +938,20 @@ 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;
+ } else if (arg->opt == IPSET_OPT_ADT_COMMENT) {
+ safe_snprintf(session, ",\n \"%s\" : ", arg->name[0]);
+ safe_dprintf(session, arg->print, arg->opt);
+ break;
+ }
+ safe_snprintf(session, ",\n \"%s\" : \"", arg->name[0]);
+ safe_dprintf(session, arg->print, arg->opt);
+ safe_snprintf(session, "\"");
+ break;
default:
break;
}
@@ -932,6 +959,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");
@@ -1003,6 +1032,19 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
ipset_data_setname(data),
type->name, type->revision);
break;
+ case IPSET_LIST_JSON:
+ ipset_envopt_set(session, IPSET_ENV_QUOTED);
+ if (session->saved_setname[0] != '\0')
+ safe_snprintf(session, ",\n");
+ 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 +1080,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 +1133,22 @@ 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\" : [");
+ ipset_envopt_unset(session, IPSET_ENV_QUOTED);
+ break;
default:
break;
}
@@ -1177,7 +1251,8 @@ print_set_done(struct ipset_session *session, bool callback_done)
D("called for %s", session->saved_setname[0] == '\0'
? "NONE" : session->saved_setname);
if (session->sort) {
- struct ipset_sorted *pos;
+ struct ipset_sorted *pos, *next;
+ const char *comma = session->mode == IPSET_LIST_JSON ? "," : "";
int ret;
/* Print set header */
@@ -1189,9 +1264,15 @@ print_set_done(struct ipset_session *session, bool callback_done)
list_sort(session, &session->sorted, bystrcmp);
list_for_each_entry(pos, &session->sorted, list) {
+ /* In JSON output we must not emit the last comma */
+ if (session->mode == IPSET_LIST_JSON) {
+ next = list_entry(pos->list.next, typeof(*pos), list);
+ if (&next->list == &session->sorted)
+ comma = "";
+ }
ret = session->print_outfn(session, session->p,
- "%s",
- session->outbuf + pos->offset);
+ "%s%s",
+ session->outbuf + pos->offset, comma);
if (ret < 0)
return MNL_CB_ERROR;
}
@@ -1210,11 +1291,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;
}
@@ -1241,9 +1335,15 @@ 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 (session->saved_setname[0] != '\0')
+ safe_snprintf(session, ",\n");
+ safe_snprintf(session, " { \"name\" : \"%s\" }",
+ ipset_data_setname(data));
+ } else
safe_snprintf(session, "%s\n",
ipset_data_setname(data));
+ strcpy(session->saved_setname, ipset_data_setname(data));
return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_OK;
}
@@ -1298,6 +1398,7 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
if (nla[IPSET_ATTR_ADT] != NULL) {
struct nlattr *tb, *adt[IPSET_ATTR_ADT_MAX+1];
+ bool first_in_list = true;
mnl_attr_for_each_nested(tb, nla[IPSET_ATTR_ADT]) {
D("ADT attributes for %s", ipset_data_setname(data));
@@ -1308,8 +1409,9 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
FAILURE("Broken %s kernel message: "
"cannot validate ADT attributes!",
cmd2name[cmd]);
- if (list_adt(session, adt) != MNL_CB_OK)
+ if (list_adt(session, adt, first_in_list) != MNL_CB_OK)
return MNL_CB_ERROR;
+ first_in_list = false;
}
if (session->sort)
return MNL_CB_OK;
@@ -1721,6 +1823,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 +2088,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 +2113,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 +2133,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 +2146,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 +2293,24 @@ 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;
+ 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 */
+ 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/m4/ax_cflags_gcc_option.m4 b/m4/ax_cflags_gcc_option.m4
index 8cffe5d..b173ed4 100644
--- a/m4/ax_cflags_gcc_option.m4
+++ b/m4/ax_cflags_gcc_option.m4
@@ -80,15 +80,14 @@ AS_VAR_PUSHDEF([VAR],[ax_cv_cflags_gcc_option_$2])dnl
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)],
VAR,[AS_VAR_SET([VAR],["no, unknown"])
AC_LANG_SAVE
- AC_LANG_C
+ AC_LANG([C])
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "-pedantic -Werror % m4_ifval($2,$2,-option)" dnl GCC
"-pedantic % m4_ifval($2,$2,-option) %% no, obsolete" dnl new GCC
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
- AC_TRY_COMPILE([],[return 0;],
- [AS_VAR_SET([VAR],[`echo $ac_arg | sed -e 's,.*% *,,'`]); break])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[return 0;]])],[AS_VAR_SET([VAR],[`echo $ac_arg | sed -e 's,.*% *,,'`]); break],[])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
@@ -117,15 +116,14 @@ AS_VAR_PUSHDEF([VAR],[ax_cv_cxxflags_gcc_option_$2])dnl
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)],
VAR,[AS_VAR_SET([VAR],["no, unknown"])
AC_LANG_SAVE
- AC_LANG_CPLUSPLUS
+ AC_LANG([C++])
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "-pedantic -Werror % m4_ifval($2,$2,-option)" dnl GCC
"-pedantic % m4_ifval($2,$2,-option) %% no, obsolete" dnl new GCC
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
- AC_TRY_COMPILE([],[return 0;],
- [AS_VAR_SET([VAR],[`echo $ac_arg | sed -e 's,.*% *,,'`]); break])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[return 0;]])],[AS_VAR_SET([VAR],[`echo $ac_arg | sed -e 's,.*% *,,'`]); break],[])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
@@ -153,15 +151,14 @@ AS_VAR_PUSHDEF([VAR],[ax_cv_cflags_gcc_option_$1])dnl
AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)],
VAR,[AS_VAR_SET([VAR],["no, unknown"])
AC_LANG_SAVE
- AC_LANG_C
+ AC_LANG([C])
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "-pedantic -Werror % m4_ifval($1,$1,-option)" dnl GCC
"-pedantic % m4_ifval($1,$1,-option) %% no, obsolete" dnl new GCC
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
- AC_TRY_COMPILE([],[return 0;],
- [AS_VAR_SET([VAR],[`echo $ac_arg | sed -e 's,.*% *,,'`]); break])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[return 0;]])],[AS_VAR_SET([VAR],[`echo $ac_arg | sed -e 's,.*% *,,'`]); break],[])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
@@ -190,15 +187,14 @@ AS_VAR_PUSHDEF([VAR],[ax_cv_cxxflags_gcc_option_$1])dnl
AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)],
VAR,[AS_VAR_SET([VAR],["no, unknown"])
AC_LANG_SAVE
- AC_LANG_CPLUSPLUS
+ AC_LANG([C++])
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "-pedantic -Werror % m4_ifval($1,$1,-option)" dnl GCC
"-pedantic % m4_ifval($1,$1,-option) %% no, obsolete" dnl new GCC
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
- AC_TRY_COMPILE([],[return 0;],
- [AS_VAR_SET([VAR],[`echo $ac_arg | sed -e 's,.*% *,,'`]); break])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[return 0;]])],[AS_VAR_SET([VAR],[`echo $ac_arg | sed -e 's,.*% *,,'`]); break],[])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
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..39912ee 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.
@@ -251,17 +251,13 @@ In the case of host names the DNS resolver is called internally
by \fBipset\fR but if it returns multiple IP addresses, only the
first one is used.
-The \fBbitmap\fR and \fBlist\fR types use a fixed sized storage. The \fBhash\fR
-types use a hash to store the elements. In order to avoid clashes in the hash,
+The \fBbitmap\fR and \fBlist\fR types use a fixed sized storage.
+
+The \fBhash\fR types use a hash to store the elements. In order to avoid clashes in the hash,
a limited number of chaining, and if that is exhausted, the doubling of the hash size
-is performed when adding entries by the
-\fBipset\fR
-command. When entries added by the
-\fBSET\fR
-target of
-\fBiptables/ip6tables\fR,
-then the hash size is fixed and the set won't be duplicated, even if the new
-entry cannot be added to the set.
+is performed when adding entries by the \fBipset\fR command. When entries added by the
+\fBSET\fR target of \fBiptables/ip6tables\fR, then the hash size is fixed and the
+hash won't be duplicated, even if the new entry cannot be added to the set.
.SH "GENERIC CREATE AND ADD OPTIONS"
.SS timeout
All set types supports the optional \fBtimeout\fR
@@ -333,23 +329,48 @@ 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 maxelem
+This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets.
+It defines the maximal number of elements which can be stored in the set, default 65536.
+It is the hard limit for the possible elements in a hash type of set. If
+the set is full (i.e. it contains \fBmaxelem\fR number of elements), new
+elements cannot be added neither by the \fBipset\fR command nor by the
+\fBSET\fR target.
+Example:
+.IP
+ipset create test hash:ip maxelem 2048
.PP
.SS hashsize
This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets.
It defines the initial hash size for the set, default is 1024. The hash size must be a power
of two, the kernel automatically rounds up non power of two hash sizes to the first
-correct value.
-Example:
+correct value. If you intend to use a set so that new elements are added by the \fBipset\fR
+command only, then you can start with a default/small \fBhashsize\fR value and the hash
+will grow automatically as you add new entries until \fBmaxelem\fR values
+are added. If you want to use a set so that new
+elements are added by the \fBSET\fR target, then choose the maximal \fBhashsize\fR
+value with respect of the \fBbucketsize\fR parameter so that number of planned elements
+will fit into the hash.
+.IP
+hashsize == maxelem / bucketsize
+.PP
+is the smallest possible approximation but a larger hash size is better to
+make sure all elements can really be stored in the set. Example:
.IP
ipset create test hash:ip hashsize 1536
.PP
-.SS maxelem
+.SS bucketsize
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 specifies the maximal number of elements which can be stored in a hash
+bucket. Possible values are any even number between 2-12 and the default is
+12. Setting the value lower forces ipset to create larger hashes when adding
+new elements to a set by the \fBipset\fR command which consumes more memory
+but gives more speed at matching in the set.
Example:
.IP
-ipset create test hash:ip maxelem 2048.
+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 +535,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 +560,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 +589,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 +611,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 +662,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 +694,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 +727,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 +767,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 +796,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 +846,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 +878,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 +923,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
@@ -888,7 +936,7 @@ The \fBhash:ip,mark\fR set type uses a hash to store IP address and packet mark
Optional \fBcreate\fR options:
.TP
\fBmarkmask\fR \fIvalue\fR
-Allows you to set bits you are interested in the packet mark. This values is then used to perform bitwise AND operation for every mark added.
+Allows you to set bits you are interested in the packet mark. This value is then used to perform bitwise AND operation for every mark added.
markmask can be any value between 1 and 4294967295, by default all 32 bits are set.
.PP
The
@@ -913,7 +961,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 +1008,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..d7733bf 100644
--- a/src/ipset.c
+++ b/src/ipset.c
@@ -6,12 +6,16 @@
* 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 */
+#include <libgen.h>
int
main(int argc, char *argv[])
@@ -29,7 +33,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);
diff --git a/src/ui.c b/src/ui.c
index 55433b8..5b4a1d7 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -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..abb69b8 100755
--- a/tests/cidr.sh
+++ b/tests/cidr.sh
@@ -35,7 +35,32 @@ NETS="0.0.0.0/1
255.255.255.252/31
255.255.255.254/32"
-ipset="../src/ipset"
+ipset="${IPSET_BIN:-../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|HostMin):/{print $2; exit}'
+ }
+ 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}
+ /^Address:/{out=$2}
+ END{print out}'
+ }
+else
+ echo "need either netmask or ipcalc tools"
+ exit 1
+fi
case "$1" in
net)
@@ -46,9 +71,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 +92,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/resize.sh b/tests/resize.sh
index 19b93fb..9069b49 100755
--- a/tests/resize.sh
+++ b/tests/resize.sh
@@ -9,6 +9,6 @@ set -e
$ipset n resize-test hash:ip hashsize 64
for x in `seq 1 32`; do
for y in `seq 1 255`; do
- $ipset a resize-test 192.168.$x.$y
- done
+ echo "a resize-test 192.168.$x.$y"
+ done | $ipset restore
done
diff --git a/tests/resizec.sh b/tests/resizec.sh
index 28d6747..781acf7 100755
--- a/tests/resizec.sh
+++ b/tests/resizec.sh
@@ -25,65 +25,65 @@ case "$2" in
$ipset n test hash:ip $1 hashsize 64 comment
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y comment "text $ip$x$sep$y"
+ echo "a test $ip$x$sep$y comment \"text $ip$x$sep$y\""
done
- done
+ done | $ipset restore
;;
ipport)
$ipset n test hash:ip,port $1 hashsize 64 comment
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y,1023 "text $ip$x$sep$y,1023"
+ echo "a test $ip$x$sep$y,1023 \"text $ip$x$sep$y,1023\""
done
- done
+ done | $ipset restore
;;
ipportip)
$ipset n test hash:ip,port,ip $1 hashsize 64 comment
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y,1023,$ip2 comment "text $ip$x$sep$y,1023,$ip2"
+ echo "a test $ip$x$sep$y,1023,$ip2 comment \"text $ip$x$sep$y,1023,$ip2\""
done
- done
+ done | $ipset restore
;;
ipportnet)
$ipset n test hash:ip,port,net $1 hashsize 64 comment
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y,1023,$ip2/$net comment "text $ip$x$sep$y,1023,$ip2/$net"
+ echo "a test $ip$x$sep$y,1023,$ip2/$net comment \"text $ip$x$sep$y,1023,$ip2/$net\""
done
- done
+ done | $ipset restore
;;
net)
$ipset n test hash:net $1 hashsize 64 comment
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net comment "text $ip$x$sep$y/$net"
+ echo "a test $ip$x$sep$y/$net comment \"text $ip$x$sep$y/$net\""
done
- done
+ done | $ipset restore
;;
netnet)
$ipset n test hash:net,net $1 hashsize 64 comment
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net,$ip$y$sep$x/$net comment "text $ip$x$sep$y/$net,$ip$y$sep$x/$net"
+ echo "a test $ip$x$sep$y/$net,$ip$y$sep$x/$net comment \"text $ip$x$sep$y/$net,$ip$y$sep$x/$net\""
done
- done
+ done | $ipset restore
;;
netport)
$ipset n test hash:net,port $1 hashsize 64 comment
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net,1023 comment "text $ip$x$sep$y/$net,1023"
+ echo "a test $ip$x$sep$y/$net,1023 comment \"text $ip$x$sep$y/$net,1023\""
done
- done
+ done | $ipset restore
;;
netiface)
$ipset n test hash:net,iface $1 hashsize 64 comment
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net,eth0 comment "text $ip$x$sep$y/$net,eth0"
+ echo "$ipset a test $ip$x$sep$y/$net,eth0 comment \"text $ip$x$sep$y/$net,eth0\""
done
- done
+ done | $ipset restore
;;
esac
$ipset l test | grep ^$ip | while read x y z; do
diff --git a/tests/resizen.sh b/tests/resizen.sh
index 9322bd2..13221f7 100755
--- a/tests/resizen.sh
+++ b/tests/resizen.sh
@@ -25,80 +25,79 @@ case "$2" in
$ipset n test hash:ip,port,net $1 hashsize 64
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y,1023,$ip2/$net nomatch
+ echo "a test $ip$x$sep$y,1023,$ip2/$net nomatch"
done
- done
+ done | $ipset restore
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset t test $ip$x$sep$y,1023,$ip2/$net nomatch 2>/dev/null
+ echo "t test $ip$x$sep$y,1023,$ip2/$net nomatch"
done
- done
+ done | $ipset restore 2>/dev/null
;;
netportnet)
$ipset n test hash:net,port,net $1 hashsize 64
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y,1023,$ip2/$net nomatch
+ echo "a test $ip$x$sep$y,1023,$ip2/$net nomatch"
done
- done
+ done | $ipset restore
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset t test $ip$x$sep$y,1023,$ip2/$net nomatch 2>/dev/null
+ echo "t test $ip$x$sep$y,1023,$ip2/$net nomatch"
done
- done
+ done | $ipset restore 2>/dev/null
;;
net)
$ipset n test hash:net $1 hashsize 64
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net nomatch
+ echo "a test $ip$x$sep$y/$net nomatch"
done
- done
+ done | $ipset restore
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset t test $ip$x$sep$y/$net nomatch 2>/dev/null
+ echo "t test $ip$x$sep$y/$net nomatch"
done
- done
+ done | $ipset restore 2>/dev/null
;;
netnet)
$ipset n test hash:net,net $1 hashsize 64
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net,$ip$y$sep$x/$net nomatch
+ echo "a test $ip$x$sep$y/$net,$ip$y$sep$x/$net nomatch"
done
- done
+ done | $ipset restore
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset t test $ip$x$sep$y/$net,$ip$y$sep$x/$net nomatch \
- 2>/dev/null
+ echo "t test $ip$x$sep$y/$net,$ip$y$sep$x/$net nomatch"
done
- done
+ done | $ipset restore 2>/dev/null
;;
netport)
$ipset n test hash:net,port $1 hashsize 64
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net,1023 nomatch
+ echo "a test $ip$x$sep$y/$net,1023 nomatch"
done
- done
+ done | $ipset restore
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset t test $ip$x$sep$y/$net,1023 nomatch 2>/dev/null
+ echo "t test $ip$x$sep$y/$net,1023 nomatch"
done
- done
+ done | $ipset restore 2>/dev/null
;;
netiface)
$ipset n test hash:net,iface $1 hashsize 64
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net,eth0 nomatch
+ echo "a test $ip$x$sep$y/$net,eth0 nomatch"
done
- done
+ done | $ipset restore
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset t test $ip$x$sep$y/$net,eth0 nomatch 2>/dev/null
+ echo "t test $ip$x$sep$y/$net,eth0 nomatch"
done
- done
+ done | $ipset restore 2>/dev/null
;;
esac
$ipset x
diff --git a/tests/resizet.sh b/tests/resizet.sh
index eed4abf..e8fdd73 100755
--- a/tests/resizet.sh
+++ b/tests/resizet.sh
@@ -25,81 +25,81 @@ case "$2" in
$ipset n test hash:ip $1 hashsize 64 timeout 100
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y
+ echo "a test $ip$x$sep$y"
done
- done
+ done | $ipset restore
;;
ipmark)
$ipset n test hash:ip,mark $1 hashsize 64 timeout 100
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y,1023
+ echo "a test $ip$x$sep$y,1023"
done
- done
+ done | $ipset restore
;;
ipport)
$ipset n test hash:ip,port $1 hashsize 64 timeout 100
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y,1023
+ echo "a test $ip$x$sep$y,1023"
done
- done
+ done | $ipset restore
;;
ipportip)
$ipset n test hash:ip,port,ip $1 hashsize 64 timeout 100
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y,1023,$ip2
+ echo "a test $ip$x$sep$y,1023,$ip2"
done
- done
+ done | $ipset restore
;;
ipportnet)
$ipset n test hash:ip,port,net $1 hashsize 64 timeout 100
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y,1023,$ip2/$net
+ echo "a test $ip$x$sep$y,1023,$ip2/$net"
done
- done
+ done | $ipset restore
;;
netportnet)
$ipset n test hash:net,port,net $1 hashsize 64 timeout 100
for x in `seq 0 16`; do
for y in `seq 0 128`; do
- $ipset a test $ip$x$sep$y/$net,1023,$ip$y$sep$x/$net
+ echo "a test $ip$x$sep$y/$net,1023,$ip$y$sep$x/$net"
done
- done
+ done | $ipset restore
;;
net)
$ipset n test hash:net $1 hashsize 64 timeout 100
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net
+ echo "a test $ip$x$sep$y/$net"
done
- done
+ done | $ipset restore
;;
netnet)
$ipset n test hash:net,net $1 hashsize 64 timeout 100
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net,$ip$y$sep$x/$net
+ echo "a test $ip$x$sep$y/$net,$ip$y$sep$x/$net"
done
- done
+ done | $ipset restore
;;
netport)
$ipset n test hash:net,port $1 hashsize 64 timeout 100
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net,1023
+ echo "a test $ip$x$sep$y/$net,1023"
done
- done
+ done | $ipset restore
;;
netiface)
$ipset n test hash:net,iface $1 hashsize 64 timeout 100
for x in `seq 0 16`; do
for y in `seq 0 255`; do
- $ipset a test $ip$x$sep$y/$net,eth0
+ echo "a test $ip$x$sep$y/$net,eth0"
done
- done
+ done | $ipset restore
;;
esac
$ipset l test | grep ^$ip | while read x y z; do
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/runtest.sh b/tests/runtest.sh
index 7afa1dd..fc4fd3c 100755
--- a/tests/runtest.sh
+++ b/tests/runtest.sh
@@ -76,6 +76,7 @@ fi
# Make sure the scripts are executable
chmod a+x check_* *.sh
+failcount=0
for types in $tests; do
$ipset -X test >/dev/null 2>&1
if [ -f $types ]; then
@@ -116,7 +117,8 @@ for types in $tests; do
echo "FAILED"
echo "Failed test: $cmd"
cat .foo.err
- exit 1
+ let "failcount++"
+ break
fi
# sleep 1
done < $filename
@@ -136,5 +138,9 @@ for x in $tests; do
done
rmmod ip_set >/dev/null 2>&1
rm -f .foo*
-echo "All tests are passed"
-
+if [ "$failcount" -eq 0 ]; then
+ echo "All tests are passed"
+else
+ echo "$failcount tests have failed"
+ exit 1
+fi
diff --git a/tests/setlist.t b/tests/setlist.t
index 7d14ec8..a2780d7 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
@@ -211,4 +211,6 @@ skip which sendip >/dev/null
0 ipset f
# Counters and timeout: destroy sets
0 ipset x
+# Use namespace and test list:set with comments (takes longer)
+0 ./setlist_ns.sh
# eof
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_ns.sh b/tests/setlist_ns.sh
new file mode 100755
index 0000000..9e47d65
--- /dev/null
+++ b/tests/setlist_ns.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+set -e
+
+CMD=$(cat <<EOF
+for x in \$(seq 0 127); do
+ echo "create h\$x hash:ip"
+ echo "create l\$x list:set timeout 10 comment"
+done | ipset restore
+for x in \$(seq 0 127); do
+ for y in \$(seq 0 127); do
+ echo "add l\$x h\$y timeout 1000 comment \"l\$x h\$y\""
+ done
+done | ipset restore
+# Wait for GC
+sleep 15
+EOF
+)
+
+for x in seq 0 123; do
+ unshare -Urn bash -c "$CMD"
+done
diff --git a/tests/setlist_resize.sh b/tests/setlist_resize.sh
index 3255656..acb33e3 100755
--- a/tests/setlist_resize.sh
+++ b/tests/setlist_resize.sh
@@ -1,26 +1,33 @@
#!/bin/sh
+set -e
# set -x
+# exec > setlist.res
+# exec 2>&1
ipset=${IPSET_BIN:-../src/ipset}
loop=8
-for x in ip_set_list_set ip_set_hash_netiface ip_set_hash_ipportnet \
- ip_set_hash_netport ip_set_hash_net ip_set_hash_ipportip \
- ip_set_hash_ipport ip_set_hash_ip ip_set_hash_netnet \
- 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
+n=0
+while [ $n -le 9 ]; do
+ egrep '^(ip_set_|xt_set)' /proc/modules | while read x y; do
+ rmmod $x >/dev/null 2>&1
+ done
+ if [ "`egrep '^(ip_set_|xt_set)' /proc/modules`" ]; then
+ sleep 1s
+ else
+ n=10
+ fi
done
+rmmod ip_set >/dev/null 2>&1
create() {
n=$1
while [ $n -le 1024 ]; do
- $ipset c test$n hash:ip
+ echo "c test$n hash:ip"
n=$((n+2))
- done
+ done | $ipset restore
}
for x in `seq 1 $loop`; do
@@ -30,7 +37,23 @@ for x in `seq 1 $loop`; do
wait
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
+ # Wait for destroy to be finished and reference counts releases
+ n=0
+ ref=0
+ while [ $n -le 9 ]; do
+ ref=`lsmod|grep -w ^ip_set_hash_ip | awk '{print $3}'`
+ if [ $ref -eq 0 ]; then
+ n=10;
+ else
+ sleep 1s
+ n=$((n+1))
+ fi
+ done
+ if [ "$ref" -ne 0 ]; then
+ lsmod
+ echo $ref
+ fi
+ test "$ref" -eq 0 || exit 1
+ 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..fc95d40 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}"
+