summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--ChangeLog98
-rw-r--r--Make_global.am2
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac207
-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/ChangeLog144
-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.in209
-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/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.h18
-rw-r--r--kernel/net/netfilter/ipset/ip_set_bitmap_ip.c14
-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.c452
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_gen.h832
-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.c28
-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.c15
-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.c36
-rw-r--r--lib/debug.c5
-rw-r--r--lib/errcode.c4
-rw-r--r--lib/ipset.c608
-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.c52
-rw-r--r--lib/session.c141
-rw-r--r--src/Makefile.am8
-rw-r--r--src/ipset-translate.891
-rw-r--r--src/ipset.873
-rw-r--r--src/ipset.c9
-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.sh32
-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
-rw-r--r--tests/restore.t24
-rw-r--r--tests/restore.t.list05
-rw-r--r--tests/restore.t.list15
-rw-r--r--tests/setlist.t20
-rw-r--r--tests/setlist.t.list423
-rwxr-xr-xtests/setlist_resize.sh6
-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
211 files changed, 8485 insertions, 4779 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..30012d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,101 @@
+7.21
+ - The patch "Fix hex literals in json output" broke save mode, restore it
+ - Fix -Werror=format-extra-args warning
+ - Workaround misleading -Wstringop-truncation warning
+
+7.20
+ - Ignore *.order.cmd and *.symvers.cmd files in kernel builds
+ - Bash completion utility updated
+ - Fix json output for -name option (Mark)
+ - Fix hex literals in json output
+ - tests: increase timeout to cope with slow virtual test machine
+
+7.19
+ - build: Fix the double-prefix in pkgconfig (Sam James)
+
+7.18
+ - Add json output to list command (Thomas Oberhammer)
+ - tests: hash:ip,port.t: Replace VRRP by GRE protocol (Phil Sutter)
+ - tests: hash:ip,port.t: 'vrrp' is printed as 'carp' (Phil Sutter)
+ - tests: cidr.sh: Add ipcalc fallback (Phil Sutter)
+ - tests: xlate: Make test input valid (Phil Sutter)
+ - tests: xlate: Test built binary by default (Phil Sutter)
+ - xlate: Drop dead code (Phil Sutter)
+ - xlate: Fix for fd leak in error path (Phil Sutter)
+ - configure.ac: fix bashisms (Sam James)
+ - lib/Makefile.am: fix pkgconfig dir (Sam James)
+
+7.17
+ - Tests: When verifying comments/timeouts, make sure entries don't expire
+ - Tests: Make sure the internal batches add the correct number of elements
+ - Tests: Verify that hash:net,port,net type can handle 0/0 properly
+ - Makefile: Create LZMA-compressed dist-files (Phil Sutter)
+
+7.16
+ - Add new ipset_parse_bitmask() function to the library interface
+ - test: Make sure no more than 64 clashing elements can be added
+ to hash:net,iface sets
+ - netfilter: ipset: add tests for the new bitmask feature (Vishwanath Pai)
+ - netfilter: ipset: Update the man page to include netmask/bitmask options
+ (Vishwanath Pai)
+ - netfilter: ipset: Add bitmask support to hash:netnet (Vishwanath Pai)
+ - netfilter: ipset: Add bitmask support to hash:ipport (Vishwanath Pai)
+ - netfilter: ipset: Add bitmask support to hash:ip (Vishwanath Pai)
+ - netfilter: ipset: Add support for new bitmask parameter (Vishwanath Pai)
+ - ipset-translate: allow invoking with a path name (Quentin Armitage)
+ - Fix IPv6 sets nftables translation (Pablo Neira Ayuso)
+ - Fix typo in ipset-translate man page (Bernhard M. Wiedemann)
+
+7.14
+ - Add missing function to libipset.map and bump library version
+ (reported by Jan Engelhardt)
+
+7.13
+ - When parsing protocols by number, do not check it in /etc/protocols.
+ - Add missing hunk to patch "Allow specifying protocols by number"
+
+7.12
+ - Allow specifying protocols by number (Haw Loeung)
+ - Fix example in ipset.8 manpage discovered by Pablo Neira Ayuso.
+ - tests: add tests ipset to nftables (Pablo Neira Ayuso)
+ - add ipset to nftables translation infrastructure (Pablo Neira Ayuso)
+ - lib: Detach restore routine from parser (Pablo Neira Ayuso)
+ - lib: split parser from command execution (Pablo Neira Ayuso)
+ - Fix patch "Parse port before trying by service name"
+
+7.11
+ - Parse port before trying by service name (Haw Loeung)
+ - Silence unused-but-set-variable warnings (reported by
+ Serhey Popovych)
+ - Handle -Werror=implicit-fallthrough= in debug mode compiling
+ - ipset: fix print format warning (Neutron Soutmun)
+ - Updated utilities
+ - Argument parsing buffer overflow in ipset_parse_argv fixed
+ (reported by Marshall Whittaker)
+ -
+7.9
+ - Fix library versioning (Jan Engelhardt)
+
+7.7
+ - Expose the initval hash parameter to userspace
+ - Handle all variable header parts in helper scripts instead ot test tasks
+ - Add bucketsize parameter to all hash types
+ - Support the -exist flag with the destroy command
+
+7.6
+ - Add checking system_power_efficient_wq in the kernel source tree
+ - .gitignore: add temporary files to the list
+
+7.5
+ - configure.ac: Support building with old autoconf 2.63
+ (Serhey Popovych)
+ - configure.ac: Build on kernels without skb->vlan_proto correctly
+ (Serhey Popovych)
+ - configure.ac: Add cond_resched_rcu() checks (Serhey Popovych)
+ - configure.ac: Better match for ipv6_skip_exthdr() frag_offp
+ arg presence (Serhey Popovych)
+ - Document explicitly that protocol is not stored in bitmap:port
+
7.4
- Fix compatibility support for netlink extended ACK and add
synchronize_rcu_bh() checking
diff --git a/Make_global.am b/Make_global.am
index 673aa41..9ba6adf 100644
--- a/Make_global.am
+++ b/Make_global.am
@@ -69,7 +69,7 @@
# interface.
# curr:rev:age
-LIBVERSION = 14:0:1
+LIBVERSION = 17:0:4
AM_CPPFLAGS = $(kinclude_CFLAGS) $(all_includes) -I$(top_srcdir)/include
diff --git a/Makefile.am b/Makefile.am
index eab32ee..cc821e6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -93,6 +93,9 @@ update_includes:
kernel/include/uapi/linux/netfilter/ipset/$$x \
> include/libipset/linux_$$x; \
done
+ for x in ip_set_compiler.h; do \
+ cp kernel/include/linux/netfilter/ipset/$$x include/libipset/$x; \
+ done
update_utils:
wget -4 -O /tmp/ipset-bash-completion.tar.gz http://sourceforge.net/projects/ipset-bashcompl/files/latest/download
diff --git a/configure.ac b/configure.ac
index e3ddcce..db9e3f8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,18 +1,20 @@
dnl Boilerplate
-AC_INIT([ipset], [7.4], [kadlec@netfilter.org])
+AC_INIT([ipset], [7.21], [kadlec@netfilter.org])
AC_CONFIG_AUX_DIR([build-aux])
AC_CANONICAL_HOST
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADER([config.h])
-AM_INIT_AUTOMAKE([foreign subdir-objects tar-pax])
+AM_INIT_AUTOMAKE([foreign subdir-objects tar-pax no-dist-gzip dist-xz])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+AC_PROG_LN_S
AC_ENABLE_STATIC
LT_INIT([dlopen])
LT_CONFIG_LTDL_DIR([libltdl])
LTDL_INIT([nonrecursive])
PKG_PROG_PKG_CONFIG
+PKG_INSTALLDIR
dnl Shortcut: Linux supported alone
case "$host" in
@@ -26,7 +28,7 @@ AC_ARG_WITH([kmod],
[Build the kernel module (default: yes)]),
[BUILDKMOD="$withval";],
[BUILDKMOD="yes";])
-AM_CONDITIONAL(WITH_KMOD, test "$BUILDKMOD" == "yes")
+AM_CONDITIONAL(WITH_KMOD, test "$BUILDKMOD" = "yes")
dnl Additional arguments
dnl Kernel build directory or source tree
@@ -75,7 +77,7 @@ if test "x$enable_bashcompl" = "xyes"; then
AC_SUBST(bashcompdir)
fi
-if test "$BUILDKMOD" == "yes"
+if test "$BUILDKMOD" = "yes"
then
dnl Sigh: check kernel version dependencies
if test "$KBUILDDIR" != ""
@@ -203,9 +205,33 @@ AC_CHECK_TYPES([union nf_inet_addr],,,[#include <linux/types.h>
dnl Checks for functions
AC_CHECK_FUNCS(gethostbyname2)
-if test "$BUILDKMOD" == "yes"
+if test "$BUILDKMOD" = "yes"
then
dnl Check kernel incompatibilities... Ugly like hell
+
+AC_MSG_CHECKING([kernel source for INIT_DEFERRABLE_WORK])
+if test -f $ksourcedir/include/linux/workqueue.h && \
+ $GREP -q 'INIT_DEFERRABLE_WORK' $ksourcedir/include/linux/workqueue.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_INIT_DEFERRABLE_WORK, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_INIT_DEFERRABLE_WORK, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for system_power_efficient_wq])
+if test -f $ksourcedir/include/linux/workqueue.h && \
+ $GREP -q 'system_power_efficient_wq' $ksourcedir/include/linux/workqueue.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_SYSTEM_POWER_EFFICIENT_WQ, define)
+elif test -f $ksourcedir/include/linux/workqueue.h && \
+ $GREP -q 'system_wq' $ksourcedir/include/linux/workqueue.h; then
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_SYSTEM_POWER_EFFICIENT_WQ, undef)
+else
+ AC_MSG_ERROR([Kernel source tree is too old, at least v2.36 is required])
+fi
+
AC_MSG_CHECKING([kernel source for struct xt_action_param])
if test -f $ksourcedir/include/linux/netfilter/x_tables.h && \
$GREP -q 'struct xt_action_param' $ksourcedir/include/linux/netfilter/x_tables.h; then
@@ -295,9 +321,13 @@ elif test -f $ksourcedir/include/linux/netlink.h && \
$AWK '/ netlink_dump_start\(/,/\)/' $ksourcedir/include/linux/netlink.h | $GREP -q 'min_dump_alloc.*;'; then
AC_MSG_RESULT(6 args)
AC_SUBST(HAVE_NETLINK_DUMP_START_ARGS, 6)
-else
+elif test -f $ksourcedir/include/linux/netlink.h && \
+ $AWK '/^struct netlink_dump_control {/,/\}/' $ksourcedir/include/linux/netlink.h | $GREP -q '\(\*start\)'; then
AC_MSG_RESULT(4 args)
AC_SUBST(HAVE_NETLINK_DUMP_START_ARGS, 4)
+else
+ AC_MSG_RESULT(7 fake args)
+ AC_SUBST(HAVE_NETLINK_DUMP_START_ARGS, 7)
fi
AC_MSG_CHECKING([kernel source for ns_capable])
@@ -414,6 +444,10 @@ if test -f $ksourcedir/include/linux/mm.h && \
$GREP -q 'kvcalloc' $ksourcedir/include/linux/mm.h; then
AC_MSG_RESULT(yes)
AC_SUBST(HAVE_KVCALLOC, define)
+elif test -f $ksourcedir/include/linux/slab.h && \
+ $GREP -q 'kvcalloc' $ksourcedir/include/linux/slab.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_KVCALLOC, define)
else
AC_MSG_RESULT(no)
AC_SUBST(HAVE_KVCALLOC, undef)
@@ -424,11 +458,35 @@ if test -f $ksourcedir/include/linux/mm.h && \
$GREP -q 'kvfree' $ksourcedir/include/linux/mm.h; then
AC_MSG_RESULT(yes)
AC_SUBST(HAVE_KVFREE, define)
+elif test -f $ksourcedir/include/linux/slab.h && \
+ $GREP -q 'kvfree' $ksourcedir/include/linux/slab.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_KVFREE, define)
else
AC_MSG_RESULT(no)
AC_SUBST(HAVE_KVFREE, undef)
fi
+AC_MSG_CHECKING([kernel source for bitmap_zalloc])
+if test -f $ksourcedir/include/linux/bitmap.h && \
+ $GREP -q 'bitmap_zalloc' $ksourcedir/include/linux/bitmap.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_BITMAP_ZALLOC, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_BITMAP_ZALLOC, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for bitmap_zero])
+if test -f $ksourcedir/include/linux/bitmap.h && \
+ $GREP -q 'bitmap_zero' $ksourcedir/include/linux/bitmap.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_BITMAP_ZERO, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_BITMAP_ZERO, undef)
+fi
+
AC_MSG_CHECKING([kernel source for struct net in struct xt_mtchk_param])
if test -f $ksourcedir/include/linux/netfilter/x_tables.h && \
$AWK '/^struct xt_mtchk_param /,/^}/' $ksourcedir/include/linux/netfilter/x_tables.h | \
@@ -667,6 +725,16 @@ else
AC_SUBST(HAVE_TIMER_SETUP, undef)
fi
+AC_MSG_CHECKING([kernel source for timer_shutdown_sync() in timer.h])
+if test -f $ksourcedir/include/linux/timer.h && \
+ $GREP -q ' timer_shutdown_sync' $ksourcedir/include/linux/timer.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_TIMER_SHUTDOWN_SYNC, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_TIMER_SHUTDOWN_SYNC, undef)
+fi
+
AC_MSG_CHECKING([kernel source for lockdep_nfnl_is_held() in nfnetlink.h])
if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \
$GREP -q ' lockdep_nfnl_is_held' $ksourcedir/include/linux/netfilter/nfnetlink.h; then
@@ -677,6 +745,16 @@ else
AC_SUBST(HAVE_LOCKDEP_NFNL_IS_HELD, undef)
fi
+AC_MSG_CHECKING([kernel source for nla_strscpy() in netlink.h])
+if test -f $ksourcedir/include/net/netlink.h && \
+ $GREP -q ' nla_strscpy' $ksourcedir/include/net/netlink.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_NLA_STRSCPY, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_NLA_STRSCPY, undef)
+fi
+
AC_MSG_CHECKING([kernel source for strscpy() in string.h])
if test -f $ksourcedir/include/linux/timer.h && \
$GREP -q ' strscpy' $ksourcedir/include/linux/string.h; then
@@ -687,6 +765,16 @@ else
AC_SUBST(HAVE_STRSCPY, undef)
fi
+AC_MSG_CHECKING([kernel source for strscpy_pad() in string.h])
+if test -f $ksourcedir/include/linux/timer.h && \
+ $GREP -q ' strscpy_pad' $ksourcedir/include/linux/string.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_STRSCPY_PAD, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_STRSCPY, undef)
+fi
+
AC_MSG_CHECKING([kernel source for synchronize_rcu_bh() in rcutiny.h and rcupdate.h])
if test -f $ksourcedir/include/linux/rcupdate.h && \
$GREP -q 'static inline void synchronize_rcu_bh' \
@@ -698,6 +786,110 @@ else
AC_SUBST(HAVE_SYNCHRONIZE_RCU_BH, undef)
fi
+AC_MSG_CHECKING([kernel source for the fourth arg of list_for_each_entry_rcu() in rculist.h])
+if test -f $ksourcedir/include/linux/rculist.h && \
+ $GREP -q 'define list_for_each_entry_rcu(pos, head, member, cond' $ksourcedir/include/linux/rculist.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for skb_protocol() in if_vlan.h])
+if test -f $ksourcedir/include/linux/if_vlan.h && \
+ $GREP -q 'static inline __be16 skb_protocol' $ksourcedir/include/linux/if_vlan.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_SKB_PROTOCOL, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_SKB_PROTOCOL, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for NLA_POLICY_EXACT_LEN() in netlink.h])
+if test -f $ksourcedir/include/net/netlink.h && \
+ $GREP -q 'define NLA_POLICY_EXACT_LEN' $ksourcedir/include/net/netlink.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_NLA_POLICY_EXACT_LEN, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_NLA_POLICY_EXACT_LEN, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for nfnl_msg_put() in nfnetlink.h])
+if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \
+ $GREP -q 'nfnl_msg_put' $ksourcedir/include/linux/netfilter/nfnetlink.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_NFNL_MSG_PUT, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_NFNL_MSG_PUT, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for struct nfnl_info in nfnl_callback function])
+if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \
+ $AWK '/^struct nfnl_callback /,/^}/' $ksourcedir/include/linux/netfilter/nfnetlink.h | $GREP -q 'struct nfnl_info'; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_NFNL_INFO_IN_NFNL_CALLBACK, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_NFNL_INFO_IN_NFNL_CALLBACK, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for enum nfnl_callback_type])
+if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \
+ $GREP -q 'enum nfnl_callback_type ' $ksourcedir/include/linux/netfilter/nfnetlink.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_NFNL_CALLBACK_TYPE, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_NFNL_CALLBACK_TYPE, undef)
+fi
+
+AC_MSG_CHECKING([kernel source of handling -EAGAIN in nfnetlink_unicast])
+if test -f $ksourcedir/net/netfilter/nfnetlink.c && \
+ $AWK '/nfnetlink_unicast\(/,/^}/' $ksourcedir/net/netfilter/nfnetlink.c | $GREP -q 'err == -EAGAIN'; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_EAGAIN_IN_NFNETLINK_UNICAST, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_EAGAIN_IN_NFNETLINK_UNICAST, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for nlmsg_unicast which returns zero in case of success])
+if test -f $ksourcedir/include/net/netlink.h && \
+ $AWK '/static inline int nlmsg_unicast\(/,/^}/' $ksourcedir/include/net/netlink.h | $GREP -q 'err > 0'; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_NLMSG_UNICAST, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_NLMSG_UNICAST, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for kvzalloc() in mm.h and slab.h])
+if test -f $ksourcedir/include/linux/mm.h && \
+ $GREP -q 'static inline void \*kvzalloc(' $ksourcedir/include/linux/mm.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_KVZALLOC, define)
+elif test -f $ksourcedir/include/linux/slab.h && \
+ $GREP -q 'kvzalloc' $ksourcedir/include/linux/slab.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_KVZALLOC, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_KVZALLOC, undef)
+fi
+
+AC_MSG_CHECKING([kernel source for GFP_KERNEL_ACCOUNT in gfp.h])
+if test -f $ksourcedir/include/linux/gfp.h && \
+ $GREP -q 'define GFP_KERNEL_ACCOUNT' $ksourcedir/include/linux/gfp.h; then
+ AC_MSG_RESULT(yes)
+ AC_SUBST(HAVE_GFP_KERNEL_ACCOUNT, define)
+else
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAVE_GFP_KERNEL_ACCOUNT, undef)
+fi
+
AC_MSG_CHECKING([kernel source for struct net_generic])
if test -f $ksourcedir/include/net/netns/generic.h && \
$GREP -q 'struct net_generic' $ksourcedir/include/net/netns/generic.h; then
@@ -753,7 +945,8 @@ dnl Checks for library functions.
dnl Generate output
AC_CONFIG_FILES([Makefile include/libipset/Makefile
lib/Makefile lib/libipset.pc src/Makefile utils/Makefile
- kernel/include/linux/netfilter/ipset/ip_set_compat.h])
+ kernel/include/linux/netfilter/ipset/ip_set_compat.h
+ kernel/include/linux/netfilter/ipset/ip_set_compiler.h])
AC_OUTPUT
dnl Summary
diff --git a/include/libipset/Makefile.am b/include/libipset/Makefile.am
index c7f7b2b..2c04029 100644
--- a/include/libipset/Makefile.am
+++ b/include/libipset/Makefile.am
@@ -17,6 +17,7 @@ pkginclude_HEADERS = \
transport.h \
types.h \
ipset.h \
- utils.h
+ utils.h \
+ xlate.h
EXTRA_DIST = debug.h icmp.h icmpv6.h
diff --git a/include/libipset/args.h b/include/libipset/args.h
index 616cca5..a549e42 100644
--- a/include/libipset/args.h
+++ b/include/libipset/args.h
@@ -56,6 +56,9 @@ enum ipset_keywords {
IPSET_ARG_SKBMARK, /* skbmark */
IPSET_ARG_SKBPRIO, /* skbprio */
IPSET_ARG_SKBQUEUE, /* skbqueue */
+ IPSET_ARG_BUCKETSIZE, /* bucketsize */
+ IPSET_ARG_INITVAL, /* initval */
+ IPSET_ARG_BITMASK, /* bitmask */
IPSET_ARG_MAX,
};
diff --git a/include/libipset/data.h b/include/libipset/data.h
index 851773a..afaf18c 100644
--- a/include/libipset/data.h
+++ b/include/libipset/data.h
@@ -37,6 +37,7 @@ enum ipset_opt {
IPSET_OPT_RESIZE,
IPSET_OPT_SIZE,
IPSET_OPT_FORCEADD,
+ IPSET_OPT_BITMASK,
/* Create-specific options, filled out by the kernel */
IPSET_OPT_ELEMENTS,
IPSET_OPT_REFERENCES,
@@ -67,8 +68,10 @@ enum ipset_opt {
IPSET_OPT_SKBPRIO,
IPSET_OPT_SKBQUEUE,
IPSET_OPT_IFACE_WILDCARD,
+ IPSET_OPT_BUCKETSIZE,
+ IPSET_OPT_INITVAL,
/* Internal options */
- IPSET_OPT_FLAGS = 48, /* IPSET_FLAG_EXIST| */
+ IPSET_OPT_FLAGS = 49, /* IPSET_FLAG_EXIST| */
IPSET_OPT_CADT_FLAGS, /* IPSET_FLAG_BEFORE| */
IPSET_OPT_ELEM,
IPSET_OPT_TYPE,
@@ -103,7 +106,8 @@ enum ipset_opt {
| IPSET_FLAG(IPSET_OPT_COUNTERS)\
| IPSET_FLAG(IPSET_OPT_CREATE_COMMENT)\
| IPSET_FLAG(IPSET_OPT_FORCEADD)\
- | IPSET_FLAG(IPSET_OPT_SKBINFO))
+ | IPSET_FLAG(IPSET_OPT_SKBINFO)\
+ | IPSET_FLAG(IPSET_OPT_BITMASK))
#define IPSET_ADT_FLAGS \
(IPSET_FLAG(IPSET_OPT_IP) \
diff --git a/include/libipset/debug.h b/include/libipset/debug.h
index 9743d59..92d5f89 100644
--- a/include/libipset/debug.h
+++ b/include/libipset/debug.h
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <sys/socket.h>
#include <linux/netlink.h>
+#define DD(cmd) cmd
#define D(fmt, args...) \
fprintf(stderr, "%s: %s: " fmt "\n", __FILE__, __func__ , ## args)
#define IF_D(test, fmt, args...) \
@@ -25,6 +26,7 @@ dump_nla(struct nlattr *nla[], int maxlen)
D("nla[%u] does%s exist", i, nla[i] ? "" : " NOT");
}
#else
+#define DD(cmd)
#define D(fmt, args...)
#define IF_D(test, fmt, args...)
#define dump_nla(nla, maxlen)
diff --git a/include/libipset/ip_set_compiler.h b/include/libipset/ip_set_compiler.h
new file mode 100644
index 0000000..1b392f8
--- /dev/null
+++ b/include/libipset/ip_set_compiler.h
@@ -0,0 +1,15 @@
+#ifndef __IP_SET_COMPILER_H
+#define __IP_SET_COMPILER_H
+
+/* Compiler attributes */
+#ifndef __has_attribute
+# define __has_attribute(x) __GCC4_has_attribute_##x
+# define __GCC4_has_attribute___fallthrough__ 0
+#endif
+
+#if __has_attribute(__fallthrough__)
+# define fallthrough __attribute__((__fallthrough__))
+#else
+# define fallthrough do {} while (0) /* fallthrough */
+#endif
+#endif /* __IP_SET_COMPILER_H */
diff --git a/include/libipset/linux_ip_set.h b/include/libipset/linux_ip_set.h
index 7fd9948..4e32a50 100644
--- a/include/libipset/linux_ip_set.h
+++ b/include/libipset/linux_ip_set.h
@@ -89,14 +89,15 @@ enum {
IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
IPSET_ATTR_MARK, /* 10 */
IPSET_ATTR_MARKMASK, /* 11 */
+ IPSET_ATTR_BITMASK, /* 12 */
/* Reserve empty slots */
IPSET_ATTR_CADT_MAX = 16,
/* Create-only specific attributes */
- IPSET_ATTR_GC,
+ IPSET_ATTR_INITVAL, /* was unused IPSET_ATTR_GC */
IPSET_ATTR_HASHSIZE,
IPSET_ATTR_MAXELEM,
IPSET_ATTR_NETMASK,
- IPSET_ATTR_PROBES,
+ IPSET_ATTR_BUCKETSIZE, /* was unused IPSET_ATTR_PROBES */
IPSET_ATTR_RESIZE,
IPSET_ATTR_SIZE,
/* Kernel-only */
@@ -157,6 +158,7 @@ enum ipset_errno {
IPSET_ERR_COMMENT,
IPSET_ERR_INVALID_MARKMASK,
IPSET_ERR_SKBINFO,
+ IPSET_ERR_BITMASK_NETMASK_EXCL,
/* Type specific error codes */
IPSET_ERR_TYPE_SPECIFIC = 4352,
@@ -214,6 +216,8 @@ enum ipset_cadt_flags {
enum ipset_create_flags {
IPSET_CREATE_FLAG_BIT_FORCEADD = 0,
IPSET_CREATE_FLAG_FORCEADD = (1 << IPSET_CREATE_FLAG_BIT_FORCEADD),
+ IPSET_CREATE_FLAG_BIT_BUCKETSIZE = 1,
+ IPSET_CREATE_FLAG_BUCKETSIZE = (1 << IPSET_CREATE_FLAG_BIT_BUCKETSIZE),
IPSET_CREATE_FLAG_BIT_MAX = 7,
};
diff --git a/include/libipset/list_sort.h b/include/libipset/list_sort.h
index 70bb02d..d9d7b36 100644
--- a/include/libipset/list_sort.h
+++ b/include/libipset/list_sort.h
@@ -61,7 +61,7 @@ static inline void list_del(struct list_head *entry)
// entry->prev = (void *) 0;
}
-static inline void __list_splice(const struct list_head *list,
+static inline void __list_splice(struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
@@ -75,7 +75,7 @@ static inline void __list_splice(const struct list_head *list,
next->prev = last;
}
-static inline void list_splice(const struct list_head *list,
+static inline void list_splice(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
diff --git a/include/libipset/parse.h b/include/libipset/parse.h
index 3fa9129..0123d4b 100644
--- a/include/libipset/parse.h
+++ b/include/libipset/parse.h
@@ -92,6 +92,8 @@ extern int ipset_parse_uint8(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_netmask(struct ipset_session *session,
enum ipset_opt opt, const char *str);
+extern int ipset_parse_bitmask(struct ipset_session *session,
+ enum ipset_opt opt, const char *str);
extern int ipset_parse_flag(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_typename(struct ipset_session *session,
diff --git a/include/libipset/print.h b/include/libipset/print.h
index f455259..9443ee1 100644
--- a/include/libipset/print.h
+++ b/include/libipset/print.h
@@ -35,6 +35,9 @@ extern int ipset_print_ipaddr(char *buf, unsigned int len,
extern int ipset_print_number(char *buf, unsigned int len,
const struct ipset_data *data,
enum ipset_opt opt, uint8_t env);
+extern int ipset_print_hexnumber(char *buf, unsigned int len,
+ const struct ipset_data *data,
+ enum ipset_opt opt, uint8_t env);
extern int ipset_print_name(char *buf, unsigned int len,
const struct ipset_data *data,
enum ipset_opt opt, uint8_t env);
diff --git a/include/libipset/session.h b/include/libipset/session.h
index 5f18a6e..365e17e 100644
--- a/include/libipset/session.h
+++ b/include/libipset/session.h
@@ -84,6 +84,8 @@ enum ipset_envopt {
IPSET_ENV_LIST_SETNAME = (1 << IPSET_ENV_BIT_LIST_SETNAME),
IPSET_ENV_BIT_LIST_HEADER = 5,
IPSET_ENV_LIST_HEADER = (1 << IPSET_ENV_BIT_LIST_HEADER),
+ IPSET_ENV_BIT_QUOTED = 6,
+ IPSET_ENV_QUOTED = (1 << IPSET_ENV_BIT_QUOTED),
};
extern bool ipset_envopt_test(struct ipset_session *session,
@@ -98,6 +100,7 @@ enum ipset_output_mode {
IPSET_LIST_PLAIN,
IPSET_LIST_SAVE,
IPSET_LIST_XML,
+ IPSET_LIST_JSON,
};
extern int ipset_session_output(struct ipset_session *session,
diff --git a/include/libipset/xlate.h b/include/libipset/xlate.h
new file mode 100644
index 0000000..6569768
--- /dev/null
+++ b/include/libipset/xlate.h
@@ -0,0 +1,6 @@
+#ifndef LIBIPSET_XLATE_H
+#define LIBIPSET_XLATE_H
+
+int ipset_xlate_argv(struct ipset *ipset, int argc, char *argv[]);
+
+#endif
diff --git a/kernel/ChangeLog b/kernel/ChangeLog
index 79e736e..1b05fbd 100644
--- a/kernel/ChangeLog
+++ b/kernel/ChangeLog
@@ -1,3 +1,147 @@
+7.21
+ - netfilter: ipset: Suppress false sparse warnings
+ - tests: Verify module unload when sets with timeout were just destroyed
+ - netfilter: ipset: remove set destroy at ip_set module removal
+ - netfilter: ipset: Cleanup the code of destroy operation and explain
+ the two stages in comments
+ - netfilter: ipset: Missing gc cancellations fixed
+
+7.20
+ - treewide: Convert del_timer*() to timer_shutdown*() (Steven Rostedt)
+ - Use timer_shutdown_sync() when available, instead of del_timer_sync()
+ - netfilter: ipset: fix race condition between swap/destroy and kernel
+ side add/del/test v4
+ - netfilter: ipset: fix race condition between swap/destroy and kernel
+ side add/del/test v3
+ - netfilter: ipset: fix race condition between swap/destroy and kernel
+ side add/del/test v2
+ - netfilter: ipset: fix race condition between swap/destroy and kernel
+ side add/del/test
+
+7.18
+ - netfilter: ipset: Fix race between IPSET_CMD_CREATE and IPSET_CMD_SWAP
+ (reported by Kyle Zeng)
+ - netfilter: ipset: add the missing IP_SET_HASH_WITH_NET0 macro for
+ ip_set_hash_netportnet.c (Kyle Zeng)
+ - compatibility: handle strscpy_pad()
+ - netfilter: ipset: refactor deprecated strncpy (Justin Stitt)
+ - netfilter: ipset: remove rcu_read_lock_bh pair from ip_set_test
+ (Florian Westphal)
+ - netfilter: ipset: Replace strlcpy with strscpy (Azeem Shaikh)
+ - netfilter: ipset: Add schedule point in call_ad(). (Kuniyuki Iwashima)
+ - net: Kconfig: fix spellos (Randy Dunlap)
+ - netfilter: ipset: Fix overflow before widen in the bitmap_ip_create()
+ function. (Gavrilov Ilia)
+
+7.17
+ - netfilter: ipset: Rework long task execution when adding/deleting entries
+ - netfilter: ipset: fix hash:net,port,net hang with /0 subnet
+
+7.16
+ - netfilter: ipset: restore allowing 64 clashing elements in hash:net,iface
+ - Fix all debug mode warnings
+ - netfilter: ipset: Add support for new bitmask parameter (Vishwanath Pai)
+ - netfilter: ipset: regression in ip_set_hash_ip.c (Vishwanath Pai)
+ - netfilter: move from strlcpy with unused retval to strscpy
+ (Wolfram Sang)
+ - compatibility: handle unsafe_memcpy()
+ - netlink: Bounds-check struct nlmsgerr creation (Kees Cook)
+ - compatibility: move to skb_protocol in the code from tc_skb_protocol
+ - Compatibility: check kvcalloc, kvfree, kvzalloc in slab.h too
+ - sched: consistently handle layer3 header accesses in the presence
+ of VLANs (Toke Høiland-Jørgensen)
+ - treewide: Replace GPLv2 boilerplate/reference with SPDX
+ - rule 500 (Thomas Gleixner)
+ - headers: Remove some left-over license text in
+ include/uapi/linux/netfilter/ (Christophe JAILLET)
+ - netfilter: ipset: enforce documented limit to prevent allocating
+ huge memory
+ - netfilter: ipset: Fix oversized kvmalloc() calls
+
+7.15
+ - netfilter: ipset: Fix maximal range check in hash_ipportnet4_uadt()
+ (Nathan Chancellor)
+
+7.14
+ - 64bit division isn't allowed on 32bit, replace it with shift
+
+7.13
+ - Limit the maximal range of consecutive elements to add/delete fix
+
+7.12
+ - Limit the maximal range of consecutive elements to add/delete
+ - Backport "netfilter: use nfnetlink_unicast()"
+ - Backport "netfilter: nfnetlink: consolidate callback type"
+ - Backport "netfilter: nfnetlink: add struct nfnl_info and
+ pass it to callbacks"
+ - Backport "netfilter: add helper function to set up the
+ nfnetlink header and use it"
+
+7.10
+ - Fix patch "Handle false warning from -Wstringop-overflow"
+ - Backward compatibility: handle renaming nla_strlcpy to nla_strscpy
+ - treewide: rename nla_strlcpy to nla_strscpy. (Francis Laniel)
+ - netfilter: ipset: fix shift-out-of-bounds in htable_bits()
+ (Vasily Averin)
+ - netfilter: ipset: fixes possible oops in mtype_resize (Vasily Averin)
+ - Handle false warning from -Wstringop-overflow
+ - Backward compatibility: handle missing strscpy with a wrapper of strlcpy.
+ - Move compiler specific compatibility support to separated file (broken
+ compatibility support reported by Ed W)
+
+7.8
+ - Complete backward compatibility fix for package copy of <linux/jhash.h>
+ - Compatibility: check for kvzalloc() and GFP_KERNEL_ACCOUNT
+ - netfilter: ipset: enable memory accounting for ipset allocations
+ (Vasily Averin)
+ - netfilter: ipset: prevent uninit-value in hash_ip6_add (Eric Dumazet)
+ - Compatibility: use skb_policy() from if_vlan.h if available
+ - Compatibility: Check for the fourth arg of list_for_each_entry_rcu()
+ - Backward compatibility fix for the package copy of <linux/jhash.h>
+
+7.7
+ - Expose the initval hash parameter to userspace
+ - Add bucketsize parameter to all hash types
+ - Use fallthrough pseudo-keyword in the package copy of <linux/jhash.h> too
+ - Support the -exist flag with the destroy command
+ - netfilter: Use fallthrough pseudo-keyword (Gustavo A. R. Silva)
+ - netfilter: Replace zero-length array with flexible-array member
+ (Gustavo A. R. Silva)
+ - netfilter: ipset: call ip_set_free() instead of kfree() (Eric Dumazet)
+ - netfiler: ipset: fix unaligned atomic access (Russell King)
+ - netfilter: ipset: Fix subcounter update skip (Phil Sutter)
+ - ipset: Update byte and packet counters regardless of whether they match
+ (Stefano Brivio)
+ - netfilter: ipset: Pass lockdep expression to RCU lists (Amol Grover)
+ - ip_set: Fix compatibility with kernels between v3.3 and v4.5
+ (Serhey Popovych)
+ - ip_set: Fix build on kernels without INIT_DEFERRABLE_WORK
+ (Serhey Popovych)
+ - ipset: Support kernels with at least system_wq support
+ - ip_set: Fix build on kernels without system_power_efficient_wq
+ (Serhey Popovych)
+
+7.6
+ - netfilter: ipset: Fix forceadd evaluation path
+ - netfilter: ipset: Correct the reported memory size
+ - ip_set: Include kernel header instead of UAPI (Serhey Popovych)
+ - netfilter: ipset: Fix "INFO: rcu detected stall in hash_xxx" reports
+ - netfilter: ipset: fix suspicious RCU usage in find_set_and_id
+ - Add compatibility support for bitmap_zalloc() and bitmap_zero()
+ - netfilter: ipset: use bitmap infrastructure completely
+ - netfilter: fix a use-after-free in mtype_destroy() (Cong Wang)
+
+7.5
+ - netfilter: ipset: avoid null deref when IPSET_ATTR_LINENO is present
+ (Florian Westphal)
+ - ip_set: Pass init_net when @net is missing in match check params
+ data structure (Serhey Popovych)
+ - netfilter: xt_set: Do not restrict --map-set to the mangle table
+ (Serhey Popovych)
+ - compat: em_ipset: Build on old kernels (Serhey Popovych)
+ - compat: Use skb_vlan_tag_present() instead of vlan_tx_tag_present()
+ (Serhey Popovych)
+
7.4
- Fix nla_policies to fully support NL_VALIDATE_STRICT
- treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500
diff --git a/kernel/include/linux/jhash.h b/kernel/include/linux/jhash.h
index c700a77..d144e33 100644
--- a/kernel/include/linux/jhash.h
+++ b/kernel/include/linux/jhash.h
@@ -1,5 +1,6 @@
#ifndef _LINUX_JHASH_H
#define _LINUX_JHASH_H
+#include <linux/netfilter/ipset/ip_set_compiler.h>
/* jhash.h: Jenkins hash support.
*
@@ -87,17 +88,17 @@ static inline u32 jhash(const void *key, u32 length, u32 initval)
/* Last block: affect all 32 bits of (c) */
/* All the case statements fall through */
switch (length) {
- case 12: c += (u32)k[11]<<24;
- case 11: c += (u32)k[10]<<16;
- case 10: c += (u32)k[9]<<8;
- case 9: c += k[8];
- case 8: b += (u32)k[7]<<24;
- case 7: b += (u32)k[6]<<16;
- case 6: b += (u32)k[5]<<8;
- case 5: b += k[4];
- case 4: a += (u32)k[3]<<24;
- case 3: a += (u32)k[2]<<16;
- case 2: a += (u32)k[1]<<8;
+ case 12: c += (u32)k[11]<<24; fallthrough;
+ case 11: c += (u32)k[10]<<16; fallthrough;
+ case 10: c += (u32)k[9]<<8; fallthrough;
+ case 9: c += k[8]; fallthrough;
+ case 8: b += (u32)k[7]<<24; fallthrough;
+ case 7: b += (u32)k[6]<<16; fallthrough;
+ case 6: b += (u32)k[5]<<8; fallthrough;
+ case 5: b += k[4]; fallthrough;
+ case 4: a += (u32)k[3]<<24; fallthrough;
+ case 3: a += (u32)k[2]<<16; fallthrough;
+ case 2: a += (u32)k[1]<<8; fallthrough;
case 1: a += k[0];
__jhash_final(a, b, c);
case 0: /* Nothing left to add */
@@ -133,8 +134,8 @@ static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
/* Handle the last 3 u32's: all the case statements fall through */
switch (length) {
- case 3: c += k[2];
- case 2: b += k[1];
+ case 3: c += k[2]; fallthrough;
+ case 2: b += k[1]; fallthrough;
case 1: a += k[0];
__jhash_final(a, b, c);
case 0: /* Nothing left to add */
diff --git a/kernel/include/linux/netfilter/ipset/ip_set.h b/kernel/include/linux/netfilter/ipset/ip_set.h
index 3949e32..7691b7a 100644
--- a/kernel/include/linux/netfilter/ipset/ip_set.h
+++ b/kernel/include/linux/netfilter/ipset/ip_set.h
@@ -99,7 +99,7 @@ struct ip_set_counter {
struct ip_set_comment_rcu {
struct rcu_head rcu;
- char str[0];
+ char str[];
};
struct ip_set_comment {
@@ -122,6 +122,7 @@ struct ip_set_ext {
u32 timeout;
u8 packets_op;
u8 bytes_op;
+ bool target;
};
struct ip_set;
@@ -188,8 +189,24 @@ struct ip_set_type_variant {
/* Return true if "b" set is the same as "a"
* according to the create set parameters */
bool (*same_set)(const struct ip_set *a, const struct ip_set *b);
+ /* Cancel ongoing garbage collectors before destroying the set*/
+ void (*cancel_gc)(struct ip_set *set);
+ /* Region-locking is used */
+ bool region_lock;
};
+struct ip_set_region {
+ spinlock_t lock; /* Region lock */
+ size_t ext_size; /* Size of the dynamic extensions */
+ u32 elements; /* Number of elements vs timeout */
+};
+
+/* Max range where every element is added/deleted in one step */
+#define IPSET_MAX_RANGE (1<<14)
+
+/* The max revision number supported by any set type + 1 */
+#define IPSET_REVISION_MAX 9
+
/* The core set type structure */
struct ip_set_type {
struct list_head list;
@@ -207,6 +224,8 @@ struct ip_set_type {
u8 family;
/* Type revisions */
u8 revision_min, revision_max;
+ /* Revision-specific supported (create) flags */
+ u8 create_flags[IPSET_REVISION_MAX+1];
/* Set features to control swapping */
u16 features;
@@ -228,6 +247,8 @@ extern void ip_set_type_unregister(struct ip_set_type *set_type);
/* A generic IP set */
struct ip_set {
+ /* For call_cru in destroy */
+ struct rcu_head rcu;
/* The name of the set */
char name[IPSET_MAXNAMELEN];
/* Lock protecting the set data */
@@ -437,13 +458,6 @@ ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr)
sizeof(*addr));
}
-/* Calculate the bytes required to store the inclusive range of a-b */
-static inline int
-bitmap_bytes(u32 a, u32 b)
-{
- return 4 * ((((b - a + 8) / 8) + 3) / 4);
-}
-
/* How often should the gc be run by default */
#define IPSET_GC_TIME (3 * 60)
@@ -518,8 +532,18 @@ ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo,
*skbinfo = ext->skbinfo;
}
+static inline void
+nf_inet_addr_mask_inplace(union nf_inet_addr *a1,
+ const union nf_inet_addr *mask)
+{
+ a1->all[0] &= mask->all[0];
+ a1->all[1] &= mask->all[1];
+ a1->all[2] &= mask->all[2];
+ a1->all[3] &= mask->all[3];
+}
+
#define IP_SET_INIT_KEXT(skb, opt, set) \
- { .bytes = (skb)->len, .packets = 1, \
+ { .bytes = (skb)->len, .packets = 1, .target = true,\
.timeout = ip_set_adt_opt_timeout(opt, set) }
#define IP_SET_INIT_UEXT(set) \
diff --git a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in
index d71c3fd..5746f39 100644
--- a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in
+++ b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in
@@ -5,6 +5,8 @@
* xt_set.c, ip_set_core.c, ip_set_getport.c, pfxlen.c too.
*/
+#@HAVE_INIT_DEFERRABLE_WORK@ HAVE_INIT_DEFERRABLE_WORK
+#@HAVE_SYSTEM_POWER_EFFICIENT_WQ@ HAVE_SYSTEM_POWER_EFFICIENT_WQ
#@HAVE_STRUCT_XT_ACTION_PARAM@ HAVE_STRUCT_XT_ACTION_PARAM
#@HAVE_VZALLOC@ HAVE_VZALLOC
#@HAVE_ETHER_ADDR_EQUAL@ HAVE_ETHER_ADDR_EQUAL
@@ -26,6 +28,8 @@
#@HAVE_RBTREE_POSTORDER_FOR_EACH_ENTRY_SAFE@ HAVE_RBTREE_POSTORDER_FOR_EACH_ENTRY_SAFE
#@HAVE_KVCALLOC@ HAVE_KVCALLOC
#@HAVE_KVFREE@ HAVE_KVFREE
+#@HAVE_BITMAP_ZALLOC@ HAVE_BITMAP_ZALLOC
+#@HAVE_BITMAP_ZERO@ HAVE_BITMAP_ZERO
#@HAVE_XT_MTCHK_PARAM_STRUCT_NET@ HAVE_XT_MTCHK_PARAM_STRUCT_NET
#@HAVE_TCF_EMATCH_OPS_CHANGE_ARG_NET@ HAVE_TCF_EMATCH_OPS_CHANGE_ARG_NET
#@HAVE_TCF_EMATCH_STRUCT_NET@ HAVE_TCF_EMATCH_STRUCT_NET
@@ -47,11 +51,24 @@
#@HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS@ HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS
#@HAVE_TYPEDEF_SCTP_SCTPHDR_T@ HAVE_TYPEDEF_SCTP_SCTPHDR_T
#@HAVE_TIMER_SETUP@ HAVE_TIMER_SETUP
+#@HAVE_TIMER_SHUTDOWN_SYNC@ HAVE_TIMER_SHUTDOWN_SYNC
#@HAVE_STRSCPY@ HAVE_STRSCPY
+#@HAVE_STRSCPY_PAD@ HAVE_STRSCPY_PAD
#@HAVE_SYNCHRONIZE_RCU_BH@ HAVE_SYNCHRONIZE_RCU_BH
#@HAVE_LOCKDEP_NFNL_IS_HELD@ HAVE_LOCKDEP_NFNL_IS_HELD
#@HAVE_COND_RESCHED_RCU@ HAVE_COND_RESCHED_RCU
#@HAVE_SKB_IIF@ HAVE_SKB_IIF
+#@HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS@ HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS
+#@HAVE_SKB_PROTOCOL@ HAVE_SKB_PROTOCOL
+#@HAVE_NLA_POLICY_EXACT_LEN@ HAVE_NLA_POLICY_EXACT_LEN
+#@HAVE_KVZALLOC@ HAVE_KVZALLOC
+#@HAVE_GFP_KERNEL_ACCOUNT@ HAVE_GFP_KERNEL_ACCOUNT
+#@HAVE_NLA_STRSCPY@ HAVE_NLA_STRSCPY
+#@HAVE_NFNL_MSG_PUT@ HAVE_NFNL_MSG_PUT
+#@HAVE_NFNL_INFO_IN_NFNL_CALLBACK@ HAVE_NFNL_INFO_IN_NFNL_CALLBACK
+#@HAVE_NFNL_CALLBACK_TYPE@ HAVE_NFNL_CALLBACK_TYPE
+#@HAVE_EAGAIN_IN_NFNETLINK_UNICAST@ HAVE_EAGAIN_IN_NFNETLINK_UNICAST
+#@HAVE_NLMSG_UNICAST@ HAVE_NLMSG_UNICAST
#ifdef HAVE_EXPORT_SYMBOL_GPL_IN_MODULE_H
#include <linux/module.h>
@@ -166,6 +183,14 @@ static inline void cond_resched_rcu(void)
#error "NETFILTER_NETLINK must be enabled: select NFACCT/NFQUEUE/LOG over NFNETLINK"
#endif
+#ifndef HAVE_INIT_DEFERRABLE_WORK
+#define INIT_DEFERRABLE_WORK INIT_DELAYED_WORK_DEFERRABLE
+#endif
+
+#ifndef HAVE_SYSTEM_POWER_EFFICIENT_EQ
+#define system_power_efficient_wq system_wq
+#endif
+
#ifndef HAVE_STRUCT_XT_ACTION_PARAM
#define xt_action_param xt_match_param
#endif
@@ -253,6 +278,16 @@ static inline void kvfree(const void *addr)
}
#endif
+#ifndef HAVE_BITMAP_ZALLOC
+#define bitmap_zalloc(nbits, flags) \
+ kmalloc(BITS_TO_LONGS(nbits) * sizeof(unsigned long), (flags) | __GFP_ZERO)
+#endif
+
+#ifndef HAVE_BITMAP_ZERO
+#define bitmap_zero(dst, nbits) \
+ memset(dst, 0, BITS_TO_LONGS(nbits) * sizeof(unsigned long))
+#endif
+
#ifndef HAVE_NLA_PUT_BE16
static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value)
{
@@ -320,18 +355,44 @@ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype,
}
#endif
-#ifdef HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS
-#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(net, nl, skb, nlh, cda, e)
-#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(net, nl, skb, ad, nlh, cda, e)
-#define IPSET_SOCK_NET(net, ctnl) net
+#ifdef HAVE_NFNL_INFO_IN_NFNL_CALLBACK
+#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(skb, i, cda)
+#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda, i)
+#define IPSET_SOCK_NET(n, ctnl, i) (i)->net
+#define INFO_NLH(i, n) (i)->nlh
+#define INFO_NET(i, n) (i)->net
+#define INFO_SK(i, n) (i)->sk
+#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l)
+#elif defined(HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS)
+#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(net, nl, skb, nlh, cda, e)
+#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda, e)
+#define IPSET_SOCK_NET(net, ctnl, i) net
+#define INFO_NLH(i, n) n
+#define INFO_NET(i, n) n
+#define INFO_SK(i, n) n
+#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l)
#elif defined(HAVE_NET_IN_NFNL_CALLBACK_FN)
-#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(net, nl, skb, nlh, cda)
-#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(net, nl, skb, ad, nlh, cda)
-#define IPSET_SOCK_NET(net, ctnl) net
+#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(net, nl, skb, nlh, cda)
+#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda)
+#define IPSET_SOCK_NET(net, ctnl, i) net
+#define INFO_NLH(i, n) n
+#define INFO_NET(i, n) n
+#define INFO_SK(i, n) n
+#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l)
#else
-#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(nl, skb, nlh, cda)
-#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(nl, skb, ad, nlh, cda)
-#define IPSET_SOCK_NET(net, ctnl) sock_net(ctnl)
+#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(nl, skb, nlh, cda)
+#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(nl, skb, ad, nlh, cda)
+#define IPSET_SOCK_NET(net, ctnl, i) sock_net(ctnl)
+#define INFO_NLH(i, n) n
+#define INFO_NET(i, n) n
+#define INFO_SK(i, n) n
+#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(ctnl, skb, set, tb, adt, flags, l)
+#endif
+
+#ifdef HAVE_NFNL_CALLBACK_TYPE
+#define SET_NFNL_CALLBACK_TYPE(t) .type = t,
+#else
+#define SET_NFNL_CALLBACK_TYPE(t)
#endif
#ifndef HAVE_TC_SKB_PROTOCOL
@@ -347,7 +408,8 @@ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype,
#define skb_vlan_tag_present vlan_tx_tag_present
#endif
-static inline __be16 tc_skb_protocol(const struct sk_buff *skb)
+#ifndef HAVE_SKB_PROTOCOL
+static inline __be16 skb_protocol(const struct sk_buff *skb, bool skip_vlan)
{
if (skb_vlan_tag_present(skb))
#ifdef HAVE_VLAN_PROTO_IN_SK_BUFF
@@ -358,6 +420,7 @@ static inline __be16 tc_skb_protocol(const struct sk_buff *skb)
return skb->protocol;
}
#endif
+#endif
#ifdef HAVE_XT_NET
#define IPSET_DEV_NET(par) xt_net(par)
@@ -374,6 +437,36 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type)
}
#endif
+#ifndef HAVE_NFNL_MSG_PUT
+#include <linux/netfilter/nfnetlink.h>
+static inline void nfnl_fill_hdr(struct nlmsghdr *nlh, u8 family, u8 version,
+ __be16 res_id)
+{
+ struct nfgenmsg *nfmsg;
+
+ nfmsg = nlmsg_data(nlh);
+ nfmsg->nfgen_family = family;
+ nfmsg->version = version;
+ nfmsg->res_id = res_id;
+}
+
+static inline struct nlmsghdr *nfnl_msg_put(struct sk_buff *skb, u32 portid,
+ u32 seq, int type, int flags,
+ u8 family, u8 version,
+ __be16 res_id)
+{
+ struct nlmsghdr *nlh;
+
+ nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg), flags);
+ if (!nlh)
+ return NULL;
+
+ nfnl_fill_hdr(nlh, family, version, res_id);
+
+ return nlh;
+}
+#endif
+
#ifdef HAVE_NETLINK_EXTENDED_ACK
#define NETLINK_ACK(in_skb, nlh, err, extack) netlink_ack(in_skb, nlh, err, extack)
#else
@@ -414,8 +507,53 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type)
struct type *var = set->data
#endif
+#ifndef HAVE_TIMER_SHUTDOWN_SYNC
+#define timer_shutdown_sync(timer) del_timer_sync(timer)
+#endif
+
#ifndef HAVE_STRSCPY
-#define strscpy(dst, src, n) (strncpy(dst, src, n) == (dst))
+static inline ssize_t strscpy(char * dest, const char * src, size_t count)
+{
+ size_t ret = strlcpy(dest, src, count);
+
+ return (ret >= count ? -E2BIG : ret);
+}
+#endif
+
+#ifndef HAVE_STRSCPY_PAD
+static inline ssize_t strscpy_pad(char *dest, const char *src, size_t count)
+{
+ ssize_t written;
+
+ written = strscpy(dest, src, count);
+ if (written < 0 || written == count - 1)
+ return written;
+
+ memset(dest + written + 1, 0, count - written - 1);
+
+ return written;
+}
+#endif
+
+#ifndef HAVE_NLA_STRSCPY
+#define nla_strscpy nla_strlcpy
+#endif
+
+#if !defined(HAVE_EAGAIN_IN_NFNETLINK_UNICAST) || !defined(HAVE_NLMSG_UNICAST)
+#define NFNETLINK_UNICAST(cntl, skb, net, portid) ipset_nfnetlink_unicast(cntl, skb, portid)
+static inline int ipset_nfnetlink_unicast(struct sock *ctnl, struct sk_buff *skb, u32 portid)
+{
+ int err = netlink_unicast(ctnl, skb, portid, MSG_DONTWAIT);
+
+ if (err > 0)
+ err = 0;
+ if (err == -EAGAIN)
+ err = -ENOBUFS;
+
+ return err;
+}
+#else
+#define NFNETLINK_UNICAST(cntl, skb, net, portid) nfnetlink_unicast(skb, net, portid)
#endif
#ifndef smp_mb__before_atomic
@@ -447,5 +585,52 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type)
#define dev_get_by_index_rcu __dev_get_by_index
#endif
+#ifdef HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS
+#define list_for_each_entry_rcu_compat(pos, head, member, cond) \
+ list_for_each_entry_rcu(pos, head, member, cond)
+#else
+#define list_for_each_entry_rcu_compat(pos, head, member, cond) \
+ list_for_each_entry_rcu(pos, head, member)
+#endif
+
+#ifndef HAVE_NLA_POLICY_EXACT_LEN
+#define NLA_POLICY_EXACT_LEN(_len) { \
+ .type = NLA_UNSPEC, \
+ .len = _len \
+}
+#endif
+
+#ifndef HAVE_KVZALLOC
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#ifndef GFP_KERNEL_ACCOUNT
+#define GFP_KERNEL_ACCOUNT GFP_KERNEL
+#endif
+static inline void *kvzalloc(size_t size, gfp_t flags)
+{
+ void *members = NULL;
+
+ if (size < KMALLOC_MAX_SIZE)
+ members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
+
+ if (members) {
+ pr_debug("%p: allocated with kmalloc\n", members);
+ return members;
+ }
+
+ members = vzalloc(size);
+ if (!members)
+ return NULL;
+ pr_debug("%p: allocated with vmalloc\n", members);
+
+ return members;
+}
+#endif
+
+#ifndef unsafe_memcpy
+#define unsafe_memcpy(dst, src, bytes, justification) \
+ memcpy(dst, src, bytes)
+#endif
+
#endif /* IP_SET_COMPAT_HEADERS */
#endif /* __IP_SET_COMPAT_H */
diff --git a/kernel/include/linux/netfilter/ipset/ip_set_compiler.h.in b/kernel/include/linux/netfilter/ipset/ip_set_compiler.h.in
new file mode 100644
index 0000000..1b392f8
--- /dev/null
+++ b/kernel/include/linux/netfilter/ipset/ip_set_compiler.h.in
@@ -0,0 +1,15 @@
+#ifndef __IP_SET_COMPILER_H
+#define __IP_SET_COMPILER_H
+
+/* Compiler attributes */
+#ifndef __has_attribute
+# define __has_attribute(x) __GCC4_has_attribute_##x
+# define __GCC4_has_attribute___fallthrough__ 0
+#endif
+
+#if __has_attribute(__fallthrough__)
+# define fallthrough __attribute__((__fallthrough__))
+#else
+# define fallthrough do {} while (0) /* fallthrough */
+#endif
+#endif /* __IP_SET_COMPILER_H */
diff --git a/kernel/include/linux/netfilter/ipset/ip_set_getport.h b/kernel/include/linux/netfilter/ipset/ip_set_getport.h
index 09c5a96..83b88f1 100644
--- a/kernel/include/linux/netfilter/ipset/ip_set_getport.h
+++ b/kernel/include/linux/netfilter/ipset/ip_set_getport.h
@@ -4,7 +4,7 @@
#include <linux/skbuff.h>
#include <linux/types.h>
-#include <uapi/linux/in.h>
+#include <linux/in.h>
extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
__be16 *port, u8 *proto);
diff --git a/kernel/include/uapi/linux/netfilter/ipset/ip_set.h b/kernel/include/uapi/linux/netfilter/ipset/ip_set.h
index 7545af4..b81f1ae 100644
--- a/kernel/include/uapi/linux/netfilter/ipset/ip_set.h
+++ b/kernel/include/uapi/linux/netfilter/ipset/ip_set.h
@@ -3,10 +3,6 @@
* Patrick Schaaf <bof@bof.de>
* Martin Josefsson <gandalf@wlug.westbo.se>
* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@netfilter.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#ifndef _UAPI_IP_SET_H
#define _UAPI_IP_SET_H
@@ -89,14 +85,15 @@ enum {
IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
IPSET_ATTR_MARK, /* 10 */
IPSET_ATTR_MARKMASK, /* 11 */
+ IPSET_ATTR_BITMASK, /* 12 */
/* Reserve empty slots */
IPSET_ATTR_CADT_MAX = 16,
/* Create-only specific attributes */
- IPSET_ATTR_GC,
+ IPSET_ATTR_INITVAL, /* was unused IPSET_ATTR_GC */
IPSET_ATTR_HASHSIZE,
IPSET_ATTR_MAXELEM,
IPSET_ATTR_NETMASK,
- IPSET_ATTR_PROBES,
+ IPSET_ATTR_BUCKETSIZE, /* was unused IPSET_ATTR_PROBES */
IPSET_ATTR_RESIZE,
IPSET_ATTR_SIZE,
/* Kernel-only */
@@ -157,6 +154,7 @@ enum ipset_errno {
IPSET_ERR_COMMENT,
IPSET_ERR_INVALID_MARKMASK,
IPSET_ERR_SKBINFO,
+ IPSET_ERR_BITMASK_NETMASK_EXCL,
/* Type specific error codes */
IPSET_ERR_TYPE_SPECIFIC = 4352,
@@ -214,6 +212,8 @@ enum ipset_cadt_flags {
enum ipset_create_flags {
IPSET_CREATE_FLAG_BIT_FORCEADD = 0,
IPSET_CREATE_FLAG_FORCEADD = (1 << IPSET_CREATE_FLAG_BIT_FORCEADD),
+ IPSET_CREATE_FLAG_BIT_BUCKETSIZE = 1,
+ IPSET_CREATE_FLAG_BUCKETSIZE = (1 << IPSET_CREATE_FLAG_BIT_BUCKETSIZE),
IPSET_CREATE_FLAG_BIT_MAX = 7,
};
diff --git a/kernel/net/netfilter/ipset/Kconfig b/kernel/net/netfilter/ipset/Kconfig
index 861659f..8772af5 100644
--- a/kernel/net/netfilter/ipset/Kconfig
+++ b/kernel/net/netfilter/ipset/Kconfig
@@ -29,7 +29,7 @@ config IP_SET_BITMAP_IP
depends on IP_SET
help
This option adds the bitmap:ip set type support, by which one
- can store IPv4 addresses (or network addresse) from a range.
+ can store IPv4 addresses (or network addresses) from a range.
To compile it as a module, choose M here. If unsure, say N.
diff --git a/kernel/net/netfilter/ipset/ip_set_bitmap_gen.h b/kernel/net/netfilter/ipset/ip_set_bitmap_gen.h
index 5bf6bbd..3245b6b 100644
--- a/kernel/net/netfilter/ipset/ip_set_bitmap_gen.h
+++ b/kernel/net/netfilter/ipset/ip_set_bitmap_gen.h
@@ -29,6 +29,7 @@
#define mtype_del IPSET_TOKEN(MTYPE, _del)
#define mtype_list IPSET_TOKEN(MTYPE, _list)
#define mtype_gc IPSET_TOKEN(MTYPE, _gc)
+#define mtype_cancel_gc IPSET_TOKEN(MTYPE, _cancel_gc)
#define mtype MTYPE
#define get_ext(set, map, id) ((map)->extensions + ((set)->dsize * (id)))
@@ -58,12 +59,9 @@ mtype_destroy(struct ip_set *set)
{
struct mtype *map = set->data;
- if (SET_WITH_TIMEOUT(set))
- del_timer_sync(&map->gc);
-
- ip_set_free(map->members);
if (set->dsize && set->extensions & IPSET_EXT_DESTROY)
mtype_ext_cleanup(set);
+ ip_set_free(map->members);
ip_set_free(map);
set->data = NULL;
@@ -76,7 +74,7 @@ mtype_flush(struct ip_set *set)
if (set->extensions & IPSET_EXT_DESTROY)
mtype_ext_cleanup(set);
- memset(map->members, 0, map->memsize);
+ bitmap_zero(map->members, map->elements);
set->elements = 0;
set->ext_size = 0;
}
@@ -290,6 +288,15 @@ mtype_gc(GC_ARG)
add_timer(&map->gc);
}
+static void
+mtype_cancel_gc(struct ip_set *set)
+{
+ struct mtype *map = set->data;
+
+ if (SET_WITH_TIMEOUT(set))
+ del_timer_sync(&map->gc);
+}
+
static const struct ip_set_type_variant mtype = {
.kadt = mtype_kadt,
.uadt = mtype_uadt,
@@ -303,6 +310,7 @@ static const struct ip_set_type_variant mtype = {
.head = mtype_head,
.list = mtype_list,
.same_set = mtype_same_set,
+ .cancel_gc = mtype_cancel_gc,
};
#endif /* __IP_SET_BITMAP_IP_GEN_H */
diff --git a/kernel/net/netfilter/ipset/ip_set_bitmap_ip.c b/kernel/net/netfilter/ipset/ip_set_bitmap_ip.c
index 14d8e1a..f37169c 100644
--- a/kernel/net/netfilter/ipset/ip_set_bitmap_ip.c
+++ b/kernel/net/netfilter/ipset/ip_set_bitmap_ip.c
@@ -37,7 +37,7 @@ MODULE_ALIAS("ip_set_bitmap:ip");
/* Type structure */
struct bitmap_ip {
- void *members; /* the set members */
+ unsigned long *members; /* the set members */
u32 first_ip; /* host byte order, included in range */
u32 last_ip; /* host byte order, included in range */
u32 elements; /* number of max elements in the set */
@@ -48,7 +48,7 @@ struct bitmap_ip {
#ifdef HAVE_TIMER_SETUP
struct ip_set *set; /* attached to this ip_set */
#endif
- unsigned char extensions[0] /* data extensions */
+ unsigned char extensions[] /* data extensions */
__aligned(__alignof__(u64));
};
@@ -222,7 +222,7 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map,
u32 first_ip, u32 last_ip,
u32 elements, u32 hosts, u8 netmask)
{
- map->members = ip_set_alloc(map->memsize);
+ map->members = bitmap_zalloc(elements, GFP_KERNEL | __GFP_NOWARN);
if (!map->members)
return false;
map->first_ip = first_ip;
@@ -312,8 +312,8 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
return -IPSET_ERR_BITMAP_RANGE;
pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
- hosts = 2 << (32 - netmask - 1);
- elements = 2 << (netmask - mask_bits - 1);
+ hosts = 2U << (32 - netmask - 1);
+ elements = 2UL << (netmask - mask_bits - 1);
}
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
return -IPSET_ERR_BITMAP_RANGE_SIZE;
@@ -326,11 +326,11 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
if (!map)
return -ENOMEM;
- map->memsize = bitmap_bytes(0, elements - 1);
+ map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long);
set->variant = &bitmap_ip;
if (!init_map_ip(set, map, first_ip, last_ip,
elements, hosts, netmask)) {
- kfree(map);
+ ip_set_free(map);
return -ENOMEM;
}
if (tb[IPSET_ATTR_TIMEOUT]) {
diff --git a/kernel/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/kernel/net/netfilter/ipset/ip_set_bitmap_ipmac.c
index fae14e2..3d25d29 100644
--- a/kernel/net/netfilter/ipset/ip_set_bitmap_ipmac.c
+++ b/kernel/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -43,7 +43,7 @@ enum {
/* Type structure */
struct bitmap_ipmac {
- void *members; /* the set members */
+ unsigned long *members; /* the set members */
u32 first_ip; /* host byte order, included in range */
u32 last_ip; /* host byte order, included in range */
u32 elements; /* number of max elements in the set */
@@ -52,7 +52,7 @@ struct bitmap_ipmac {
#ifdef HAVE_TIMER_SETUP
struct ip_set *set; /* attached to this ip_set */
#endif
- unsigned char extensions[0] /* MAC + data extensions */
+ unsigned char extensions[] /* MAC + data extensions */
__aligned(__alignof__(u64));
};
@@ -302,7 +302,7 @@ static bool
init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
u32 first_ip, u32 last_ip, u32 elements)
{
- map->members = ip_set_alloc(map->memsize);
+ map->members = bitmap_zalloc(elements, GFP_KERNEL | __GFP_NOWARN);
if (!map->members)
return false;
map->first_ip = first_ip;
@@ -365,10 +365,10 @@ bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
if (!map)
return -ENOMEM;
- map->memsize = bitmap_bytes(0, elements - 1);
+ map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long);
set->variant = &bitmap_ipmac;
if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
- kfree(map);
+ ip_set_free(map);
return -ENOMEM;
}
if (tb[IPSET_ATTR_TIMEOUT]) {
diff --git a/kernel/net/netfilter/ipset/ip_set_bitmap_port.c b/kernel/net/netfilter/ipset/ip_set_bitmap_port.c
index c38d28e..2a570d8 100644
--- a/kernel/net/netfilter/ipset/ip_set_bitmap_port.c
+++ b/kernel/net/netfilter/ipset/ip_set_bitmap_port.c
@@ -31,7 +31,7 @@ MODULE_ALIAS("ip_set_bitmap:port");
/* Type structure */
struct bitmap_port {
- void *members; /* the set members */
+ unsigned long *members; /* the set members */
u16 first_port; /* host byte order, included in range */
u16 last_port; /* host byte order, included in range */
u32 elements; /* number of max elements in the set */
@@ -40,7 +40,7 @@ struct bitmap_port {
#ifdef HAVE_TIMER_SETUP
struct ip_set *set; /* attached to this ip_set */
#endif
- unsigned char extensions[0] /* data extensions */
+ unsigned char extensions[] /* data extensions */
__aligned(__alignof__(u64));
};
@@ -234,7 +234,7 @@ static bool
init_map_port(struct ip_set *set, struct bitmap_port *map,
u16 first_port, u16 last_port)
{
- map->members = ip_set_alloc(map->memsize);
+ map->members = bitmap_zalloc(map->elements, GFP_KERNEL | __GFP_NOWARN);
if (!map->members)
return false;
map->first_port = first_port;
@@ -276,10 +276,10 @@ bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
return -ENOMEM;
map->elements = elements;
- map->memsize = bitmap_bytes(0, map->elements);
+ map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long);
set->variant = &bitmap_port;
if (!init_map_port(set, map, first_port, last_port)) {
- kfree(map);
+ ip_set_free(map);
return -ENOMEM;
}
if (tb[IPSET_ATTR_TIMEOUT]) {
diff --git a/kernel/net/netfilter/ipset/ip_set_core.c b/kernel/net/netfilter/ipset/ip_set_core.c
index 4d8e8b1..c31dbc3 100644
--- a/kernel/net/netfilter/ipset/ip_set_core.c
+++ b/kernel/net/netfilter/ipset/ip_set_core.c
@@ -21,6 +21,7 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_compiler.h>
static LIST_HEAD(ip_set_type_list); /* all registered set types */
static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */
@@ -29,7 +30,6 @@ static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */
struct ip_set_net {
struct ip_set * __rcu *ip_set_list; /* all individual sets */
ip_set_id_t ip_set_max; /* max number of sets */
- bool is_deleted; /* deleted by ip_set_net_exit */
bool is_destroyed; /* all sets are destroyed */
};
@@ -61,6 +61,8 @@ MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
ip_set_dereference((inst)->ip_set_list)[id]
#define ip_set_ref_netlink(inst,id) \
rcu_dereference_raw((inst)->ip_set_list)[id]
+#define ip_set_dereference_nfnl(p) \
+ rcu_dereference_check(p, lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))
/* The set types are implemented in modules and registered set types
* can be found in ip_set_type_list. Adding/deleting types is
@@ -86,7 +88,8 @@ find_set_type(const char *name, u8 family, u8 revision)
{
struct ip_set_type *type;
- list_for_each_entry_rcu(type, &ip_set_type_list, list)
+ list_for_each_entry_rcu_compat(type, &ip_set_type_list, list,
+ lockdep_is_held(&ip_set_type_mutex))
if (STRNCMP(type->name, name) &&
(type->family == family ||
type->family == NFPROTO_UNSPEC) &&
@@ -249,22 +252,7 @@ EXPORT_SYMBOL_GPL(ip_set_type_unregister);
void *
ip_set_alloc(size_t size)
{
- void *members = NULL;
-
- if (size < KMALLOC_MAX_SIZE)
- members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
-
- if (members) {
- pr_debug("%p: allocated with kmalloc\n", members);
- return members;
- }
-
- members = vzalloc(size);
- if (!members)
- return NULL;
- pr_debug("%p: allocated with vmalloc\n", members);
-
- return members;
+ return kvzalloc(size, GFP_KERNEL_ACCOUNT);
}
EXPORT_SYMBOL_GPL(ip_set_alloc);
@@ -285,8 +273,7 @@ flag_nested(const struct nlattr *nla)
static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
[IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 },
- [IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY,
- .len = sizeof(struct in6_addr) },
+ [IPSET_ATTR_IPADDR_IPV6] = NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
};
int
@@ -368,7 +355,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
c = kmalloc(sizeof(*c) + len + 1, GFP_ATOMIC);
if (unlikely(!c))
return;
- strlcpy(c->str, ext->comment, len + 1);
+ strscpy(c->str, ext->comment, len + 1);
set->ext_size += sizeof(*c) + strlen(c->str) + 1;
rcu_assign_pointer(comment->c, c);
}
@@ -459,6 +446,8 @@ ip_set_elem_len(struct ip_set *set, struct nlattr *tb[], size_t len,
for (id = 0; id < IPSET_EXT_ID_MAX; id++) {
if (!add_extension(id, cadt_flags, tb))
continue;
+ if (align < ip_set_extensions[id].align)
+ align = ip_set_extensions[id].align;
len = ALIGN(len, ip_set_extensions[id].align);
set->offset[id] = len;
set->extensions |= ip_set_extensions[id].type;
@@ -649,13 +638,14 @@ ip_set_match_extensions(struct ip_set *set, const struct ip_set_ext *ext,
if (SET_WITH_COUNTER(set)) {
struct ip_set_counter *counter = ext_counter(data, set);
+ ip_set_update_counter(counter, ext, flags);
+
if (flags & IPSET_FLAG_MATCH_COUNTERS &&
!(ip_set_match_counter(ip_set_get_packets(counter),
mext->packets, mext->packets_op) &&
ip_set_match_counter(ip_set_get_bytes(counter),
mext->bytes, mext->bytes_op)))
return false;
- ip_set_update_counter(counter, ext, flags);
}
if (SET_WITH_SKBINFO(set))
ip_set_get_skbinfo(ext_skbinfo(data, set),
@@ -695,6 +685,14 @@ __ip_set_put(struct ip_set *set)
* a separate reference counter
*/
static void
+__ip_set_get_netlink(struct ip_set *set)
+{
+ write_lock_bh(&ip_set_ref_lock);
+ set->ref_netlink++;
+ write_unlock_bh(&ip_set_ref_lock);
+}
+
+static void
__ip_set_put_netlink(struct ip_set *set)
{
write_lock_bh(&ip_set_ref_lock);
@@ -712,15 +710,24 @@ __ip_set_put_netlink(struct ip_set *set)
static struct ip_set *
ip_set_rcu_get(struct net *net, ip_set_id_t index)
{
- struct ip_set *set;
struct ip_set_net *inst = ip_set_pernet(net);
- rcu_read_lock();
- /* ip_set_list itself needs to be protected */
- set = rcu_dereference(inst->ip_set_list)[index];
- rcu_read_unlock();
+ /* ip_set_list and the set pointer need to be protected */
+ return ip_set_dereference_nfnl(inst->ip_set_list)[index];
+}
- return set;
+static inline void
+ip_set_lock(struct ip_set *set)
+{
+ if (!set->variant->region_lock)
+ spin_lock_bh(&set->lock);
+}
+
+static inline void
+ip_set_unlock(struct ip_set *set)
+{
+ if (!set->variant->region_lock)
+ spin_unlock_bh(&set->lock);
}
int
@@ -737,16 +744,14 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
!(opt->family == set->family || set->family == NFPROTO_UNSPEC))
return 0;
- rcu_read_lock_bh();
ret = set->variant->kadt(set, skb, par, IPSET_TEST, opt);
- rcu_read_unlock_bh();
if (ret == -EAGAIN) {
/* Type requests element to be completed */
pr_debug("element must be completed, ADD is triggered\n");
- spin_lock_bh(&set->lock);
+ ip_set_lock(set);
set->variant->kadt(set, skb, par, IPSET_ADD, opt);
- spin_unlock_bh(&set->lock);
+ ip_set_unlock(set);
ret = 1;
} else {
/* --return-nomatch: invert matched element */
@@ -775,9 +780,9 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
!(opt->family == set->family || set->family == NFPROTO_UNSPEC))
return -IPSET_ERR_TYPE_MISMATCH;
- spin_lock_bh(&set->lock);
+ ip_set_lock(set);
ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt);
- spin_unlock_bh(&set->lock);
+ ip_set_unlock(set);
return ret;
}
@@ -797,9 +802,9 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
!(opt->family == set->family || set->family == NFPROTO_UNSPEC))
return -IPSET_ERR_TYPE_MISMATCH;
- spin_lock_bh(&set->lock);
+ ip_set_lock(set);
ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt);
- spin_unlock_bh(&set->lock);
+ ip_set_unlock(set);
return ret;
}
@@ -872,7 +877,7 @@ ip_set_name_byindex(struct net *net, ip_set_id_t index, char *name)
BUG_ON(!set);
read_lock_bh(&ip_set_ref_lock);
- strncpy(name, set->name, IPSET_MAXNAMELEN);
+ strscpy_pad(name, set->name, IPSET_MAXNAMELEN);
read_unlock_bh(&ip_set_ref_lock);
}
EXPORT_SYMBOL_GPL(ip_set_name_byindex);
@@ -920,11 +925,9 @@ ip_set_nfnl_put(struct net *net, ip_set_id_t index)
struct ip_set_net *inst = ip_set_pernet(net);
nfnl_lock(NFNL_SUBSYS_IPSET);
- if (!inst->is_deleted) { /* already deleted from ip_set_net_exit() */
- set = ip_set(inst, index);
- if (set)
- __ip_set_put(set);
- }
+ set = ip_set(inst, index);
+ if (set)
+ __ip_set_put(set);
nfnl_unlock(NFNL_SUBSYS_IPSET);
}
EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
@@ -961,20 +964,9 @@ static struct nlmsghdr *
start_msg(struct sk_buff *skb, u32 portid, u32 seq, unsigned int flags,
enum ipset_cmd cmd)
{
- struct nlmsghdr *nlh;
- struct nfgenmsg *nfmsg;
-
- nlh = nlmsg_put(skb, portid, seq, nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd),
- sizeof(*nfmsg), flags);
- if (!nlh)
- return NULL;
-
- nfmsg = nlmsg_data(nlh);
- nfmsg->nfgen_family = NFPROTO_IPV4;
- nfmsg->version = NFNETLINK_V0;
- nfmsg->res_id = 0;
-
- return nlh;
+ return nfnl_msg_put(skb, portid, seq,
+ nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd), flags,
+ NFPROTO_IPV4, NFNETLINK_V0, 0);
}
/* Create a set */
@@ -1044,7 +1036,8 @@ static int
IPSET_CBFN(ip_set_none, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
return -EOPNOTSUPP;
}
@@ -1053,16 +1046,17 @@ static int
IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
- struct net *net = IPSET_SOCK_NET(n, ctnl);
+ struct net *net = IPSET_SOCK_NET(n, ctnl, info);
struct ip_set_net *inst = ip_set_pernet(net);
struct ip_set *set, *clash = NULL;
ip_set_id_t index = IPSET_INVALID_ID;
struct nlattr *tb[IPSET_ATTR_CREATE_MAX + 1] = {};
const char *name, *typename;
u8 family, revision;
- u32 flags = flag_exist(nlh);
+ u32 flags = flag_exist(INFO_NLH(info, nlh));
int ret = 0;
if (unlikely(protocol_min_failed(attr) ||
@@ -1088,7 +1082,7 @@ IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl,
if (!set)
return -ENOMEM;
spin_lock_init(&set->lock);
- strlcpy(set->name, name, IPSET_MAXNAMELEN);
+ strscpy(set->name, name, IPSET_MAXNAMELEN);
set->family = family;
set->revision = revision;
@@ -1110,8 +1104,10 @@ IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl,
ret = -IPSET_ERR_PROTOCOL;
goto put_out;
}
+ /* Set create flags depending on the type revision */
+ set->flags |= set->type->create_flags[revision];
- ret = set->type->create(net, set, tb, flags);
+ ret = set->type->create(INFO_NET(info, net), set, tb, flags);
if (ret != 0)
goto put_out;
@@ -1165,6 +1161,7 @@ IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl,
return ret;
cleanup:
+ set->variant->cancel_gc(set);
set->variant->destroy(set);
put_out:
module_put(set->type->me);
@@ -1182,24 +1179,58 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = {
.len = IPSET_MAXNAMELEN - 1 },
};
+/* Destroying a set is split into two stages when a DESTROY command issued:
+ * - Cancel garbage collectors and decrement the module reference counter:
+ * - Cancelling may wait and we are allowed to do it at this stage.
+ * - Module remove is protected by rcu_barrier() which waits for
+ * the second stage to be finished.
+ * - In order to prevent the race between kernel side add/del/test element
+ * operations and destroy, the destroying of the set data areas are
+ * performed via a call_rcu() call.
+ */
+
+/* Call set variant specific destroy function and reclaim the set data. */
static void
-ip_set_destroy_set(struct ip_set *set)
+ip_set_destroy_set_variant(struct ip_set *set)
{
- pr_debug("set: %s\n", set->name);
-
/* Must call it without holding any lock */
set->variant->destroy(set);
- module_put(set->type->me);
kfree(set);
}
+static void
+ip_set_destroy_set_variant_rcu(struct rcu_head *head)
+{
+ struct ip_set *set = container_of(head, struct ip_set, rcu);
+
+ ip_set_destroy_set_variant(set);
+}
+
+/* Cancel the garbage collectors and decrement module references */
+static void
+ip_set_destroy_cancel_gc(struct ip_set *set)
+{
+ set->variant->cancel_gc(set);
+ module_put(set->type->me);
+}
+
+/* Use when we may wait for the complete destroy to be finished.
+ */
+static void
+ip_set_destroy_set(struct ip_set *set)
+{
+ ip_set_destroy_cancel_gc(set);
+ ip_set_destroy_set_variant(set);
+}
+
static int
IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
struct ip_set *s;
ip_set_id_t i;
int ret = 0;
@@ -1207,9 +1238,6 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl,
if (unlikely(protocol_min_failed(attr)))
return -IPSET_ERR_PROTOCOL;
- /* Must wait for flush to be really finished in list:set */
- rcu_barrier();
-
/* Commands are serialized and references are
* protected by the ip_set_ref_lock.
* External systems (i.e. xt_set) must call
@@ -1220,8 +1248,10 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl,
* counter, so if it's already zero, we can proceed
* without holding the lock.
*/
- read_lock_bh(&ip_set_ref_lock);
if (!attr[IPSET_ATTR_SETNAME]) {
+ /* Must wait for flush to be really finished in list:set */
+ rcu_barrier();
+ read_lock_bh(&ip_set_ref_lock);
for (i = 0; i < inst->ip_set_max; i++) {
s = ip_set(inst, i);
if (s && (s->ref || s->ref_netlink)) {
@@ -1241,19 +1271,30 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl,
/* Modified by ip_set_destroy() only, which is serialized */
inst->is_destroyed = false;
} else {
+ u32 flags = flag_exist(INFO_NLH(info, nlh));
+ u16 features = 0;
+
+ read_lock_bh(&ip_set_ref_lock);
s = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]),
&i);
if (!s) {
- ret = -ENOENT;
+ if (!(flags & IPSET_FLAG_EXIST))
+ ret = -ENOENT;
goto out;
} else if (s->ref || s->ref_netlink) {
ret = -IPSET_ERR_BUSY;
goto out;
}
+ features = s->type->features;
ip_set(inst, i) = NULL;
read_unlock_bh(&ip_set_ref_lock);
-
- ip_set_destroy_set(s);
+ if (features & IPSET_TYPE_NAME) {
+ /* Must wait for flush to be really finished */
+ rcu_barrier();
+ }
+ /* Must cancel garbage collectors */
+ ip_set_destroy_cancel_gc(s);
+ call_rcu(&s->rcu, ip_set_destroy_set_variant_rcu);
}
return 0;
out:
@@ -1268,18 +1309,19 @@ ip_set_flush_set(struct ip_set *set)
{
pr_debug("set: %s\n", set->name);
- spin_lock_bh(&set->lock);
+ ip_set_lock(set);
set->variant->flush(set);
- spin_unlock_bh(&set->lock);
+ ip_set_unlock(set);
}
static int
IPSET_CBFN(ip_set_flush, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
struct ip_set *s;
ip_set_id_t i;
@@ -1318,9 +1360,10 @@ static int
IPSET_CBFN(ip_set_rename, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
struct ip_set *set, *s;
const char *name2;
ip_set_id_t i;
@@ -1349,7 +1392,7 @@ IPSET_CBFN(ip_set_rename, struct net *net, struct sock *ctnl,
goto out;
}
}
- strncpy(set->name, name2, IPSET_MAXNAMELEN);
+ strscpy_pad(set->name, name2, IPSET_MAXNAMELEN);
out:
write_unlock_bh(&ip_set_ref_lock);
@@ -1369,9 +1412,10 @@ static int
IPSET_CBFN(ip_set_swap, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
struct ip_set *from, *to;
ip_set_id_t from_id, to_id;
char from_name[IPSET_MAXNAMELEN];
@@ -1406,9 +1450,9 @@ IPSET_CBFN(ip_set_swap, struct net *net, struct sock *ctnl,
return -EBUSY;
}
- strncpy(from_name, from->name, IPSET_MAXNAMELEN);
- strncpy(from->name, to->name, IPSET_MAXNAMELEN);
- strncpy(to->name, from_name, IPSET_MAXNAMELEN);
+ strscpy_pad(from_name, from->name, IPSET_MAXNAMELEN);
+ strscpy_pad(from->name, to->name, IPSET_MAXNAMELEN);
+ strscpy_pad(to->name, from_name, IPSET_MAXNAMELEN);
swap(from->ref, to->ref);
ip_set(inst, from_id) = to;
@@ -1490,31 +1534,40 @@ ip_set_dump_policy[IPSET_ATTR_CMD_MAX + 1] = {
};
static int
-dump_init(struct netlink_callback *cb, struct ip_set_net *inst)
+ip_set_dump_start(struct netlink_callback *cb)
{
struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
struct nlattr *cda[IPSET_ATTR_CMD_MAX + 1];
struct nlattr *attr = (void *)nlh + min_len;
+ struct sk_buff *skb = cb->skb;
+ struct ip_set_net *inst = ip_set_pernet(sock_net(skb->sk));
u32 dump_type;
- ip_set_id_t index;
int ret;
ret = NLA_PARSE(cda, IPSET_ATTR_CMD_MAX, attr,
nlh->nlmsg_len - min_len,
ip_set_dump_policy, NULL);
if (ret)
- return ret;
+ goto error;
cb->args[IPSET_CB_PROTO] = nla_get_u8(cda[IPSET_ATTR_PROTOCOL]);
if (cda[IPSET_ATTR_SETNAME]) {
+ ip_set_id_t index;
struct ip_set *set;
+#if HAVE_NETLINK_DUMP_START_ARGS != 4
+ read_lock_bh(&ip_set_ref_lock);
+#endif
set = find_set_and_id(inst, nla_data(cda[IPSET_ATTR_SETNAME]),
&index);
- if (!set)
- return -ENOENT;
-
+#if HAVE_NETLINK_DUMP_START_ARGS != 4
+ read_unlock_bh(&ip_set_ref_lock);
+#endif
+ if (!set) {
+ ret = -ENOENT;
+ goto error;
+ }
dump_type = DUMP_ONE;
cb->args[IPSET_CB_INDEX] = index;
} else {
@@ -1530,10 +1583,17 @@ dump_init(struct netlink_callback *cb, struct ip_set_net *inst)
cb->args[IPSET_CB_DUMP] = dump_type;
return 0;
+
+error:
+ /* We have to create and send the error message manually :-( */
+ if (nlh->nlmsg_flags & NLM_F_ACK) {
+ NETLINK_ACK(cb->skb, nlh, ret, NULL);
+ }
+ return ret;
}
static int
-ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
+ip_set_dump_do(struct sk_buff *skb, struct netlink_callback *cb)
{
ip_set_id_t index = IPSET_INVALID_ID, max;
struct ip_set *set = NULL;
@@ -1545,16 +1605,14 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
int ret = 0;
if (!cb->args[IPSET_CB_DUMP]) {
- ret = dump_init(cb, inst);
+#if HAVE_NETLINK_DUMP_START_ARGS == 4
+ return -EINVAL;
+#else
+ ret = ip_set_dump_start(cb);
if (ret < 0) {
- nlh = nlmsg_hdr(cb->skb);
- /* We have to create and send the error message
- * manually :-(
- */
- if (nlh->nlmsg_flags & NLM_F_ACK)
- NETLINK_ACK(cb->skb, nlh, ret, NULL);
return ret;
}
+#endif
}
if (cb->args[IPSET_CB_INDEX] >= inst->ip_set_max)
@@ -1634,7 +1692,7 @@ dump_last:
goto next_set;
if (set->variant->uref)
set->variant->uref(set, cb, true);
- /* fall through */
+ fallthrough;
default:
ret = set->variant->list(set, skb, cb);
if (!cb->args[IPSET_CB_ARG0])
@@ -1685,26 +1743,30 @@ static int
IPSET_CBFN(ip_set_dump, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
if (unlikely(protocol_min_failed(attr)))
return -IPSET_ERR_PROTOCOL;
#if HAVE_NETLINK_DUMP_START_ARGS == 5
return netlink_dump_start(ctnl, skb, nlh,
- ip_set_dump_start,
+ ip_set_dump_do,
ip_set_dump_done);
#elif HAVE_NETLINK_DUMP_START_ARGS == 6
return netlink_dump_start(ctnl, skb, nlh,
- ip_set_dump_start,
+ ip_set_dump_do,
ip_set_dump_done, 0);
#else
{
struct netlink_dump_control c = {
- .dump = ip_set_dump_start,
+#if HAVE_NETLINK_DUMP_START_ARGS == 4
+ .start = ip_set_dump_start,
+#endif
+ .dump = ip_set_dump_do,
.done = ip_set_dump_done,
};
- return netlink_dump_start(ctnl, skb, nlh, &c);
+ return netlink_dump_start(INFO_SK(info, ctnl), skb, INFO_NLH(info, nlh), &c);
}
#endif
}
@@ -1721,8 +1783,8 @@ static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = {
};
static int
-call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
- struct nlattr *tb[], enum ipset_adt adt,
+CALL_AD(struct net *net, struct sock *ctnl, struct sk_buff *skb,
+ struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt,
u32 flags, bool use_lineno)
{
int ret;
@@ -1730,13 +1792,22 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
bool eexist = flags & IPSET_FLAG_EXIST, retried = false;
do {
- spin_lock_bh(&set->lock);
+ if (retried) {
+ __ip_set_get_netlink(set);
+ nfnl_unlock(NFNL_SUBSYS_IPSET);
+ cond_resched();
+ nfnl_lock(NFNL_SUBSYS_IPSET);
+ __ip_set_put_netlink(set);
+ }
+
+ ip_set_lock(set);
ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
- spin_unlock_bh(&set->lock);
+ ip_set_unlock(set);
retried = true;
- } while (ret == -EAGAIN &&
- set->variant->resize &&
- (ret = set->variant->resize(set, retried)) == 0);
+ } while (ret == -ERANGE ||
+ (ret == -EAGAIN &&
+ set->variant->resize &&
+ (ret = set->variant->resize(set, retried)) == 0));
if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
return 0;
@@ -1755,11 +1826,12 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
skb2 = nlmsg_new(payload, GFP_KERNEL);
if (!skb2)
return -ENOMEM;
- rep = __nlmsg_put(skb2, NETLINK_PORTID(skb),
- nlh->nlmsg_seq, NLMSG_ERROR, payload, 0);
+ rep = nlmsg_put(skb2, NETLINK_PORTID(skb),
+ nlh->nlmsg_seq, NLMSG_ERROR, payload, 0);
errmsg = nlmsg_data(rep);
errmsg->error = ret;
- memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
+ unsafe_memcpy(&errmsg->msg, nlh, nlh->nlmsg_len,
+ /* Bounds checked by the skb layer. */);
cmdattr = (void *)&errmsg->msg + min_len;
ret = NLA_PARSE(cda, IPSET_ATTR_CMD_MAX, cmdattr,
@@ -1774,8 +1846,7 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
*errline = lineno;
- netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb),
- MSG_DONTWAIT);
+ NFNETLINK_UNICAST(ctnl, skb2, net, NETLINK_PORTID(skb));
/* Signal netlink not to send its ACK/errmsg. */
return -EINTR;
}
@@ -1783,19 +1854,18 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
return ret;
}
-static int
-IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl,
- struct sk_buff *skb,
- enum ipset_adt adt,
- const struct nlmsghdr *nlh,
- const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
-{
- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
+static int IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl,
+ struct sk_buff *skb,
+ enum ipset_adt adt,
+ const struct nlmsghdr *nlh,
+ const struct nlattr * const attr[],
+ struct netlink_ext_ack *extack, const struct nfnl_info *info)
+{
+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
struct ip_set *set;
struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
const struct nlattr *nla;
- u32 flags = flag_exist(nlh);
+ u32 flags = flag_exist(INFO_NLH(info, nlh));
bool use_lineno;
int ret = 0;
@@ -1820,7 +1890,7 @@ IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl,
attr[IPSET_ATTR_DATA],
set->type->adt_policy, NULL))
return -IPSET_ERR_PROTOCOL;
- ret = call_ad(ctnl, skb, set, tb, adt, flags,
+ ret = CALL_AD(net, ctnl, skb, set, tb, adt, flags,
use_lineno);
} else {
int nla_rem;
@@ -1831,7 +1901,7 @@ IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl,
NLA_PARSE_NESTED(tb, IPSET_ATTR_ADT_MAX, nla,
set->type->adt_policy, NULL))
return -IPSET_ERR_PROTOCOL;
- ret = call_ad(ctnl, skb, set, tb, adt,
+ ret = CALL_AD(net, ctnl, skb, set, tb, adt,
flags, use_lineno);
if (ret < 0)
return ret;
@@ -1844,20 +1914,22 @@ static int
IPSET_CBFN(ip_set_uadd, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
- return IPSET_CBFN_AD(ip_set_ad, net, ctnl, skb,
- IPSET_ADD, nlh, attr, extack);
+ return IPSET_CBFN_AD(ip_set_ad, INFO_NET(info, net), INFO_SK(info, ctnl), skb,
+ IPSET_ADD, INFO_NLH(info, nlh), attr, extack, info);
}
static int
IPSET_CBFN(ip_set_udel, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
- return IPSET_CBFN_AD(ip_set_ad, net, ctnl, skb,
- IPSET_DEL, nlh, attr, extack);
+ return IPSET_CBFN_AD(ip_set_ad, INFO_NET(info, net), INFO_SK(info, ctnl), skb,
+ IPSET_DEL, INFO_NLH(info, nlh), attr, extack, info);
}
static int
@@ -1865,12 +1937,14 @@ IPSET_CBFN(ip_set_utest, struct net *net, struct sock *ctnl,
struct sk_buff *skb,
const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
struct ip_set *set;
struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
int ret = 0;
+ u32 lineno;
if (unlikely(protocol_min_failed(attr) ||
!attr[IPSET_ATTR_SETNAME] ||
@@ -1887,7 +1961,7 @@ IPSET_CBFN(ip_set_utest, struct net *net, struct sock *ctnl,
return -IPSET_ERR_PROTOCOL;
rcu_read_lock_bh();
- ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
+ ret = set->variant->uadt(set, tb, IPSET_TEST, &lineno, 0, 0);
rcu_read_unlock_bh();
/* Userspace can't trigger element to be re-added */
if (ret == -EAGAIN)
@@ -1902,13 +1976,13 @@ static int
IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
const struct ip_set *set;
struct sk_buff *skb2;
struct nlmsghdr *nlh2;
- int ret = 0;
if (unlikely(protocol_min_failed(attr) ||
!attr[IPSET_ATTR_SETNAME]))
@@ -1922,7 +1996,7 @@ IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl,
if (!skb2)
return -ENOMEM;
- nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0,
+ nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0,
IPSET_CMD_HEADER);
if (!nlh2)
goto nlmsg_failure;
@@ -1934,11 +2008,7 @@ IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl,
goto nla_put_failure;
nlmsg_end(skb2, nlh2);
- ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT);
- if (ret < 0)
- return ret;
-
- return 0;
+ return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb));
nla_put_failure:
nlmsg_cancel(skb2, nlh2);
@@ -1960,7 +2030,8 @@ static int
IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
struct sk_buff *skb2;
struct nlmsghdr *nlh2;
@@ -1983,7 +2054,7 @@ IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl,
if (!skb2)
return -ENOMEM;
- nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0,
+ nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0,
IPSET_CMD_TYPE);
if (!nlh2)
goto nlmsg_failure;
@@ -1996,11 +2067,7 @@ IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl,
nlmsg_end(skb2, nlh2);
pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len);
- ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT);
- if (ret < 0)
- return ret;
-
- return 0;
+ return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb));
nla_put_failure:
nlmsg_cancel(skb2, nlh2);
@@ -2020,11 +2087,11 @@ static int
IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
struct sk_buff *skb2;
struct nlmsghdr *nlh2;
- int ret = 0;
if (unlikely(!attr[IPSET_ATTR_PROTOCOL]))
return -IPSET_ERR_PROTOCOL;
@@ -2033,7 +2100,7 @@ IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl,
if (!skb2)
return -ENOMEM;
- nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0,
+ nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0,
IPSET_CMD_PROTOCOL);
if (!nlh2)
goto nlmsg_failure;
@@ -2043,11 +2110,7 @@ IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl,
goto nla_put_failure;
nlmsg_end(skb2, nlh2);
- ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT);
- if (ret < 0)
- return ret;
-
- return 0;
+ return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb));
nla_put_failure:
nlmsg_cancel(skb2, nlh2);
@@ -2062,14 +2125,14 @@ static int
IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
struct sk_buff *skb2;
struct nlmsghdr *nlh2;
ip_set_id_t id = IPSET_INVALID_ID;
const struct ip_set *set;
- int ret = 0;
if (unlikely(protocol_failed(attr) ||
!attr[IPSET_ATTR_SETNAME]))
@@ -2083,7 +2146,7 @@ IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl,
if (!skb2)
return -ENOMEM;
- nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0,
+ nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0,
IPSET_CMD_GET_BYNAME);
if (!nlh2)
goto nlmsg_failure;
@@ -2093,11 +2156,7 @@ IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl,
goto nla_put_failure;
nlmsg_end(skb2, nlh2);
- ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT);
- if (ret < 0)
- return ret;
-
- return 0;
+ return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb));
nla_put_failure:
nlmsg_cancel(skb2, nlh2);
@@ -2115,14 +2174,14 @@ static int
IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const attr[],
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ const struct nfnl_info *info)
{
- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
struct sk_buff *skb2;
struct nlmsghdr *nlh2;
ip_set_id_t id = IPSET_INVALID_ID;
const struct ip_set *set;
- int ret = 0;
if (unlikely(protocol_failed(attr) ||
!attr[IPSET_ATTR_INDEX]))
@@ -2139,7 +2198,7 @@ IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl,
if (!skb2)
return -ENOMEM;
- nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0,
+ nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0,
IPSET_CMD_GET_BYINDEX);
if (!nlh2)
goto nlmsg_failure;
@@ -2148,11 +2207,7 @@ IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl,
goto nla_put_failure;
nlmsg_end(skb2, nlh2);
- ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT);
- if (ret < 0)
- return ret;
-
- return 0;
+ return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb));
nla_put_failure:
nlmsg_cancel(skb2, nlh2);
@@ -2164,80 +2219,96 @@ nlmsg_failure:
static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = {
[IPSET_CMD_NONE] = {
.call = ip_set_none,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
},
[IPSET_CMD_CREATE] = {
.call = ip_set_create,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_create_policy,
},
[IPSET_CMD_DESTROY] = {
.call = ip_set_destroy,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_setname_policy,
},
[IPSET_CMD_FLUSH] = {
.call = ip_set_flush,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_setname_policy,
},
[IPSET_CMD_RENAME] = {
.call = ip_set_rename,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_setname2_policy,
},
[IPSET_CMD_SWAP] = {
.call = ip_set_swap,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_setname2_policy,
},
[IPSET_CMD_LIST] = {
.call = ip_set_dump,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_dump_policy,
},
[IPSET_CMD_SAVE] = {
.call = ip_set_dump,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_setname_policy,
},
[IPSET_CMD_ADD] = {
.call = ip_set_uadd,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_adt_policy,
},
[IPSET_CMD_DEL] = {
.call = ip_set_udel,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_adt_policy,
},
[IPSET_CMD_TEST] = {
.call = ip_set_utest,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_adt_policy,
},
[IPSET_CMD_HEADER] = {
.call = ip_set_header,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_setname_policy,
},
[IPSET_CMD_TYPE] = {
.call = ip_set_type,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_type_policy,
},
[IPSET_CMD_PROTOCOL] = {
.call = ip_set_protocol,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_protocol_policy,
},
[IPSET_CMD_GET_BYNAME] = {
.call = ip_set_byname,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_setname_policy,
},
[IPSET_CMD_GET_BYINDEX] = {
.call = ip_set_byindex,
+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
.attr_count = IPSET_ATTR_CMD_MAX,
.policy = ip_set_index_policy,
},
@@ -2410,7 +2481,6 @@ ip_set_net_init(struct net *net)
#else
goto err_alloc;
#endif
- inst->is_deleted = false;
inst->is_destroyed = false;
rcu_assign_pointer(inst->ip_set_list, list);
return 0;
@@ -2427,20 +2497,6 @@ ip_set_net_exit(struct net *net)
{
struct ip_set_net *inst = ip_set_pernet(net);
- struct ip_set *set = NULL;
- ip_set_id_t i;
-
- inst->is_deleted = true; /* flag for ip_set_nfnl_put */
-
- nfnl_lock(NFNL_SUBSYS_IPSET);
- for (i = 0; i < inst->ip_set_max; i++) {
- set = ip_set(inst, i);
- if (set) {
- ip_set(inst, i) = NULL;
- ip_set_destroy_set(set);
- }
- }
- nfnl_unlock(NFNL_SUBSYS_IPSET);
kvfree(rcu_dereference_protected(inst->ip_set_list, 1));
#ifndef HAVE_NET_OPS_ID
kvfree(inst);
@@ -2505,8 +2561,8 @@ ip_set_fini(void)
{
nf_unregister_sockopt(&so_set);
nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
-
UNREGISTER_PERNET_SUBSYS(&ip_set_net_ops);
+
pr_debug("these are the famous last words\n");
}
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_gen.h b/kernel/net/netfilter/ipset/ip_set_hash_gen.h
index 1767fed..76c3894 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/kernel/net/netfilter/ipset/ip_set_hash_gen.h
@@ -8,13 +8,21 @@
#include <linux/rcupdate.h>
#include <linux/jhash.h>
#include <linux/types.h>
+#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/ipset/ip_set.h>
-#define __ipset_dereference_protected(p, c) rcu_dereference_protected(p, c)
-#define ipset_dereference_protected(p, set) \
- __ipset_dereference_protected(p, lockdep_is_held(&(set)->lock))
-
-#define rcu_dereference_bh_nfnl(p) rcu_dereference_bh_check(p, 1)
+#define __ipset_dereference(p) \
+ rcu_dereference_protected(p, 1)
+#define ipset_dereference_nfnl(p) \
+ rcu_dereference_protected(p, \
+ lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))
+#define ipset_dereference_set(p, set) \
+ rcu_dereference_protected(p, \
+ lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \
+ lockdep_is_held(&(set)->lock))
+#define ipset_dereference_bh_nfnl(p) \
+ rcu_dereference_bh_check(p, \
+ lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))
/* Hashing which uses arrays to resolve clashing. The hash table is resized
* (doubled) when searching becomes too long.
@@ -30,37 +38,12 @@
*/
/* Number of elements to store in an initial array block */
-#define AHASH_INIT_SIZE 4
+#define AHASH_INIT_SIZE 2
/* Max number of elements to store in an array block */
-#define AHASH_MAX_SIZE (3 * AHASH_INIT_SIZE)
+#define AHASH_MAX_SIZE (6 * AHASH_INIT_SIZE)
/* Max muber of elements in the array block when tuned */
#define AHASH_MAX_TUNED 64
-
-/* Max number of elements can be tuned */
-#ifdef IP_SET_HASH_WITH_MULTI
-#define AHASH_MAX(h) ((h)->ahash_max)
-
-static u8
-tune_ahash_max(u8 curr, u32 multi)
-{
- u32 n;
-
- if (multi < curr)
- return curr;
-
- n = curr + AHASH_INIT_SIZE;
- /* Currently, at listing one hash bucket must fit into a message.
- * Therefore we have a hard limit here.
- */
- return n > curr && n <= AHASH_MAX_TUNED ? n : curr;
-}
-
-#define TUNE_AHASH_MAX(h, multi) \
- ((h)->ahash_max = tune_ahash_max((h)->ahash_max, multi))
-#else
-#define AHASH_MAX(h) AHASH_MAX_SIZE
-#define TUNE_AHASH_MAX(h, multi)
-#endif
+#define AHASH_MAX(h) ((h)->bucketsize)
/* A hash bucket */
struct hbucket {
@@ -69,16 +52,40 @@ struct hbucket {
DECLARE_BITMAP(used, AHASH_MAX_TUNED);
u8 size; /* size of the array */
u8 pos; /* position of the first free entry */
- unsigned char value[0] /* the array of the values */
+ unsigned char value[] /* the array of the values */
__aligned(__alignof__(u64));
};
+/* Region size for locking == 2^HTABLE_REGION_BITS */
+#define HTABLE_REGION_BITS 10
+#define ahash_numof_locks(htable_bits) \
+ ((htable_bits) < HTABLE_REGION_BITS ? 1 \
+ : jhash_size((htable_bits) - HTABLE_REGION_BITS))
+#define ahash_sizeof_regions(htable_bits) \
+ (ahash_numof_locks(htable_bits) * sizeof(struct ip_set_region))
+#define ahash_region(n, htable_bits) \
+ ((n) % ahash_numof_locks(htable_bits))
+#define ahash_bucket_start(h, htable_bits) \
+ ((htable_bits) < HTABLE_REGION_BITS ? 0 \
+ : (h) * jhash_size(HTABLE_REGION_BITS))
+#define ahash_bucket_end(h, htable_bits) \
+ ((htable_bits) < HTABLE_REGION_BITS ? jhash_size(htable_bits) \
+ : ((h) + 1) * jhash_size(HTABLE_REGION_BITS))
+
+struct htable_gc {
+ struct delayed_work dwork;
+ struct ip_set *set; /* Set the gc belongs to */
+ u32 region; /* Last gc run position */
+};
+
/* The hash table: the table size stored here in order to make resizing easy */
struct htable {
atomic_t ref; /* References for resizing */
- atomic_t uref; /* References for dumping */
+ atomic_t uref; /* References for dumping and gc */
u8 htable_bits; /* size of hash table == 2^htable_bits */
- struct hbucket __rcu *bucket[0]; /* hashtable buckets */
+ u32 maxelem; /* Maxelem per region */
+ struct ip_set_region *hregion; /* Region locks and ext sizes */
+ struct hbucket __rcu *bucket[]; /* hashtable buckets */
};
#define hbucket(h, i) ((h)->bucket[i])
@@ -101,31 +108,17 @@ htable_size(u8 hbits)
{
size_t hsize;
- /* We must fit both into u32 in jhash and size_t */
+ /* We must fit both into u32 in jhash and INT_MAX in kvmalloc_node() */
if (hbits > 31)
return 0;
hsize = jhash_size(hbits);
- if ((((size_t)-1) - sizeof(struct htable)) / sizeof(struct hbucket *)
+ if ((INT_MAX - sizeof(struct htable)) / sizeof(struct hbucket *)
< hsize)
return 0;
return hsize * sizeof(struct hbucket *) + sizeof(struct htable);
}
-/* Compute htable_bits from the user input parameter hashsize */
-static u8
-htable_bits(u32 hashsize)
-{
- /* Assume that hashsize == 2^htable_bits */
- u8 bits = fls(hashsize - 1);
-
- if (jhash_size(bits) != hashsize)
- /* Round up to the first 2^n value */
- bits = fls(hashsize);
-
- return bits;
-}
-
#ifdef IP_SET_HASH_WITH_NETS
#if IPSET_NET_COUNT > 1
#define __CIDR(cidr, i) (cidr[i])
@@ -163,6 +156,21 @@ htable_bits(u32 hashsize)
#define NLEN 0
#endif /* IP_SET_HASH_WITH_NETS */
+#define SET_ELEM_EXPIRED(set, d) \
+ (SET_WITH_TIMEOUT(set) && \
+ ip_set_timeout_expired(ext_timeout(d, set)))
+
+#if defined(IP_SET_HASH_WITH_NETMASK) || defined(IP_SET_HASH_WITH_BITMASK)
+static const union nf_inet_addr onesmask = {
+ .all[0] = 0xffffffff,
+ .all[1] = 0xffffffff,
+ .all[2] = 0xffffffff,
+ .all[3] = 0xffffffff
+};
+
+static const union nf_inet_addr zeromask = {};
+#endif
+
#endif /* _IP_SET_HASH_GEN_H */
#ifndef MTYPE
@@ -206,12 +214,15 @@ htable_bits(u32 hashsize)
#undef mtype_test_cidrs
#undef mtype_test
#undef mtype_uref
-#undef mtype_expire
#undef mtype_resize
+#undef mtype_ext_size
+#undef mtype_resize_ad
#undef mtype_head
#undef mtype_list
+#undef mtype_gc_do
#undef mtype_gc
#undef mtype_gc_init
+#undef mtype_cancel_gc
#undef mtype_variant
#undef mtype_data_match
@@ -248,12 +259,15 @@ htable_bits(u32 hashsize)
#define mtype_test_cidrs IPSET_TOKEN(MTYPE, _test_cidrs)
#define mtype_test IPSET_TOKEN(MTYPE, _test)
#define mtype_uref IPSET_TOKEN(MTYPE, _uref)
-#define mtype_expire IPSET_TOKEN(MTYPE, _expire)
#define mtype_resize IPSET_TOKEN(MTYPE, _resize)
+#define mtype_ext_size IPSET_TOKEN(MTYPE, _ext_size)
+#define mtype_resize_ad IPSET_TOKEN(MTYPE, _resize_ad)
#define mtype_head IPSET_TOKEN(MTYPE, _head)
#define mtype_list IPSET_TOKEN(MTYPE, _list)
+#define mtype_gc_do IPSET_TOKEN(MTYPE, _gc_do)
#define mtype_gc IPSET_TOKEN(MTYPE, _gc)
#define mtype_gc_init IPSET_TOKEN(MTYPE, _gc_init)
+#define mtype_cancel_gc IPSET_TOKEN(MTYPE, _cancel_gc)
#define mtype_variant IPSET_TOKEN(MTYPE, _variant)
#define mtype_data_match IPSET_TOKEN(MTYPE, _data_match)
@@ -276,36 +290,44 @@ htable_bits(u32 hashsize)
/* The generic hash structure */
struct htype {
struct htable __rcu *table; /* the hash table */
- struct timer_list gc; /* garbage collection when timeout enabled */
-#ifdef HAVE_TIMER_SETUP
- struct ip_set *set; /* attached to this ip_set */
-#endif
+ struct htable_gc gc; /* gc workqueue */
u32 maxelem; /* max elements in the hash */
u32 initval; /* random jhash init value */
#ifdef IP_SET_HASH_WITH_MARKMASK
u32 markmask; /* markmask value for mark mask to store */
#endif
-#ifdef IP_SET_HASH_WITH_MULTI
- u8 ahash_max; /* max elements in an array block */
-#endif
-#ifdef IP_SET_HASH_WITH_NETMASK
+ u8 bucketsize; /* max elements in an array block */
+#if defined(IP_SET_HASH_WITH_NETMASK) || defined(IP_SET_HASH_WITH_BITMASK)
u8 netmask; /* netmask value for subnets to store */
+ union nf_inet_addr bitmask; /* stores bitmask */
#endif
+ struct list_head ad; /* Resize add|del backlist */
struct mtype_elem next; /* temporary storage for uadd */
#ifdef IP_SET_HASH_WITH_NETS
struct net_prefixes nets[NLEN]; /* book-keeping of prefixes */
#endif
};
+/* ADD|DEL entries saved during resize */
+struct mtype_resize_ad {
+ struct list_head list;
+ enum ipset_adt ad; /* ADD|DEL element */
+ struct mtype_elem d; /* Element value */
+ struct ip_set_ext ext; /* Extensions for ADD */
+ struct ip_set_ext mext; /* Target extensions for ADD */
+ u32 flags; /* Flags for ADD */
+};
+
#ifdef IP_SET_HASH_WITH_NETS
/* Network cidr size book keeping when the hash stores different
* sized networks. cidr == real cidr + 1 to support /0.
*/
static void
-mtype_add_cidr(struct htype *h, u8 cidr, u8 n)
+mtype_add_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n)
{
int i, j;
+ spin_lock_bh(&set->lock);
/* Add in increasing prefix order, so larger cidr first */
for (i = 0, j = -1; i < NLEN && h->nets[i].cidr[n]; i++) {
if (j != -1) {
@@ -314,7 +336,7 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n)
j = i;
} else if (h->nets[i].cidr[n] == cidr) {
h->nets[CIDR_POS(cidr)].nets[n]++;
- return;
+ goto unlock;
}
}
if (j != -1) {
@@ -323,24 +345,29 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n)
}
h->nets[i].cidr[n] = cidr;
h->nets[CIDR_POS(cidr)].nets[n] = 1;
+unlock:
+ spin_unlock_bh(&set->lock);
}
static void
-mtype_del_cidr(struct htype *h, u8 cidr, u8 n)
+mtype_del_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n)
{
u8 i, j, net_end = NLEN - 1;
+ spin_lock_bh(&set->lock);
for (i = 0; i < NLEN; i++) {
if (h->nets[i].cidr[n] != cidr)
continue;
h->nets[CIDR_POS(cidr)].nets[n]--;
if (h->nets[CIDR_POS(cidr)].nets[n] > 0)
- return;
+ goto unlock;
for (j = i; j < net_end && h->nets[j].cidr[n]; j++)
h->nets[j].cidr[n] = h->nets[j + 1].cidr[n];
h->nets[j].cidr[n] = 0;
- return;
+ goto unlock;
}
+unlock:
+ spin_unlock_bh(&set->lock);
}
#endif
@@ -348,7 +375,7 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 n)
static size_t
mtype_ahash_memsize(const struct htype *h, const struct htable *t)
{
- return sizeof(*h) + sizeof(*t);
+ return sizeof(*h) + sizeof(*t) + ahash_sizeof_regions(t->htable_bits);
}
/* Get the ith element from the array block n */
@@ -372,24 +399,29 @@ mtype_flush(struct ip_set *set)
struct htype *h = set->data;
struct htable *t;
struct hbucket *n;
- u32 i;
-
- t = ipset_dereference_protected(h->table, set);
- for (i = 0; i < jhash_size(t->htable_bits); i++) {
- n = __ipset_dereference_protected(hbucket(t, i), 1);
- if (!n)
- continue;
- if (set->extensions & IPSET_EXT_DESTROY)
- mtype_ext_cleanup(set, n);
- /* FIXME: use slab cache */
- rcu_assign_pointer(hbucket(t, i), NULL);
- kfree_rcu(n, rcu);
+ u32 r, i;
+
+ t = ipset_dereference_nfnl(h->table);
+ for (r = 0; r < ahash_numof_locks(t->htable_bits); r++) {
+ spin_lock_bh(&t->hregion[r].lock);
+ for (i = ahash_bucket_start(r, t->htable_bits);
+ i < ahash_bucket_end(r, t->htable_bits); i++) {
+ n = __ipset_dereference(hbucket(t, i));
+ if (!n)
+ continue;
+ if (set->extensions & IPSET_EXT_DESTROY)
+ mtype_ext_cleanup(set, n);
+ /* FIXME: use slab cache */
+ rcu_assign_pointer(hbucket(t, i), NULL);
+ kfree_rcu(n, rcu);
+ }
+ t->hregion[r].ext_size = 0;
+ t->hregion[r].elements = 0;
+ spin_unlock_bh(&t->hregion[r].lock);
}
#ifdef IP_SET_HASH_WITH_NETS
memset(h->nets, 0, sizeof(h->nets));
#endif
- set->elements = 0;
- set->ext_size = 0;
}
/* Destroy the hashtable part of the set */
@@ -400,7 +432,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy)
u32 i;
for (i = 0; i < jhash_size(t->htable_bits); i++) {
- n = __ipset_dereference_protected(hbucket(t, i), 1);
+ n = (__force struct hbucket *)hbucket(t, i);
if (!n)
continue;
if (set->extensions & IPSET_EXT_DESTROY && ext_destroy)
@@ -409,6 +441,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy)
kfree(n);
}
+ ip_set_free(t->hregion);
ip_set_free(t);
}
@@ -417,28 +450,18 @@ static void
mtype_destroy(struct ip_set *set)
{
struct htype *h = set->data;
+ struct list_head *l, *lt;
- if (SET_WITH_TIMEOUT(set))
- del_timer_sync(&h->gc);
-
- mtype_ahash_destroy(set,
- __ipset_dereference_protected(h->table, 1), true);
+ mtype_ahash_destroy(set, (__force struct htable *)h->table, true);
+ list_for_each_safe(l, lt, &h->ad) {
+ list_del(l);
+ kfree(l);
+ }
kfree(h);
set->data = NULL;
}
-static void
-mtype_gc_init(struct ip_set *set, void (*gc)(GC_ARG))
-{
- struct htype *h = set->data;
-
- TIMER_SETUP(&h->gc, gc);
- mod_timer(&h->gc, jiffies + IPSET_GC_PERIOD(set->timeout) * HZ);
- pr_debug("gc initialized, run in every %u\n",
- IPSET_GC_PERIOD(set->timeout));
-}
-
static bool
mtype_same_set(const struct ip_set *a, const struct ip_set *b)
{
@@ -448,8 +471,8 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b)
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem &&
a->timeout == b->timeout &&
-#ifdef IP_SET_HASH_WITH_NETMASK
- x->netmask == y->netmask &&
+#if defined(IP_SET_HASH_WITH_NETMASK) || defined(IP_SET_HASH_WITH_BITMASK)
+ nf_inet_addr_cmp(&x->bitmask, &y->bitmask) &&
#endif
#ifdef IP_SET_HASH_WITH_MARKMASK
x->markmask == y->markmask &&
@@ -457,11 +480,9 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b)
a->extensions == b->extensions;
}
-/* Delete expired elements from the hashtable */
static void
-mtype_expire(struct ip_set *set, struct htype *h)
+mtype_gc_do(struct ip_set *set, struct htype *h, struct htable *t, u32 r)
{
- struct htable *t;
struct hbucket *n, *tmp;
struct mtype_elem *data;
u32 i, j, d;
@@ -469,10 +490,12 @@ mtype_expire(struct ip_set *set, struct htype *h)
#ifdef IP_SET_HASH_WITH_NETS
u8 k;
#endif
+ u8 htable_bits = t->htable_bits;
- t = ipset_dereference_protected(h->table, set);
- for (i = 0; i < jhash_size(t->htable_bits); i++) {
- n = __ipset_dereference_protected(hbucket(t, i), 1);
+ spin_lock_bh(&t->hregion[r].lock);
+ for (i = ahash_bucket_start(r, htable_bits);
+ i < ahash_bucket_end(r, htable_bits); i++) {
+ n = __ipset_dereference(hbucket(t, i));
if (!n)
continue;
for (j = 0, d = 0; j < n->pos; j++) {
@@ -488,58 +511,108 @@ mtype_expire(struct ip_set *set, struct htype *h)
smp_mb__after_atomic();
#ifdef IP_SET_HASH_WITH_NETS
for (k = 0; k < IPSET_NET_COUNT; k++)
- mtype_del_cidr(h,
+ mtype_del_cidr(set, h,
NCIDR_PUT(DCIDR_GET(data->cidr, k)),
k);
#endif
+ t->hregion[r].elements--;
ip_set_ext_destroy(set, data);
- set->elements--;
d++;
}
if (d >= AHASH_INIT_SIZE) {
if (d >= n->size) {
- set->ext_size -= ext_size(n->size, dsize);
+ t->hregion[r].ext_size -=
+ ext_size(n->size, dsize);
rcu_assign_pointer(hbucket(t, i), NULL);
kfree_rcu(n, rcu);
continue;
}
tmp = kzalloc(sizeof(*tmp) +
- (n->size - AHASH_INIT_SIZE) * dsize,
- GFP_ATOMIC);
+ (n->size - AHASH_INIT_SIZE) * dsize,
+ GFP_ATOMIC);
if (!tmp)
- /* Still try to delete expired elements */
+ /* Still try to delete expired elements. */
continue;
tmp->size = n->size - AHASH_INIT_SIZE;
for (j = 0, d = 0; j < n->pos; j++) {
if (!test_bit(j, n->used))
continue;
data = ahash_data(n, j, dsize);
- memcpy(tmp->value + d * dsize, data, dsize);
+ memcpy(tmp->value + d * dsize,
+ data, dsize);
set_bit(d, tmp->used);
d++;
}
tmp->pos = d;
- set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize);
+ t->hregion[r].ext_size -=
+ ext_size(AHASH_INIT_SIZE, dsize);
rcu_assign_pointer(hbucket(t, i), tmp);
kfree_rcu(n, rcu);
}
}
+ spin_unlock_bh(&t->hregion[r].lock);
}
static void
-mtype_gc(GC_ARG)
+mtype_gc(struct work_struct *work)
{
- INIT_GC_VARS(htype, h);
+ struct htable_gc *gc;
+ struct ip_set *set;
+ struct htype *h;
+ struct htable *t;
+ u32 r, numof_locks;
+ unsigned int next_run;
+
+ gc = container_of(work, struct htable_gc, dwork.work);
+ set = gc->set;
+ h = set->data;
- pr_debug("called\n");
spin_lock_bh(&set->lock);
- mtype_expire(set, h);
+ t = ipset_dereference_set(h->table, set);
+ atomic_inc(&t->uref);
+ numof_locks = ahash_numof_locks(t->htable_bits);
+ r = gc->region++;
+ if (r >= numof_locks) {
+ r = gc->region = 0;
+ }
+ next_run = (IPSET_GC_PERIOD(set->timeout) * HZ) / numof_locks;
+ if (next_run < HZ/10)
+ next_run = HZ/10;
spin_unlock_bh(&set->lock);
- h->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
- add_timer(&h->gc);
+ mtype_gc_do(set, h, t, r);
+
+ if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
+ pr_debug("Table destroy after resize by expire: %p\n", t);
+ mtype_ahash_destroy(set, t, false);
+ }
+
+ queue_delayed_work(system_power_efficient_wq, &gc->dwork, next_run);
}
+static void
+mtype_gc_init(struct htable_gc *gc)
+{
+ INIT_DEFERRABLE_WORK(&gc->dwork, mtype_gc);
+ queue_delayed_work(system_power_efficient_wq, &gc->dwork, HZ);
+}
+
+static void
+mtype_cancel_gc(struct ip_set *set)
+{
+ struct htype *h = set->data;
+
+ if (SET_WITH_TIMEOUT(set))
+ cancel_delayed_work_sync(&h->gc.dwork);
+}
+
+static int
+mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
+ struct ip_set_ext *mext, u32 flags);
+static int
+mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
+ struct ip_set_ext *mext, u32 flags);
+
/* Resize a hash: create a new hash table with doubling the hashsize
* and inserting the elements to it. Repeat until we succeed or
* fail due to memory pressures.
@@ -550,7 +623,7 @@ mtype_resize(struct ip_set *set, bool retried)
struct htype *h = set->data;
struct htable *t, *orig;
u8 htable_bits;
- size_t extsize, dsize = set->dsize;
+ size_t hsize, dsize = set->dsize;
#ifdef IP_SET_HASH_WITH_NETS
u8 flags;
struct mtype_elem *tmp;
@@ -558,7 +631,9 @@ mtype_resize(struct ip_set *set, bool retried)
struct mtype_elem *data;
struct mtype_elem *d;
struct hbucket *n, *m;
- u32 i, j, key;
+ struct list_head *l, *lt;
+ struct mtype_resize_ad *x;
+ u32 i, j, r, nr, key;
int ret;
#ifdef IP_SET_HASH_WITH_NETS
@@ -566,108 +641,140 @@ mtype_resize(struct ip_set *set, bool retried)
if (!tmp)
return -ENOMEM;
#endif
- rcu_read_lock_bh();
- orig = rcu_dereference_bh_nfnl(h->table);
+ orig = ipset_dereference_bh_nfnl(h->table);
htable_bits = orig->htable_bits;
- rcu_read_unlock_bh();
retry:
ret = 0;
htable_bits++;
- if (!htable_bits) {
- /* In case we have plenty of memory :-) */
- pr_warn("Cannot increase the hashsize of set %s further\n",
- set->name);
- ret = -IPSET_ERR_HASH_FULL;
+ if (!htable_bits)
+ goto hbwarn;
+ hsize = htable_size(htable_bits);
+ if (!hsize)
+ goto hbwarn;
+ t = ip_set_alloc(hsize);
+ if (!t) {
+ ret = -ENOMEM;
goto out;
}
- t = ip_set_alloc(htable_size(htable_bits));
- if (!t) {
+ t->hregion = ip_set_alloc(ahash_sizeof_regions(htable_bits));
+ if (!t->hregion) {
+ ip_set_free(t);
ret = -ENOMEM;
goto out;
}
t->htable_bits = htable_bits;
+ t->maxelem = h->maxelem / ahash_numof_locks(htable_bits);
+ for (i = 0; i < ahash_numof_locks(htable_bits); i++)
+ spin_lock_init(&t->hregion[i].lock);
- spin_lock_bh(&set->lock);
- orig = __ipset_dereference_protected(h->table, 1);
- /* There can't be another parallel resizing, but dumping is possible */
+ /* There can't be another parallel resizing,
+ * but dumping, gc, kernel side add/del are possible
+ */
+ orig = ipset_dereference_bh_nfnl(h->table);
atomic_set(&orig->ref, 1);
atomic_inc(&orig->uref);
- extsize = 0;
pr_debug("attempt to resize set %s from %u to %u, t %p\n",
set->name, orig->htable_bits, htable_bits, orig);
- for (i = 0; i < jhash_size(orig->htable_bits); i++) {
- n = __ipset_dereference_protected(hbucket(orig, i), 1);
- if (!n)
- continue;
- for (j = 0; j < n->pos; j++) {
- if (!test_bit(j, n->used))
+ for (r = 0; r < ahash_numof_locks(orig->htable_bits); r++) {
+ /* Expire may replace a hbucket with another one */
+ rcu_read_lock_bh();
+ for (i = ahash_bucket_start(r, orig->htable_bits);
+ i < ahash_bucket_end(r, orig->htable_bits); i++) {
+ n = __ipset_dereference(hbucket(orig, i));
+ if (!n)
continue;
- data = ahash_data(n, j, dsize);
+ for (j = 0; j < n->pos; j++) {
+ if (!test_bit(j, n->used))
+ continue;
+ data = ahash_data(n, j, dsize);
+ if (SET_ELEM_EXPIRED(set, data))
+ continue;
#ifdef IP_SET_HASH_WITH_NETS
- /* We have readers running parallel with us,
- * so the live data cannot be modified.
- */
- flags = 0;
- memcpy(tmp, data, dsize);
- data = tmp;
- mtype_data_reset_flags(data, &flags);
+ /* We have readers running parallel with us,
+ * so the live data cannot be modified.
+ */
+ flags = 0;
+ memcpy(tmp, data, dsize);
+ data = tmp;
+ mtype_data_reset_flags(data, &flags);
#endif
- key = HKEY(data, h->initval, htable_bits);
- m = __ipset_dereference_protected(hbucket(t, key), 1);
- if (!m) {
- m = kzalloc(sizeof(*m) +
+ key = HKEY(data, h->initval, htable_bits);
+ m = __ipset_dereference(hbucket(t, key));
+ nr = ahash_region(key, htable_bits);
+ if (!m) {
+ m = kzalloc(sizeof(*m) +
AHASH_INIT_SIZE * dsize,
GFP_ATOMIC);
- if (!m) {
- ret = -ENOMEM;
- goto cleanup;
- }
- m->size = AHASH_INIT_SIZE;
- extsize += ext_size(AHASH_INIT_SIZE, dsize);
- RCU_INIT_POINTER(hbucket(t, key), m);
- } else if (m->pos >= m->size) {
- struct hbucket *ht;
-
- if (m->size >= AHASH_MAX(h)) {
- ret = -EAGAIN;
- } else {
- ht = kzalloc(sizeof(*ht) +
+ if (!m) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ m->size = AHASH_INIT_SIZE;
+ t->hregion[nr].ext_size +=
+ ext_size(AHASH_INIT_SIZE,
+ dsize);
+ RCU_INIT_POINTER(hbucket(t, key), m);
+ } else if (m->pos >= m->size) {
+ struct hbucket *ht;
+
+ if (m->size >= AHASH_MAX(h)) {
+ ret = -EAGAIN;
+ } else {
+ ht = kzalloc(sizeof(*ht) +
(m->size + AHASH_INIT_SIZE)
* dsize,
GFP_ATOMIC);
- if (!ht)
- ret = -ENOMEM;
+ if (!ht)
+ ret = -ENOMEM;
+ }
+ if (ret < 0)
+ goto cleanup;
+ memcpy(ht, m, sizeof(struct hbucket) +
+ m->size * dsize);
+ ht->size = m->size + AHASH_INIT_SIZE;
+ t->hregion[nr].ext_size +=
+ ext_size(AHASH_INIT_SIZE,
+ dsize);
+ kfree(m);
+ m = ht;
+ RCU_INIT_POINTER(hbucket(t, key), ht);
}
- if (ret < 0)
- goto cleanup;
- memcpy(ht, m, sizeof(struct hbucket) +
- m->size * dsize);
- ht->size = m->size + AHASH_INIT_SIZE;
- extsize += ext_size(AHASH_INIT_SIZE, dsize);
- kfree(m);
- m = ht;
- RCU_INIT_POINTER(hbucket(t, key), ht);
- }
- d = ahash_data(m, m->pos, dsize);
- memcpy(d, data, dsize);
- set_bit(m->pos++, m->used);
+ d = ahash_data(m, m->pos, dsize);
+ memcpy(d, data, dsize);
+ set_bit(m->pos++, m->used);
+ t->hregion[nr].elements++;
#ifdef IP_SET_HASH_WITH_NETS
- mtype_data_reset_flags(d, &flags);
+ mtype_data_reset_flags(d, &flags);
#endif
+ }
}
+ rcu_read_unlock_bh();
}
- rcu_assign_pointer(h->table, t);
- set->ext_size = extsize;
- spin_unlock_bh(&set->lock);
+ /* There can't be any other writer. */
+ rcu_assign_pointer(h->table, t);
/* Give time to other readers of the set */
synchronize_rcu();
pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name,
orig->htable_bits, orig, t->htable_bits, t);
- /* If there's nobody else dumping the table, destroy it */
+ /* Add/delete elements processed by the SET target during resize.
+ * Kernel-side add cannot trigger a resize and userspace actions
+ * are serialized by the mutex.
+ */
+ list_for_each_safe(l, lt, &h->ad) {
+ x = list_entry(l, struct mtype_resize_ad, list);
+ if (x->ad == IPSET_ADD) {
+ mtype_add(set, &x->d, &x->ext, &x->mext, x->flags);
+ } else {
+ mtype_del(set, &x->d, NULL, NULL, 0);
+ }
+ list_del(l);
+ kfree(l);
+ }
+ /* If there's nobody else using the table, destroy it */
if (atomic_dec_and_test(&orig->uref)) {
pr_debug("Table destroy by resize %p\n", orig);
mtype_ahash_destroy(set, orig, false);
@@ -680,13 +787,49 @@ out:
return ret;
cleanup:
+ rcu_read_unlock_bh();
atomic_set(&orig->ref, 0);
atomic_dec(&orig->uref);
- spin_unlock_bh(&set->lock);
mtype_ahash_destroy(set, t, false);
if (ret == -EAGAIN)
goto retry;
goto out;
+
+hbwarn:
+ /* In case we have plenty of memory :-) */
+ pr_warn("Cannot increase the hashsize of set %s further\n", set->name);
+ ret = -IPSET_ERR_HASH_FULL;
+ goto out;
+}
+
+/* Get the current number of elements and ext_size in the set */
+static void
+mtype_ext_size(struct ip_set *set, u32 *elements, size_t *ext_size)
+{
+ struct htype *h = set->data;
+ const struct htable *t;
+ u32 i, j, r;
+ struct hbucket *n;
+ struct mtype_elem *data;
+
+ *elements = 0;
+ t = rcu_dereference_bh(h->table);
+ for (r = 0; r < ahash_numof_locks(t->htable_bits); r++) {
+ for (i = ahash_bucket_start(r, t->htable_bits);
+ i < ahash_bucket_end(r, t->htable_bits); i++) {
+ n = rcu_dereference_bh(hbucket(t, i));
+ if (!n)
+ continue;
+ for (j = 0; j < n->pos; j++) {
+ if (!test_bit(j, n->used))
+ continue;
+ data = ahash_data(n, j, set->dsize);
+ if (!SET_ELEM_EXPIRED(set, data))
+ (*elements)++;
+ }
+ }
+ *ext_size += t->hregion[r].ext_size;
+ }
}
/* Add an element to a hash and update the internal counters when succeeded,
@@ -701,32 +844,49 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
const struct mtype_elem *d = value;
struct mtype_elem *data;
struct hbucket *n, *old = ERR_PTR(-ENOENT);
- int i, j = -1;
+ int i, j = -1, ret;
bool flag_exist = flags & IPSET_FLAG_EXIST;
bool deleted = false, forceadd = false, reuse = false;
- u32 key, multi = 0;
+ u32 r, key, multi = 0, elements, maxelem;
- if (set->elements >= h->maxelem) {
- if (SET_WITH_TIMEOUT(set))
- /* FIXME: when set is full, we slow down here */
- mtype_expire(set, h);
- if (set->elements >= h->maxelem && SET_WITH_FORCEADD(set))
+ rcu_read_lock_bh();
+ t = rcu_dereference_bh(h->table);
+ key = HKEY(value, h->initval, t->htable_bits);
+ r = ahash_region(key, t->htable_bits);
+ atomic_inc(&t->uref);
+ elements = t->hregion[r].elements;
+ maxelem = t->maxelem;
+ if (elements >= maxelem) {
+ u32 e;
+ if (SET_WITH_TIMEOUT(set)) {
+ rcu_read_unlock_bh();
+ mtype_gc_do(set, h, t, r);
+ rcu_read_lock_bh();
+ }
+ maxelem = h->maxelem;
+ elements = 0;
+ for (e = 0; e < ahash_numof_locks(t->htable_bits); e++)
+ elements += t->hregion[e].elements;
+ if (elements >= maxelem && SET_WITH_FORCEADD(set))
forceadd = true;
}
+ rcu_read_unlock_bh();
- t = ipset_dereference_protected(h->table, set);
- key = HKEY(value, h->initval, t->htable_bits);
- n = __ipset_dereference_protected(hbucket(t, key), 1);
+ spin_lock_bh(&t->hregion[r].lock);
+ n = rcu_dereference_bh(hbucket(t, key));
if (!n) {
- if (forceadd || set->elements >= h->maxelem)
+ if (forceadd || elements >= maxelem)
goto set_full;
old = NULL;
n = kzalloc(sizeof(*n) + AHASH_INIT_SIZE * set->dsize,
GFP_ATOMIC);
- if (!n)
- return -ENOMEM;
+ if (!n) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
n->size = AHASH_INIT_SIZE;
- set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize);
+ t->hregion[r].ext_size +=
+ ext_size(AHASH_INIT_SIZE, set->dsize);
goto copy_elem;
}
for (i = 0; i < n->pos; i++) {
@@ -740,67 +900,75 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
}
data = ahash_data(n, i, set->dsize);
if (mtype_data_equal(data, d, &multi)) {
- if (flag_exist ||
- (SET_WITH_TIMEOUT(set) &&
- ip_set_timeout_expired(ext_timeout(data, set)))) {
+ if (flag_exist || SET_ELEM_EXPIRED(set, data)) {
/* Just the extensions could be overwritten */
j = i;
goto overwrite_extensions;
}
- return -IPSET_ERR_EXIST;
+ ret = -IPSET_ERR_EXIST;
+ goto unlock;
}
/* Reuse first timed out entry */
- if (SET_WITH_TIMEOUT(set) &&
- ip_set_timeout_expired(ext_timeout(data, set)) &&
- j == -1) {
+ if (SET_ELEM_EXPIRED(set, data) && j == -1) {
j = i;
reuse = true;
}
}
if (reuse || forceadd) {
+ if (j == -1)
+ j = 0;
data = ahash_data(n, j, set->dsize);
if (!deleted) {
#ifdef IP_SET_HASH_WITH_NETS
for (i = 0; i < IPSET_NET_COUNT; i++)
- mtype_del_cidr(h,
+ mtype_del_cidr(set, h,
NCIDR_PUT(DCIDR_GET(data->cidr, i)),
i);
#endif
ip_set_ext_destroy(set, data);
- set->elements--;
+ t->hregion[r].elements--;
}
goto copy_data;
}
- if (set->elements >= h->maxelem)
+ if (elements >= maxelem)
goto set_full;
/* Create a new slot */
if (n->pos >= n->size) {
- TUNE_AHASH_MAX(h, multi);
+#ifdef IP_SET_HASH_WITH_MULTI
+ if (h->bucketsize >= AHASH_MAX_TUNED)
+ goto set_full;
+ else if (h->bucketsize <= multi)
+ h->bucketsize += AHASH_INIT_SIZE;
+#endif
if (n->size >= AHASH_MAX(h)) {
/* Trigger rehashing */
mtype_data_next(&h->next, d);
- return -EAGAIN;
+ ret = -EAGAIN;
+ goto resize;
}
old = n;
n = kzalloc(sizeof(*n) +
(old->size + AHASH_INIT_SIZE) * set->dsize,
GFP_ATOMIC);
- if (!n)
- return -ENOMEM;
+ if (!n) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
memcpy(n, old, sizeof(struct hbucket) +
old->size * set->dsize);
n->size = old->size + AHASH_INIT_SIZE;
- set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize);
+ t->hregion[r].ext_size +=
+ ext_size(AHASH_INIT_SIZE, set->dsize);
}
copy_elem:
j = n->pos++;
data = ahash_data(n, j, set->dsize);
copy_data:
- set->elements++;
+ t->hregion[r].elements++;
#ifdef IP_SET_HASH_WITH_NETS
for (i = 0; i < IPSET_NET_COUNT; i++)
- mtype_add_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, i)), i);
+ mtype_add_cidr(set, h, NCIDR_PUT(DCIDR_GET(d->cidr, i)), i);
#endif
memcpy(data, d, sizeof(struct mtype_elem));
overwrite_extensions:
@@ -823,13 +991,41 @@ overwrite_extensions:
if (old)
kfree_rcu(old, rcu);
}
+ ret = 0;
+resize:
+ spin_unlock_bh(&t->hregion[r].lock);
+ if (atomic_read(&t->ref) && ext->target) {
+ /* Resize is in process and kernel side add, save values */
+ struct mtype_resize_ad *x;
+
+ x = kzalloc(sizeof(struct mtype_resize_ad), GFP_ATOMIC);
+ if (!x)
+ /* Don't bother */
+ goto out;
+ x->ad = IPSET_ADD;
+ memcpy(&x->d, value, sizeof(struct mtype_elem));
+ memcpy(&x->ext, ext, sizeof(struct ip_set_ext));
+ memcpy(&x->mext, mext, sizeof(struct ip_set_ext));
+ x->flags = flags;
+ spin_lock_bh(&set->lock);
+ list_add_tail(&x->list, &h->ad);
+ spin_unlock_bh(&set->lock);
+ }
+ goto out;
- return 0;
set_full:
if (net_ratelimit())
pr_warn("Set %s is full, maxelem %u reached\n",
- set->name, h->maxelem);
- return -IPSET_ERR_HASH_FULL;
+ set->name, maxelem);
+ ret = -IPSET_ERR_HASH_FULL;
+unlock:
+ spin_unlock_bh(&t->hregion[r].lock);
+out:
+ if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
+ pr_debug("Table destroy after resize by add: %p\n", t);
+ mtype_ahash_destroy(set, t, false);
+ }
+ return ret;
}
/* Delete an element from the hash and free up space if possible.
@@ -843,13 +1039,23 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
const struct mtype_elem *d = value;
struct mtype_elem *data;
struct hbucket *n;
- int i, j, k, ret = -IPSET_ERR_EXIST;
+ struct mtype_resize_ad *x = NULL;
+ int i, j, k, r, ret = -IPSET_ERR_EXIST;
u32 key, multi = 0;
size_t dsize = set->dsize;
- t = ipset_dereference_protected(h->table, set);
+ /* Userspace add and resize is excluded by the mutex.
+ * Kernespace add does not trigger resize.
+ */
+ rcu_read_lock_bh();
+ t = rcu_dereference_bh(h->table);
key = HKEY(value, h->initval, t->htable_bits);
- n = __ipset_dereference_protected(hbucket(t, key), 1);
+ r = ahash_region(key, t->htable_bits);
+ atomic_inc(&t->uref);
+ rcu_read_unlock_bh();
+
+ spin_lock_bh(&t->hregion[r].lock);
+ n = rcu_dereference_bh(hbucket(t, key));
if (!n)
goto out;
for (i = 0, k = 0; i < n->pos; i++) {
@@ -860,8 +1066,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
data = ahash_data(n, i, dsize);
if (!mtype_data_equal(data, d, &multi))
continue;
- if (SET_WITH_TIMEOUT(set) &&
- ip_set_timeout_expired(ext_timeout(data, set)))
+ if (SET_ELEM_EXPIRED(set, data))
goto out;
ret = 0;
@@ -869,20 +1074,33 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
smp_mb__after_atomic();
if (i + 1 == n->pos)
n->pos--;
- set->elements--;
+ t->hregion[r].elements--;
#ifdef IP_SET_HASH_WITH_NETS
for (j = 0; j < IPSET_NET_COUNT; j++)
- mtype_del_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, j)),
- j);
+ mtype_del_cidr(set, h,
+ NCIDR_PUT(DCIDR_GET(d->cidr, j)), j);
#endif
ip_set_ext_destroy(set, data);
+ if (atomic_read(&t->ref) && ext->target) {
+ /* Resize is in process and kernel side del,
+ * save values
+ */
+ x = kzalloc(sizeof(struct mtype_resize_ad),
+ GFP_ATOMIC);
+ if (x) {
+ x->ad = IPSET_DEL;
+ memcpy(&x->d, value,
+ sizeof(struct mtype_elem));
+ x->flags = flags;
+ }
+ }
for (; i < n->pos; i++) {
if (!test_bit(i, n->used))
k++;
}
if (n->pos == 0 && k == 0) {
- set->ext_size -= ext_size(n->size, dsize);
+ t->hregion[r].ext_size -= ext_size(n->size, dsize);
rcu_assign_pointer(hbucket(t, key), NULL);
kfree_rcu(n, rcu);
} else if (k >= AHASH_INIT_SIZE) {
@@ -901,7 +1119,8 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
k++;
}
tmp->pos = k;
- set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize);
+ t->hregion[r].ext_size -=
+ ext_size(AHASH_INIT_SIZE, dsize);
rcu_assign_pointer(hbucket(t, key), tmp);
kfree_rcu(n, rcu);
}
@@ -909,6 +1128,16 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
}
out:
+ spin_unlock_bh(&t->hregion[r].lock);
+ if (x) {
+ spin_lock_bh(&set->lock);
+ list_add(&x->list, &h->ad);
+ spin_unlock_bh(&set->lock);
+ }
+ if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
+ pr_debug("Table destroy after resize by del: %p\n", t);
+ mtype_ahash_destroy(set, t, false);
+ }
return ret;
}
@@ -994,6 +1223,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
int i, ret = 0;
u32 key, multi = 0;
+ rcu_read_lock_bh();
t = rcu_dereference_bh(h->table);
#ifdef IP_SET_HASH_WITH_NETS
/* If we test an IP address and not a network address,
@@ -1025,6 +1255,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
goto out;
}
out:
+ rcu_read_unlock_bh();
return ret;
}
@@ -1036,23 +1267,14 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
const struct htable *t;
struct nlattr *nested;
size_t memsize;
+ u32 elements = 0;
+ size_t ext_size = 0;
u8 htable_bits;
- /* If any members have expired, set->elements will be wrong
- * mytype_expire function will update it with the right count.
- * we do not hold set->lock here, so grab it first.
- * set->elements can still be incorrect in the case of a huge set,
- * because elements might time out during the listing.
- */
- if (SET_WITH_TIMEOUT(set)) {
- spin_lock_bh(&set->lock);
- mtype_expire(set, h);
- spin_unlock_bh(&set->lock);
- }
-
rcu_read_lock_bh();
- t = rcu_dereference_bh_nfnl(h->table);
- memsize = mtype_ahash_memsize(h, t) + set->ext_size;
+ t = rcu_dereference_bh(h->table);
+ mtype_ext_size(set, &elements, &ext_size);
+ memsize = mtype_ahash_memsize(h, t) + ext_size + set->ext_size;
htable_bits = t->htable_bits;
rcu_read_unlock_bh();
@@ -1063,18 +1285,35 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
htonl(jhash_size(htable_bits))) ||
nla_put_net32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem)))
goto nla_put_failure;
+#ifdef IP_SET_HASH_WITH_BITMASK
+ /* if netmask is set to anything other than HOST_MASK we know that the user supplied netmask
+ * and not bitmask. These two are mutually exclusive. */
+ if (h->netmask == HOST_MASK && !nf_inet_addr_cmp(&onesmask, &h->bitmask)) {
+ if (set->family == NFPROTO_IPV4) {
+ if (nla_put_ipaddr4(skb, IPSET_ATTR_BITMASK, h->bitmask.ip))
+ goto nla_put_failure;
+ } else if (set->family == NFPROTO_IPV6) {
+ if (nla_put_ipaddr6(skb, IPSET_ATTR_BITMASK, &h->bitmask.in6))
+ goto nla_put_failure;
+ }
+ }
+#endif
#ifdef IP_SET_HASH_WITH_NETMASK
- if (h->netmask != HOST_MASK &&
- nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask))
+ if (h->netmask != HOST_MASK && nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask))
goto nla_put_failure;
#endif
#ifdef IP_SET_HASH_WITH_MARKMASK
if (nla_put_u32(skb, IPSET_ATTR_MARKMASK, h->markmask))
goto nla_put_failure;
#endif
+ if (set->flags & IPSET_CREATE_FLAG_BUCKETSIZE) {
+ if (nla_put_u8(skb, IPSET_ATTR_BUCKETSIZE, h->bucketsize) ||
+ nla_put_net32(skb, IPSET_ATTR_INITVAL, htonl(h->initval)))
+ goto nla_put_failure;
+ }
if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) ||
nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) ||
- nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(set->elements)))
+ nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(elements)))
goto nla_put_failure;
if (unlikely(ip_set_put_flags(skb, set)))
goto nla_put_failure;
@@ -1094,15 +1333,15 @@ mtype_uref(struct ip_set *set, struct netlink_callback *cb, bool start)
if (start) {
rcu_read_lock_bh();
- t = rcu_dereference_bh_nfnl(h->table);
+ t = ipset_dereference_bh_nfnl(h->table);
atomic_inc(&t->uref);
cb->args[IPSET_CB_PRIVATE] = (unsigned long)t;
rcu_read_unlock_bh();
} else if (cb->args[IPSET_CB_PRIVATE]) {
t = (struct htable *)cb->args[IPSET_CB_PRIVATE];
if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
- /* Resizing didn't destroy the hash table */
- pr_debug("Table destroy by dump: %p\n", t);
+ pr_debug("Table destroy after resize "
+ " by dump: %p\n", t);
mtype_ahash_destroy(set, t, false);
}
cb->args[IPSET_CB_PRIVATE] = 0;
@@ -1144,8 +1383,7 @@ mtype_list(const struct ip_set *set,
if (!test_bit(i, n->used))
continue;
e = ahash_data(n, i, set->dsize);
- if (SET_WITH_TIMEOUT(set) &&
- ip_set_timeout_expired(ext_timeout(e, set)))
+ if (SET_ELEM_EXPIRED(set, e))
continue;
pr_debug("list hash %lu hbucket %p i %u, data %p\n",
cb->args[IPSET_CB_ARG0], n, i, e);
@@ -1211,6 +1449,8 @@ static const struct ip_set_type_variant mtype_variant = {
.uref = mtype_uref,
.resize = mtype_resize,
.same_set = mtype_same_set,
+ .cancel_gc = mtype_cancel_gc,
+ .region_lock = true,
};
#ifdef IP_SET_EMIT_CREATE
@@ -1223,12 +1463,15 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
u32 markmask;
#endif
u8 hbits;
-#ifdef IP_SET_HASH_WITH_NETMASK
- u8 netmask;
+#if defined(IP_SET_HASH_WITH_NETMASK) || defined(IP_SET_HASH_WITH_BITMASK)
+ int ret __attribute__((unused)) = 0;
+ u8 netmask = set->family == NFPROTO_IPV4 ? 32 : 128;
+ union nf_inet_addr bitmask = onesmask;
#endif
size_t hsize;
struct htype *h;
struct htable *t;
+ u32 i;
pr_debug("Create set %s with family %s\n",
set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6");
@@ -1261,7 +1504,6 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
#endif
#ifdef IP_SET_HASH_WITH_NETMASK
- netmask = set->family == NFPROTO_IPV4 ? 32 : 128;
if (tb[IPSET_ATTR_NETMASK]) {
netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
@@ -1269,6 +1511,33 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
(set->family == NFPROTO_IPV6 && netmask > 128) ||
netmask == 0)
return -IPSET_ERR_INVALID_NETMASK;
+
+ /* we convert netmask to bitmask and store it */
+ if (set->family == NFPROTO_IPV4)
+ bitmask.ip = ip_set_netmask(netmask);
+ else
+ ip6_netmask(&bitmask, netmask);
+ }
+#endif
+
+#ifdef IP_SET_HASH_WITH_BITMASK
+ if (tb[IPSET_ATTR_BITMASK]) {
+ /* bitmask and netmask do the same thing, allow only one of these options */
+ if (tb[IPSET_ATTR_NETMASK])
+ return -IPSET_ERR_BITMASK_NETMASK_EXCL;
+
+ if (set->family == NFPROTO_IPV4) {
+ ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_BITMASK], &bitmask.ip);
+ if (ret || !bitmask.ip)
+ return -IPSET_ERR_INVALID_NETMASK;
+ } else if (set->family == NFPROTO_IPV6) {
+ ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_BITMASK], &bitmask);
+ if (ret || ipv6_addr_any(&bitmask.in6))
+ return -IPSET_ERR_INVALID_NETMASK;
+ }
+
+ if (nf_inet_addr_cmp(&bitmask, &zeromask))
+ return -IPSET_ERR_INVALID_NETMASK;
}
#endif
@@ -1286,7 +1555,11 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
if (!h)
return -ENOMEM;
- hbits = htable_bits(hashsize);
+ /* Compute htable_bits from the user input parameter hashsize.
+ * Assume that hashsize == 2^htable_bits,
+ * otherwise round up to the first 2^n value.
+ */
+ hbits = fls(hashsize - 1);
hsize = htable_size(hbits);
if (hsize == 0) {
kfree(h);
@@ -1297,21 +1570,42 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
kfree(h);
return -ENOMEM;
}
+ t->hregion = ip_set_alloc(ahash_sizeof_regions(hbits));
+ if (!t->hregion) {
+ ip_set_free(t);
+ kfree(h);
+ return -ENOMEM;
+ }
+ h->gc.set = set;
+ for (i = 0; i < ahash_numof_locks(hbits); i++)
+ spin_lock_init(&t->hregion[i].lock);
h->maxelem = maxelem;
-#ifdef IP_SET_HASH_WITH_NETMASK
+#if defined(IP_SET_HASH_WITH_NETMASK) || defined(IP_SET_HASH_WITH_BITMASK)
+ h->bitmask = bitmask;
h->netmask = netmask;
#endif
#ifdef IP_SET_HASH_WITH_MARKMASK
h->markmask = markmask;
#endif
- get_random_bytes(&h->initval, sizeof(h->initval));
-
+ if (tb[IPSET_ATTR_INITVAL])
+ h->initval = ntohl(nla_get_be32(tb[IPSET_ATTR_INITVAL]));
+ else
+ get_random_bytes(&h->initval, sizeof(h->initval));
+ h->bucketsize = AHASH_MAX_SIZE;
+ if (tb[IPSET_ATTR_BUCKETSIZE]) {
+ h->bucketsize = nla_get_u8(tb[IPSET_ATTR_BUCKETSIZE]);
+ if (h->bucketsize < AHASH_INIT_SIZE)
+ h->bucketsize = AHASH_INIT_SIZE;
+ else if (h->bucketsize > AHASH_MAX_SIZE)
+ h->bucketsize = AHASH_MAX_SIZE;
+ else if (h->bucketsize % 2)
+ h->bucketsize += 1;
+ }
t->htable_bits = hbits;
+ t->maxelem = h->maxelem / ahash_numof_locks(hbits);
RCU_INIT_POINTER(h->table, t);
-#ifdef HAVE_TIMER_SETUP
- h->set = set;
-#endif
+ INIT_LIST_HEAD(&h->ad);
set->data = h;
#ifndef IP_SET_PROTO_UNDEF
if (set->family == NFPROTO_IPV4) {
@@ -1334,12 +1628,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
#ifndef IP_SET_PROTO_UNDEF
if (set->family == NFPROTO_IPV4)
#endif
- IPSET_TOKEN(HTYPE, 4_gc_init)(set,
- IPSET_TOKEN(HTYPE, 4_gc));
+ IPSET_TOKEN(HTYPE, 4_gc_init)(&h->gc);
#ifndef IP_SET_PROTO_UNDEF
else
- IPSET_TOKEN(HTYPE, 6_gc_init)(set,
- IPSET_TOKEN(HTYPE, 6_gc));
+ IPSET_TOKEN(HTYPE, 6_gc_init)(&h->gc);
#endif
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ip.c b/kernel/net/netfilter/ipset/ip_set_hash_ip.c
index 41c576f..5a2cb71 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_ip.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_ip.c
@@ -24,7 +24,9 @@
/* 1 Counters support */
/* 2 Comments support */
/* 3 Forceadd support */
-#define IPSET_TYPE_REV_MAX 4 /* skbinfo support */
+/* 4 skbinfo support */
+/* 5 bucketsize, initval support */
+#define IPSET_TYPE_REV_MAX 6 /* bitmask support */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
@@ -34,6 +36,7 @@ MODULE_ALIAS("ip_set_hash:ip");
/* Type specific function prefix */
#define HTYPE hash_ip
#define IP_SET_HASH_WITH_NETMASK
+#define IP_SET_HASH_WITH_BITMASK
/* IPv4 variant */
@@ -86,7 +89,7 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
__be32 ip;
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip);
- ip &= ip_set_netmask(h->netmask);
+ ip &= h->bitmask.ip;
if (ip == 0)
return -EINVAL;
@@ -98,11 +101,11 @@ static int
hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ip4 *h = set->data;
+ struct hash_ip4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ip4_elem e = { 0 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
- u32 ip = 0, ip_to = 0, hosts;
+ u32 ip = 0, ip_to = 0, hosts, i = 0;
int ret = 0;
if (tb[IPSET_ATTR_LINENO])
@@ -119,7 +122,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
if (ret)
return ret;
- ip &= ip_set_hostmask(h->netmask);
+ ip &= ntohl(h->bitmask.ip);
e.ip = htonl(ip);
if (e.ip == 0)
return -IPSET_ERR_HASH_ELEM;
@@ -132,8 +135,11 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
- if (ip > ip_to)
+ if (ip > ip_to) {
+ if (ip_to == 0)
+ return -IPSET_ERR_HASH_ELEM;
swap(ip, ip_to);
+ }
} else if (tb[IPSET_ATTR_CIDR]) {
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
@@ -144,18 +150,20 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
- if (retried) {
+ if (retried)
ip = ntohl(h->next.ip);
+ for (; ip <= ip_to; i++) {
e.ip = htonl(ip);
- }
- for (; ip <= ip_to;) {
+ if (i > IPSET_MAX_RANGE) {
+ hash_ip4_data_next(&h->next, &e);
+ return -ERANGE;
+ }
ret = adtfn(set, &e, &ext, &ext, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
ip += hosts;
- e.ip = htonl(ip);
- if (e.ip == 0)
+ if (ip == 0)
return 0;
ret = 0;
@@ -180,12 +188,6 @@ hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6);
}
-static void
-hash_ip6_netmask(union nf_inet_addr *ip, u8 prefix)
-{
- ip6_netmask(ip, prefix);
-}
-
static bool
hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *e)
{
@@ -222,7 +224,7 @@ hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
- hash_ip6_netmask(&e.ip, h->netmask);
+ nf_inet_addr_mask_inplace(&e.ip, &h->bitmask);
if (ipv6_addr_any(&e.ip.in6))
return -EINVAL;
@@ -261,7 +263,7 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
if (ret)
return ret;
- hash_ip6_netmask(&e.ip, h->netmask);
+ nf_inet_addr_mask_inplace(&e.ip, &h->bitmask);
if (ipv6_addr_any(&e.ip.in6))
return -IPSET_ERR_HASH_ELEM;
@@ -278,14 +280,17 @@ static struct ip_set_type hash_ip_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_ip_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
+ [IPSET_ATTR_BITMASK] = { .type = NLA_NESTED },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
},
.adt_policy = {
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipmac.c b/kernel/net/netfilter/ipset/ip_set_hash_ipmac.c
index eceb7bc..467c59a 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_ipmac.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_ipmac.c
@@ -23,7 +23,7 @@
#include <linux/netfilter/ipset/ip_set_hash.h>
#define IPSET_TYPE_REV_MIN 0
-#define IPSET_TYPE_REV_MAX 0
+#define IPSET_TYPE_REV_MAX 1 /* bucketsize, initval support */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tomasz Chilinski <tomasz.chilinski@chilan.com>");
@@ -268,11 +268,13 @@ static struct ip_set_type hash_ipmac_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_ipmac_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipmark.c b/kernel/net/netfilter/ipset/ip_set_hash_ipmark.c
index 4ebd21b..ad2a2dc 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_ipmark.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_ipmark.c
@@ -23,7 +23,8 @@
#define IPSET_TYPE_REV_MIN 0
/* 1 Forceadd support */
-#define IPSET_TYPE_REV_MAX 2 /* skbinfo support */
+/* 2 skbinfo support */
+#define IPSET_TYPE_REV_MAX 3 /* bucketsize, initval support */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vytas Dauksa <vytas.dauksa@smoothwall.net>");
@@ -98,11 +99,11 @@ static int
hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipmark4 *h = set->data;
+ struct hash_ipmark4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipmark4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
- u32 ip, ip_to = 0;
+ u32 ip, ip_to = 0, i = 0;
int ret;
if (tb[IPSET_ATTR_LINENO])
@@ -122,6 +123,8 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
e.mark = ntohl(nla_get_be32(tb[IPSET_ATTR_MARK]));
e.mark &= h->markmask;
+ if (e.mark == 0 && e.ip == 0)
+ return -IPSET_ERR_HASH_ELEM;
if (adt == IPSET_TEST ||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR])) {
@@ -134,8 +137,11 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
- if (ip > ip_to)
+ if (ip > ip_to) {
+ if (e.mark == 0 && ip_to == 0)
+ return -IPSET_ERR_HASH_ELEM;
swap(ip, ip_to);
+ }
} else if (tb[IPSET_ATTR_CIDR]) {
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
@@ -146,8 +152,12 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
if (retried)
ip = ntohl(h->next.ip);
- for (; ip <= ip_to; ip++) {
+ for (; ip <= ip_to; ip++, i++) {
e.ip = htonl(ip);
+ if (i > IPSET_MAX_RANGE) {
+ hash_ipmark4_data_next(&h->next, &e);
+ return -ERANGE;
+ }
ret = adtfn(set, &e, &ext, &ext, flags);
if (ret && !ip_set_eexist(ret, flags))
@@ -276,12 +286,14 @@ static struct ip_set_type hash_ipmark_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_ipmark_create,
.create_policy = {
[IPSET_ATTR_MARKMASK] = { .type = NLA_U32 },
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipport.c b/kernel/net/netfilter/ipset/ip_set_hash_ipport.c
index 7e34bc4..46f8bbf 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -26,7 +26,9 @@
/* 2 Counters support added */
/* 3 Comments support added */
/* 4 Forceadd support added */
-#define IPSET_TYPE_REV_MAX 5 /* skbinfo support added */
+/* 5 skbinfo support added */
+/* 6 bucketsize, initval support added */
+#define IPSET_TYPE_REV_MAX 7 /* bitmask support added */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
@@ -35,6 +37,8 @@ MODULE_ALIAS("ip_set_hash:ip,port");
/* Type specific function prefix */
#define HTYPE hash_ipport
+#define IP_SET_HASH_WITH_NETMASK
+#define IP_SET_HASH_WITH_BITMASK
/* IPv4 variant */
@@ -92,12 +96,16 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport4_elem e = { .ip = 0 };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
+ const struct MTYPE *h = set->data;
if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&e.port, &e.proto))
return -EINVAL;
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
+ e.ip &= h->bitmask.ip;
+ if (e.ip == 0)
+ return -EINVAL;
return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
}
@@ -105,11 +113,11 @@ static int
hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipport4 *h = set->data;
+ struct hash_ipport4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport4_elem e = { .ip = 0 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
- u32 ip, ip_to = 0, p = 0, port, port_to;
+ u32 ip, ip_to = 0, p = 0, port, port_to, i = 0;
bool with_ports = false;
int ret;
@@ -129,6 +137,10 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
if (ret)
return ret;
+ e.ip &= h->bitmask.ip;
+ if (e.ip == 0)
+ return -EINVAL;
+
e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
if (tb[IPSET_ATTR_PROTO]) {
@@ -178,9 +190,13 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
for (; ip <= ip_to; ip++) {
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
: port;
- for (; p <= port_to; p++) {
+ for (; p <= port_to; p++, i++) {
e.ip = htonl(ip);
e.port = htons(p);
+ if (i > IPSET_MAX_RANGE) {
+ hash_ipport4_data_next(&h->next, &e);
+ return -ERANGE;
+ }
ret = adtfn(set, &e, &ext, &ext, flags);
if (ret && !ip_set_eexist(ret, flags))
@@ -250,12 +266,17 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport6_elem e = { .ip = { .all = { 0 } } };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
+ const struct MTYPE *h = set->data;
if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&e.port, &e.proto))
return -EINVAL;
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
+ nf_inet_addr_mask_inplace(&e.ip, &h->bitmask);
+ if (ipv6_addr_any(&e.ip.in6))
+ return -EINVAL;
+
return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
}
@@ -295,6 +316,10 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
if (ret)
return ret;
+ nf_inet_addr_mask_inplace(&e.ip, &h->bitmask);
+ if (ipv6_addr_any(&e.ip.in6))
+ return -EINVAL;
+
e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
if (tb[IPSET_ATTR_PROTO]) {
@@ -342,15 +367,19 @@ static struct ip_set_type hash_ipport_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_ipport_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
+ [IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
+ [IPSET_ATTR_BITMASK] = { .type = NLA_NESTED },
},
.adt_policy = {
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c b/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c
index 81ce821..ca5fe9c 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -26,7 +26,8 @@
/* 2 Counters support added */
/* 3 Comments support added */
/* 4 Forceadd support added */
-#define IPSET_TYPE_REV_MAX 5 /* skbinfo support added */
+/* 5 skbinfo support added */
+#define IPSET_TYPE_REV_MAX 6 /* bucketsize, initval support added */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
@@ -108,11 +109,11 @@ static int
hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipportip4 *h = set->data;
+ struct hash_ipportip4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip4_elem e = { .ip = 0 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
- u32 ip, ip_to = 0, p = 0, port, port_to;
+ u32 ip, ip_to = 0, p = 0, port, port_to, i = 0;
bool with_ports = false;
int ret;
@@ -185,9 +186,13 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
for (; ip <= ip_to; ip++) {
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
: port;
- for (; p <= port_to; p++) {
+ for (; p <= port_to; p++, i++) {
e.ip = htonl(ip);
e.port = htons(p);
+ if (i > IPSET_MAX_RANGE) {
+ hash_ipportip4_data_next(&h->next, &e);
+ return -ERANGE;
+ }
ret = adtfn(set, &e, &ext, &ext, flags);
if (ret && !ip_set_eexist(ret, flags))
@@ -357,11 +362,13 @@ static struct ip_set_type hash_ipportip_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_ipportip_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c b/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c
index 4d4d443..8f44644 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -28,7 +28,8 @@
/* 4 Counters support added */
/* 5 Comments support added */
/* 6 Forceadd support added */
-#define IPSET_TYPE_REV_MAX 7 /* skbinfo support added */
+/* 7 skbinfo support added */
+#define IPSET_TYPE_REV_MAX 8 /* bucketsize, initval support added */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
@@ -160,12 +161,12 @@ static int
hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipportnet4 *h = set->data;
+ struct hash_ipportnet4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip = 0, ip_to = 0, p = 0, port, port_to;
- u32 ip2_from = 0, ip2_to = 0, ip2;
+ u32 ip2_from = 0, ip2_to = 0, ip2, i = 0;
bool with_ports = false;
u8 cidr;
int ret;
@@ -279,9 +280,15 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
for (; p <= port_to; p++) {
e.port = htons(p);
do {
+ i++;
e.ip2 = htonl(ip2);
ip2 = ip_set_range_to_cidr(ip2, ip2_to, &cidr);
e.cidr = cidr - 1;
+ if (i > IPSET_MAX_RANGE) {
+ hash_ipportnet4_data_next(&h->next,
+ &e);
+ return -ERANGE;
+ }
ret = adtfn(set, &e, &ext, &ext, flags);
if (ret && !ip_set_eexist(ret, flags))
@@ -514,11 +521,13 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_ipportnet_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_mac.c b/kernel/net/netfilter/ipset/ip_set_hash_mac.c
index 407c158..014bb71 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_mac.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_mac.c
@@ -17,7 +17,7 @@
#include <linux/netfilter/ipset/ip_set_hash.h>
#define IPSET_TYPE_REV_MIN 0
-#define IPSET_TYPE_REV_MAX 0
+#define IPSET_TYPE_REV_MAX 1 /* bucketsize, initval support */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
@@ -126,11 +126,13 @@ static struct ip_set_type hash_mac_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_mac_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_net.c b/kernel/net/netfilter/ipset/ip_set_hash_net.c
index 923bffb..8baceea 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_net.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_net.c
@@ -25,7 +25,8 @@
/* 3 Counters support added */
/* 4 Comments support added */
/* 5 Forceadd support added */
-#define IPSET_TYPE_REV_MAX 6 /* skbinfo mapping support added */
+/* 6 skbinfo support added */
+#define IPSET_TYPE_REV_MAX 7 /* bucketsize, initval support added */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
@@ -136,11 +137,11 @@ static int
hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_net4 *h = set->data;
+ struct hash_net4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_net4_elem e = { .cidr = HOST_MASK };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
- u32 ip = 0, ip_to = 0;
+ u32 ip = 0, ip_to = 0, i = 0;
int ret;
if (tb[IPSET_ATTR_LINENO])
@@ -188,10 +189,16 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
if (ip + UINT_MAX == ip_to)
return -IPSET_ERR_HASH_RANGE;
}
+
if (retried)
ip = ntohl(h->next.ip);
do {
+ i++;
e.ip = htonl(ip);
+ if (i > IPSET_MAX_RANGE) {
+ hash_net4_data_next(&h->next, &e);
+ return -ERANGE;
+ }
ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
ret = adtfn(set, &e, &ext, &ext, flags);
if (ret && !ip_set_eexist(ret, flags))
@@ -355,11 +362,13 @@ static struct ip_set_type hash_net_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_net_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_netiface.c b/kernel/net/netfilter/ipset/ip_set_hash_netiface.c
index 4202dd2..5baa852 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -27,7 +27,8 @@
/* 4 Comments support added */
/* 5 Forceadd support added */
/* 6 skbinfo support added */
-#define IPSET_TYPE_REV_MAX 7 /* interface wildcard support added */
+/* 7 interface wildcard support added */
+#define IPSET_TYPE_REV_MAX 8 /* bucketsize, initval support added */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
@@ -40,7 +41,7 @@ MODULE_ALIAS("ip_set_hash:net,iface");
#define IP_SET_HASH_WITH_MULTI
#define IP_SET_HASH_WITH_NET0
-#define STRLCPY(a, b) strlcpy(a, b, IFNAMSIZ)
+#define STRSCPY(a, b) strscpy(a, b, IFNAMSIZ)
/* IPv4 variant */
@@ -182,11 +183,11 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
if (!eiface)
return -EINVAL;
- STRLCPY(e.iface, eiface);
+ STRSCPY(e.iface, eiface);
e.physdev = 1;
#endif
} else {
- STRLCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out));
+ STRSCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out));
}
if (strlen(e.iface) == 0)
@@ -202,7 +203,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
- u32 ip = 0, ip_to = 0;
+ u32 ip = 0, ip_to = 0, i = 0;
int ret;
if (tb[IPSET_ATTR_LINENO])
@@ -226,7 +227,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
if (e.cidr > HOST_MASK)
return -IPSET_ERR_INVALID_CIDR;
}
- nla_strlcpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ);
+ nla_strscpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ);
if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
@@ -260,7 +261,12 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
if (retried)
ip = ntohl(h->next.ip);
do {
+ i++;
e.ip = htonl(ip);
+ if (i > IPSET_MAX_RANGE) {
+ hash_netiface4_data_next(&h->next, &e);
+ return -ERANGE;
+ }
ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
ret = adtfn(set, &e, &ext, &ext, flags);
@@ -395,11 +401,11 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
if (!eiface)
return -EINVAL;
- STRLCPY(e.iface, eiface);
+ STRSCPY(e.iface, eiface);
e.physdev = 1;
#endif
} else {
- STRLCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out));
+ STRSCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out));
}
if (strlen(e.iface) == 0)
@@ -443,7 +449,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
ip6_netmask(&e.ip, e.cidr);
- nla_strlcpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ);
+ nla_strscpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ);
if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
@@ -471,11 +477,13 @@ static struct ip_set_type hash_netiface_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_netiface_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_netnet.c b/kernel/net/netfilter/ipset/ip_set_hash_netnet.c
index da4ef91..8fbe649 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_netnet.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_netnet.c
@@ -22,7 +22,9 @@
#define IPSET_TYPE_REV_MIN 0
/* 1 Forceadd support added */
-#define IPSET_TYPE_REV_MAX 2 /* skbinfo support added */
+/* 2 skbinfo support added */
+/* 3 bucketsize, initval support added */
+#define IPSET_TYPE_REV_MAX 4 /* bitmask support added */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>");
@@ -32,6 +34,8 @@ MODULE_ALIAS("ip_set_hash:net,net");
/* Type specific function prefix */
#define HTYPE hash_netnet
#define IP_SET_HASH_WITH_NETS
+#define IP_SET_HASH_WITH_NETMASK
+#define IP_SET_HASH_WITH_BITMASK
#define IPSET_NET_COUNT 2
/* IPv4 variants */
@@ -152,8 +156,8 @@ hash_netnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0]);
ip4addrptr(skb, opt->flags & IPSET_DIM_TWO_SRC, &e.ip[1]);
- e.ip[0] &= ip_set_netmask(e.cidr[0]);
- e.ip[1] &= ip_set_netmask(e.cidr[1]);
+ e.ip[0] &= (ip_set_netmask(e.cidr[0]) & h->bitmask.ip);
+ e.ip[1] &= (ip_set_netmask(e.cidr[1]) & h->bitmask.ip);
return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
}
@@ -162,12 +166,12 @@ static int
hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_netnet4 *h = set->data;
+ struct hash_netnet4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netnet4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip = 0, ip_to = 0;
- u32 ip2 = 0, ip2_from = 0, ip2_to = 0;
+ u32 ip2 = 0, ip2_from = 0, ip2_to = 0, i = 0;
int ret;
if (tb[IPSET_ATTR_LINENO])
@@ -211,8 +215,8 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
if (adt == IPSET_TEST || !(tb[IPSET_ATTR_IP_TO] ||
tb[IPSET_ATTR_IP2_TO])) {
- e.ip[0] = htonl(ip & ip_set_hostmask(e.cidr[0]));
- e.ip[1] = htonl(ip2_from & ip_set_hostmask(e.cidr[1]));
+ e.ip[0] = htonl(ip & ntohl(h->bitmask.ip) & ip_set_hostmask(e.cidr[0]));
+ e.ip[1] = htonl(ip2_from & ntohl(h->bitmask.ip) & ip_set_hostmask(e.cidr[1]));
ret = adtfn(set, &e, &ext, &ext, flags);
return ip_set_enomatch(ret, flags, adt, set) ? -ret :
ip_set_eexist(ret, flags) ? 0 : ret;
@@ -255,7 +259,12 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
e.ip[0] = htonl(ip);
ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
do {
+ i++;
e.ip[1] = htonl(ip2);
+ if (i > IPSET_MAX_RANGE) {
+ hash_netnet4_data_next(&h->next, &e);
+ return -ERANGE;
+ }
ip2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
ret = adtfn(set, &e, &ext, &ext, flags);
if (ret && !ip_set_eexist(ret, flags))
@@ -389,6 +398,11 @@ hash_netnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
ip6_netmask(&e.ip[0], e.cidr[0]);
ip6_netmask(&e.ip[1], e.cidr[1]);
+ nf_inet_addr_mask_inplace(&e.ip[0], &h->bitmask);
+ nf_inet_addr_mask_inplace(&e.ip[1], &h->bitmask);
+ if (e.cidr[0] == HOST_MASK && ipv6_addr_any(&e.ip[0].in6))
+ return -EINVAL;
+
return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
}
@@ -399,6 +413,7 @@ hash_netnet6_uadt(struct ip_set *set, struct nlattr *tb[],
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netnet6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
+ const struct hash_netnet6 *h = set->data;
int ret;
if (tb[IPSET_ATTR_LINENO])
@@ -438,6 +453,11 @@ hash_netnet6_uadt(struct ip_set *set, struct nlattr *tb[],
ip6_netmask(&e.ip[0], e.cidr[0]);
ip6_netmask(&e.ip[1], e.cidr[1]);
+ nf_inet_addr_mask_inplace(&e.ip[0], &h->bitmask);
+ nf_inet_addr_mask_inplace(&e.ip[1], &h->bitmask);
+ if (e.cidr[0] == HOST_MASK && ipv6_addr_any(&e.ip[0].in6))
+ return -IPSET_ERR_HASH_ELEM;
+
if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
@@ -459,14 +479,18 @@ static struct ip_set_type hash_netnet_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_netnet_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
+ [IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
+ [IPSET_ATTR_BITMASK] = { .type = NLA_NESTED },
},
.adt_policy = {
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_netport.c b/kernel/net/netfilter/ipset/ip_set_hash_netport.c
index 48ad1c4..8a2a7c5 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_netport.c
@@ -27,7 +27,8 @@
/* 4 Counters support added */
/* 5 Comments support added */
/* 6 Forceadd support added */
-#define IPSET_TYPE_REV_MAX 7 /* skbinfo support added */
+/* 7 skbinfo support added */
+#define IPSET_TYPE_REV_MAX 8 /* bucketsize, initval support added */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
@@ -154,11 +155,11 @@ static int
hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_netport4 *h = set->data;
+ struct hash_netport4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
- u32 port, port_to, p = 0, ip = 0, ip_to = 0;
+ u32 port, port_to, p = 0, ip = 0, ip_to = 0, i = 0;
bool with_ports = false;
u8 cidr;
int ret;
@@ -246,8 +247,12 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
e.ip = htonl(ip);
ip = ip_set_range_to_cidr(ip, ip_to, &cidr);
e.cidr = cidr - 1;
- for (; p <= port_to; p++) {
+ for (; p <= port_to; p++, i++) {
e.port = htons(p);
+ if (i > IPSET_MAX_RANGE) {
+ hash_netport4_data_next(&h->next, &e);
+ return -ERANGE;
+ }
ret = adtfn(set, &e, &ext, &ext, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
@@ -461,11 +466,13 @@ static struct ip_set_type hash_netport_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_netport_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c b/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c
index 686cbbc..d5774a1 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c
+++ b/kernel/net/netfilter/ipset/ip_set_hash_netportnet.c
@@ -24,7 +24,8 @@
#define IPSET_TYPE_REV_MIN 0
/* 0 Comments support added */
/* 1 Forceadd support added */
-#define IPSET_TYPE_REV_MAX 2 /* skbinfo support added */
+/* 2 skbinfo support added */
+#define IPSET_TYPE_REV_MAX 3 /* bucketsize, initval support added */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>");
@@ -36,6 +37,7 @@ MODULE_ALIAS("ip_set_hash:net,port,net");
#define IP_SET_HASH_WITH_PROTO
#define IP_SET_HASH_WITH_NETS
#define IPSET_NET_COUNT 2
+#define IP_SET_HASH_WITH_NET0
/* IPv4 variant */
@@ -173,16 +175,26 @@ hash_netportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
}
+static u32
+hash_netportnet4_range_to_cidr(u32 from, u32 to, u8 *cidr)
+{
+ if (from == 0 && to == UINT_MAX) {
+ *cidr = 0;
+ return to;
+ }
+ return ip_set_range_to_cidr(from, to, cidr);
+}
+
static int
hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_netportnet4 *h = set->data;
+ struct hash_netportnet4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netportnet4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip = 0, ip_to = 0, p = 0, port, port_to;
- u32 ip2_from = 0, ip2_to = 0, ip2;
+ u32 ip2_from = 0, ip2_to = 0, ip2, i = 0;
bool with_ports = false;
int ret;
@@ -296,13 +308,19 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
do {
e.ip[0] = htonl(ip);
- ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
+ ip = hash_netportnet4_range_to_cidr(ip, ip_to, &e.cidr[0]);
for (; p <= port_to; p++) {
e.port = htons(p);
do {
+ i++;
e.ip[1] = htonl(ip2);
- ip2 = ip_set_range_to_cidr(ip2, ip2_to,
- &e.cidr[1]);
+ if (i > IPSET_MAX_RANGE) {
+ hash_netportnet4_data_next(&h->next,
+ &e);
+ return -ERANGE;
+ }
+ ip2 = hash_netportnet4_range_to_cidr(ip2,
+ ip2_to, &e.cidr[1]);
ret = adtfn(set, &e, &ext, &ext, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
@@ -559,11 +577,13 @@ static struct ip_set_type hash_netportnet_type __read_mostly = {
.family = NFPROTO_UNSPEC,
.revision_min = IPSET_TYPE_REV_MIN,
.revision_max = IPSET_TYPE_REV_MAX,
+ .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE,
.create = hash_netportnet_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
- [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_INITVAL] = { .type = NLA_U32 },
+ [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
diff --git a/kernel/net/netfilter/ipset/ip_set_list_set.c b/kernel/net/netfilter/ipset/ip_set_list_set.c
index fe862fb..cc2e5b9 100644
--- a/kernel/net/netfilter/ipset/ip_set_list_set.c
+++ b/kernel/net/netfilter/ipset/ip_set_list_set.c
@@ -62,7 +62,7 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb,
/* Don't lookup sub-counters at all */
opt->cmdflags &= ~IPSET_FLAG_MATCH_COUNTERS;
if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE)
- opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE;
+ opt->cmdflags |= IPSET_FLAG_SKIP_COUNTER_UPDATE;
list_for_each_entry_rcu(e, &map->members, list) {
ret = ip_set_test(e->id, skb, par, opt);
if (ret <= 0)
@@ -429,9 +429,6 @@ list_set_destroy(struct ip_set *set)
struct list_set *map = set->data;
struct set_elem *e, *n;
- if (SET_WITH_TIMEOUT(set))
- del_timer_sync(&map->gc);
-
list_for_each_entry_safe(e, n, &map->members, list) {
list_del(&e->list);
ip_set_put_byindex(map->net, e->id);
@@ -548,6 +545,15 @@ list_set_same_set(const struct ip_set *a, const struct ip_set *b)
a->extensions == b->extensions;
}
+static void
+list_set_cancel_gc(struct ip_set *set)
+{
+ struct list_set *map = set->data;
+
+ if (SET_WITH_TIMEOUT(set))
+ timer_shutdown_sync(&map->gc);
+}
+
static const struct ip_set_type_variant set_variant = {
.kadt = list_set_kadt,
.uadt = list_set_uadt,
@@ -561,6 +567,7 @@ static const struct ip_set_type_variant set_variant = {
.head = list_set_head,
.list = list_set_list,
.same_set = list_set_same_set,
+ .cancel_gc = list_set_cancel_gc,
};
static void
diff --git a/kernel/net/netfilter/ipset/pfxlen.c b/kernel/net/netfilter/ipset/pfxlen.c
index 59f6e72..1e264c7 100644
--- a/kernel/net/netfilter/ipset/pfxlen.c
+++ b/kernel/net/netfilter/ipset/pfxlen.c
@@ -1,6 +1,4 @@
#include <linux/version.h>
-#define IP_SET_COMPAT_HEADERS
-#include <linux/netfilter/ipset/ip_set_compat.h>
#include <linux/netfilter/ipset/pfxlen.h>
/* Prefixlen maps for fast conversions, by Jan Engelhardt. */
diff --git a/kernel/net/netfilter/xt_set.c b/kernel/net/netfilter/xt_set.c
index c2735c4..95efb3a 100644
--- a/kernel/net/netfilter/xt_set.c
+++ b/kernel/net/netfilter/xt_set.c
@@ -39,7 +39,7 @@ MODULE_ALIAS("ip6t_SET");
#ifdef HAVE_XT_MTCHK_PARAM_STRUCT_NET
#define XT_PAR_NET(par) ((par)->net)
#else
-#define XT_PAR_NET(par) NULL
+#define XT_PAR_NET(par) (&(init_net))
#endif
static inline int
diff --git a/kernel/net/sched/em_ipset.c b/kernel/net/sched/em_ipset.c
index 96fd4a3..5428f8d 100644
--- a/kernel/net/sched/em_ipset.c
+++ b/kernel/net/sched/em_ipset.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* net/sched/em_ipset.c ipset ematch
*
* Copyright (c) 2012 Florian Westphal <fw@strlen.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
*/
#include <linux/gfp.h>
@@ -87,7 +84,7 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em,
#else
#define ACPAR_FAMILY(f) acpar.family = f
#endif
- switch (tc_skb_protocol(skb)) {
+ switch (skb_protocol(skb, true)) {
case htons(ETH_P_IP):
ACPAR_FAMILY(NFPROTO_IPV4);
if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 3a82417..a9edf95 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -46,7 +46,6 @@ EXTRA_libipset_la_SOURCES = \
EXTRA_DIST = $(IPSET_SETTYPE_LIST) libipset.map
-pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libipset.pc
dist_man_MANS = libipset.3
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..c05b201 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,7 @@ ipset_strlcpy(char *dst, const char *src, size_t len)
assert(dst);
assert(src);
- strncpy(dst, src, len);
+ memcpy(dst, src, len);
dst[len - 1] = '\0';
}
@@ -286,8 +287,8 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
data->index = *(const uint16_t *) value;
break;
/* Create-specific options */
- case IPSET_OPT_GC:
- data->create.gc = *(const uint32_t *) value;
+ case IPSET_OPT_INITVAL:
+ data->create.initval = *(const uint32_t *) value;
break;
case IPSET_OPT_HASHSIZE:
data->create.hashsize = *(const uint32_t *) value;
@@ -301,8 +302,14 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
case IPSET_OPT_NETMASK:
data->create.netmask = *(const uint8_t *) value;
break;
- case IPSET_OPT_PROBES:
- data->create.probes = *(const uint8_t *) value;
+ case IPSET_OPT_BITMASK:
+ if (!(data->family == NFPROTO_IPV4 ||
+ data->family == NFPROTO_IPV6))
+ return -1;
+ copy_addr(data->family, &data->create.bitmask, value);
+ break;
+ case IPSET_OPT_BUCKETSIZE:
+ data->create.bucketsize = *(const uint8_t *) value;
break;
case IPSET_OPT_RESIZE:
data->create.resize = *(const uint8_t *) value;
@@ -498,8 +505,8 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
case IPSET_OPT_INDEX:
return &data->index;
/* Create-specific options */
- case IPSET_OPT_GC:
- return &data->create.gc;
+ case IPSET_OPT_INITVAL:
+ return &data->create.initval;
case IPSET_OPT_HASHSIZE:
return &data->create.hashsize;
case IPSET_OPT_MAXELEM:
@@ -508,8 +515,10 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
return &data->create.markmask;
case IPSET_OPT_NETMASK:
return &data->create.netmask;
- case IPSET_OPT_PROBES:
- return &data->create.probes;
+ case IPSET_OPT_BITMASK:
+ return &data->create.bitmask;
+ case IPSET_OPT_BUCKETSIZE:
+ return &data->create.bucketsize;
case IPSET_OPT_RESIZE:
return &data->create.resize;
case IPSET_OPT_SIZE:
@@ -594,6 +603,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
case IPSET_OPT_IP_TO:
case IPSET_OPT_IP2:
case IPSET_OPT_IP2_TO:
+ case IPSET_OPT_BITMASK:
return family == NFPROTO_IPV4 ? sizeof(uint32_t)
: sizeof(struct in6_addr);
case IPSET_OPT_MARK:
@@ -608,7 +618,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
case IPSET_OPT_NAMEREF:
return IPSET_MAXNAMELEN;
case IPSET_OPT_TIMEOUT:
- case IPSET_OPT_GC:
+ case IPSET_OPT_INITVAL:
case IPSET_OPT_HASHSIZE:
case IPSET_OPT_MAXELEM:
case IPSET_OPT_MARKMASK:
@@ -625,7 +635,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
case IPSET_OPT_CIDR:
case IPSET_OPT_CIDR2:
case IPSET_OPT_NETMASK:
- case IPSET_OPT_PROBES:
+ case IPSET_OPT_BUCKETSIZE:
case IPSET_OPT_RESIZE:
case IPSET_OPT_PROTO:
return sizeof(uint8_t);
diff --git a/lib/debug.c b/lib/debug.c
index 6b3ead2..dbc5cfb 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -35,12 +35,13 @@ static const struct ipset_attrname createattr2name[] = {
[IPSET_ATTR_PROTO] = { .name = "PROTO" },
[IPSET_ATTR_CADT_FLAGS] = { .name = "CADT_FLAGS" },
[IPSET_ATTR_CADT_LINENO] = { .name = "CADT_LINENO" },
- [IPSET_ATTR_GC] = { .name = "GC" },
+ [IPSET_ATTR_INITVAL] = { .name = "INITVAL" },
[IPSET_ATTR_HASHSIZE] = { .name = "HASHSIZE" },
[IPSET_ATTR_MAXELEM] = { .name = "MAXELEM" },
[IPSET_ATTR_MARKMASK] = { .name = "MARKMASK" },
[IPSET_ATTR_NETMASK] = { .name = "NETMASK" },
- [IPSET_ATTR_PROBES] = { .name = "PROBES" },
+ [IPSET_ATTR_BITMASK] = { .name = "BITMASK" },
+ [IPSET_ATTR_BUCKETSIZE] = { .name = "BUCKETSIZE" },
[IPSET_ATTR_RESIZE] = { .name = "RESIZE" },
[IPSET_ATTR_SIZE] = { .name = "SIZE" },
[IPSET_ATTR_ELEMENTS] = { .name = "ELEMENTS" },
diff --git a/lib/errcode.c b/lib/errcode.c
index b38f95e..49c97a1 100644
--- a/lib/errcode.c
+++ b/lib/errcode.c
@@ -25,6 +25,8 @@ static const struct ipset_errcode_table core_errcode_table[] = {
"The set with the given name does not exist" },
{ EMSGSIZE, 0,
"Kernel error received: message could not be created" },
+ { ERANGE, 0,
+ "The specified range is too large, split it up into smaller ranges" },
{ IPSET_ERR_PROTOCOL, 0,
"Kernel error received: ipset protocol error" },
@@ -42,6 +44,8 @@ static const struct ipset_errcode_table core_errcode_table[] = {
"The value of the markmask parameter is invalid" },
{ IPSET_ERR_INVALID_FAMILY, 0,
"Protocol family not supported by the set type" },
+ { IPSET_ERR_BITMASK_NETMASK_EXCL, 0,
+ "netmask and bitmask options are mutually exclusive, provide only one" },
/* DESTROY specific error codes */
{ IPSET_ERR_BUSY, IPSET_CMD_DESTROY,
diff --git a/lib/ipset.c b/lib/ipset.c
index 8633491..c910d88 100644
--- a/lib/ipset.c
+++ b/lib/ipset.c
@@ -13,6 +13,7 @@
#include <stdio.h> /* printf */
#include <stdlib.h> /* exit */
#include <string.h> /* str* */
+#include <inttypes.h> /* PRIu64 */
#include <config.h>
@@ -27,6 +28,9 @@
#include <libipset/print.h> /* ipset_print_family */
#include <libipset/utils.h> /* STREQ */
#include <libipset/ipset.h> /* prototypes */
+#include <libipset/ip_set_compiler.h> /* compiler attributes */
+#include <libipset/list_sort.h> /* lists */
+#include <libipset/xlate.h> /* ipset_xlate_argv */
static char program_name[] = PACKAGE;
static char program_version[] = PACKAGE_VERSION;
@@ -49,6 +53,17 @@ struct ipset {
char *newargv[MAX_ARGS];
int newargc;
const char *filename; /* Input/output filename */
+ bool xlate;
+ struct list_head xlate_sets;
+};
+
+struct ipset_xlate_set {
+ struct list_head list;
+ char name[IPSET_MAXNAMELEN];
+ uint8_t netmask;
+ uint8_t family;
+ bool interval;
+ const struct ipset_type *type;
};
/* Commands and environment options */
@@ -220,7 +235,7 @@ const struct ipset_envopts ipset_envopts[] = {
{ .name = { "-o", "-output" },
.has_arg = IPSET_MANDATORY_ARG, .flag = IPSET_OPT_MAX,
.parse = ipset_parse_output,
- .help = "plain|save|xml\n"
+ .help = "plain|save|xml|json\n"
" Specify output mode for listing sets.\n"
" Default value for \"list\" command is mode \"plain\"\n"
" and for \"save\" command is mode \"save\".",
@@ -414,6 +429,8 @@ ipset_parse_output(struct ipset *ipset,
return ipset_session_output(session, IPSET_LIST_PLAIN);
else if (STREQ(str, "xml"))
return ipset_session_output(session, IPSET_LIST_XML);
+ else if (STREQ(str, "json"))
+ return ipset_session_output(session, IPSET_LIST_JSON);
else if (STREQ(str, "save"))
return ipset_session_output(session, IPSET_LIST_SAVE);
@@ -922,20 +939,21 @@ static const char *cmd_prefix[] = {
[IPSET_TEST] = "test SETNAME",
};
-/* Workhorses */
+static struct ipset_xlate_set *
+ipset_xlate_set_get(struct ipset *ipset, const char *name)
+{
+ struct ipset_xlate_set *set;
-/**
- * ipset_parse_argv - parse and argv array and execute the command
- * @ipset: ipset structure
- * @argc: length of the array
- * @argv: array of strings
- *
- * Parse an array of strings and execute the ipset command.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
+ list_for_each_entry(set, &ipset->xlate_sets, list) {
+ if (!strcmp(set->name, name))
+ return set;
+ }
+
+ return NULL;
+}
+
+static int
+ipset_parser(struct ipset *ipset, int oargc, char *oargv[])
{
int ret = 0;
enum ipset_cmd cmd = IPSET_CMD_NONE;
@@ -943,12 +961,17 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
char *arg0 = NULL, *arg1 = NULL;
const struct ipset_envopts *opt;
const struct ipset_commands *command;
- const struct ipset_type *type;
+ const struct ipset_type *type = NULL;
struct ipset_session *session = ipset->session;
void *p = ipset_session_printf_private(session);
int argc = oargc;
char *argv[MAX_ARGS] = {};
+ if (argc > MAX_ARGS)
+ return ipset->custom_error(ipset,
+ p, IPSET_PARAMETER_PROBLEM,
+ "Line is too long to parse.");
+
/* We need a local copy because of ipset_shift_argv */
memcpy(argv, oargv, sizeof(char *) * argc);
@@ -1107,6 +1130,7 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
if (arg0) {
const struct ipset_arg *arg;
int k;
+ enum ipset_adt c;
/* Type-specific help, without kernel checking */
type = type_find(arg0);
@@ -1116,11 +1140,11 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
"Unknown settype: `%s'", arg0);
printf("\n%s type specific options:\n\n", type->name);
for (i = 0; cmd_help_order[i] != IPSET_CADT_MAX; i++) {
- cmd = cmd_help_order[i];
+ c = cmd_help_order[i];
printf("%s %s %s\n",
- cmd_prefix[cmd], type->name, type->cmd[cmd].help);
- for (k = 0; type->cmd[cmd].args[k] != IPSET_ARG_NONE; k++) {
- arg = ipset_keyword(type->cmd[cmd].args[k]);
+ cmd_prefix[c], type->name, type->cmd[c].help);
+ for (k = 0; type->cmd[c].args[k] != IPSET_ARG_NONE; k++) {
+ arg = ipset_keyword(type->cmd[c].args[k]);
if (!arg->help || arg->help[0] == '\0')
continue;
printf(" %s\n", arg->help);
@@ -1208,6 +1232,7 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
return ret;
}
/* Fall through to parse optional setname */
+ fallthrough;
case IPSET_CMD_DESTROY:
case IPSET_CMD_FLUSH:
/* Args: [setname] */
@@ -1236,7 +1261,7 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
return ipset->custom_error(ipset,
p, IPSET_PARAMETER_PROBLEM,
"Unknown argument %s", argv[1]);
- return restore(ipset);
+ return IPSET_CMD_RESTORE;
case IPSET_CMD_ADD:
case IPSET_CMD_DEL:
case IPSET_CMD_TEST:
@@ -1246,7 +1271,20 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
if (ret < 0)
return ipset->standard_error(ipset, p);
- type = ipset_type_get(session, cmd);
+ if (!ipset->xlate) {
+ type = ipset_type_get(session, cmd);
+ } else {
+ const struct ipset_xlate_set *xlate_set;
+
+ xlate_set = ipset_xlate_set_get(ipset, arg0);
+ if (xlate_set) {
+ ipset_session_data_set(session, IPSET_OPT_TYPE,
+ xlate_set->type);
+ ipset_session_data_set(session, IPSET_OPT_FAMILY,
+ &xlate_set->family);
+ type = xlate_set->type;
+ }
+ }
if (type == NULL)
return ipset->standard_error(ipset, p);
@@ -1273,6 +1311,37 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
if (argc > 1)
return ipset->custom_error(ipset, p, IPSET_PARAMETER_PROBLEM,
"Unknown argument %s", argv[1]);
+
+ return cmd;
+}
+
+/* Workhorses */
+
+/**
+ * ipset_parse_argv - parse and argv array and execute the command
+ * @ipset: ipset structure
+ * @argc: length of the array
+ * @argv: array of strings
+ *
+ * Parse an array of strings and execute the ipset command.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int
+ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
+{
+ struct ipset_session *session = ipset->session;
+ void *p = ipset_session_printf_private(session);
+ enum ipset_cmd cmd;
+ int ret;
+
+ cmd = ipset_parser(ipset, oargc, oargv);
+ if (cmd < 0)
+ return cmd;
+
+ if (cmd == IPSET_CMD_RESTORE)
+ return restore(ipset);
+
ret = ipset_cmd(session, cmd, ipset->restore_line);
D("ret %d", ret);
/* In the case of warning, the return code is success */
@@ -1448,6 +1517,9 @@ ipset_init(void)
return NULL;
}
ipset_custom_printf(ipset, NULL, NULL, NULL, NULL);
+
+ INIT_LIST_HEAD(&ipset->xlate_sets);
+
return ipset;
}
@@ -1462,6 +1534,8 @@ ipset_init(void)
int
ipset_fini(struct ipset *ipset)
{
+ struct ipset_xlate_set *xlate_set, *next;
+
assert(ipset);
if (ipset->session)
@@ -1470,6 +1544,498 @@ ipset_fini(struct ipset *ipset)
if (ipset->newargv[0])
free(ipset->newargv[0]);
+ list_for_each_entry_safe(xlate_set, next, &ipset->xlate_sets, list)
+ free(xlate_set);
+
free(ipset);
return 0;
}
+
+/* Ignore the set family, use inet. */
+static const char *ipset_xlate_family(uint8_t family UNUSED)
+{
+ return "inet";
+}
+
+enum ipset_xlate_set_type {
+ IPSET_XLATE_TYPE_UNKNOWN = 0,
+ IPSET_XLATE_TYPE_HASH_MAC,
+ IPSET_XLATE_TYPE_HASH_IP,
+ IPSET_XLATE_TYPE_HASH_IP_MAC,
+ IPSET_XLATE_TYPE_HASH_NET_IFACE,
+ IPSET_XLATE_TYPE_HASH_NET_PORT,
+ IPSET_XLATE_TYPE_HASH_NET_PORT_NET,
+ IPSET_XLATE_TYPE_HASH_NET_NET,
+ IPSET_XLATE_TYPE_HASH_NET,
+ IPSET_XLATE_TYPE_HASH_IP_PORT_NET,
+ IPSET_XLATE_TYPE_HASH_IP_PORT_IP,
+ IPSET_XLATE_TYPE_HASH_IP_MARK,
+ IPSET_XLATE_TYPE_HASH_IP_PORT,
+ IPSET_XLATE_TYPE_BITMAP_PORT,
+ IPSET_XLATE_TYPE_BITMAP_IP_MAC,
+ IPSET_XLATE_TYPE_BITMAP_IP,
+};
+
+static enum ipset_xlate_set_type ipset_xlate_set_type(const char *typename)
+{
+ if (!strcmp(typename, "hash:mac"))
+ return IPSET_XLATE_TYPE_HASH_MAC;
+ else if (!strcmp(typename, "hash:ip"))
+ return IPSET_XLATE_TYPE_HASH_IP;
+ else if (!strcmp(typename, "hash:ip,mac"))
+ return IPSET_XLATE_TYPE_HASH_IP_MAC;
+ else if (!strcmp(typename, "hash:net,iface"))
+ return IPSET_XLATE_TYPE_HASH_NET_IFACE;
+ else if (!strcmp(typename, "hash:net,port"))
+ return IPSET_XLATE_TYPE_HASH_NET_PORT;
+ else if (!strcmp(typename, "hash:net,port,net"))
+ return IPSET_XLATE_TYPE_HASH_NET_PORT_NET;
+ else if (!strcmp(typename, "hash:net,net"))
+ return IPSET_XLATE_TYPE_HASH_NET_NET;
+ else if (!strcmp(typename, "hash:net"))
+ return IPSET_XLATE_TYPE_HASH_NET;
+ else if (!strcmp(typename, "hash:ip,port,net"))
+ return IPSET_XLATE_TYPE_HASH_IP_PORT_NET;
+ else if (!strcmp(typename, "hash:ip,port,ip"))
+ return IPSET_XLATE_TYPE_HASH_IP_PORT_IP;
+ else if (!strcmp(typename, "hash:ip,mark"))
+ return IPSET_XLATE_TYPE_HASH_IP_MARK;
+ else if (!strcmp(typename, "hash:ip,port"))
+ return IPSET_XLATE_TYPE_HASH_IP_PORT;
+ else if (!strcmp(typename, "hash:ip"))
+ return IPSET_XLATE_TYPE_HASH_IP;
+ else if (!strcmp(typename, "bitmap:port"))
+ return IPSET_XLATE_TYPE_BITMAP_PORT;
+ else if (!strcmp(typename, "bitmap:ip,mac"))
+ return IPSET_XLATE_TYPE_BITMAP_IP_MAC;
+ else if (!strcmp(typename, "bitmap:ip"))
+ return IPSET_XLATE_TYPE_BITMAP_IP;
+
+ return IPSET_XLATE_TYPE_UNKNOWN;
+}
+
+#define NFT_SET_INTERVAL (1 << 0)
+
+static const char *
+ipset_xlate_type_to_nftables(int family, enum ipset_xlate_set_type type,
+ uint32_t *flags)
+{
+ switch (type) {
+ case IPSET_XLATE_TYPE_HASH_MAC:
+ return "ether_addr";
+ case IPSET_XLATE_TYPE_HASH_IP:
+ if (family == AF_INET)
+ return "ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_IP_MAC:
+ if (family == AF_INET)
+ return "ipv4_addr . ether_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . ether_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_NET_IFACE:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr . ifname";
+ else if (family == AF_INET6)
+ return "ipv6_addr . ifname";
+ break;
+ case IPSET_XLATE_TYPE_HASH_NET_PORT:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr . inet_proto . inet_service";
+ else if (family == AF_INET6)
+ return "ipv6_addr . inet_proto . inet_service";
+ break;
+ case IPSET_XLATE_TYPE_HASH_NET_PORT_NET:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr . inet_proto . inet_service . ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . inet_proto . inet_service . ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_NET_NET:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr . ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_NET:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_IP_PORT_NET:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr . inet_proto . inet_service . ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . inet_proto . inet_service . ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_IP_PORT_IP:
+ if (family == AF_INET)
+ return "ipv4_addr . inet_proto . inet_service . ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . inet_proto . inet_service . ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_IP_MARK:
+ if (family == AF_INET)
+ return "ipv4_addr . mark";
+ else if (family == AF_INET6)
+ return "ipv6_addr . mark";
+ break;
+ case IPSET_XLATE_TYPE_HASH_IP_PORT:
+ if (family == AF_INET)
+ return "ipv4_addr . inet_proto . inet_service";
+ else if (family == AF_INET6)
+ return "ipv6_addr . inet_proto . inet_service";
+ break;
+ case IPSET_XLATE_TYPE_BITMAP_PORT:
+ return "inet_service";
+ case IPSET_XLATE_TYPE_BITMAP_IP_MAC:
+ if (family == AF_INET)
+ return "ipv4_addr . ether_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . ether_addr";
+ break;
+ case IPSET_XLATE_TYPE_BITMAP_IP:
+ if (family == AF_INET)
+ return "ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_UNKNOWN:
+ break;
+ default:
+ break;
+ }
+ /* This should not ever happen. */
+ return "unknown";
+}
+
+static int ipset_xlate(struct ipset *ipset, enum ipset_cmd cmd,
+ const char *table)
+{
+ const char *set, *typename, *nft_type;
+ const struct ipset_type *ipset_type;
+ struct ipset_xlate_set *xlate_set;
+ enum ipset_xlate_set_type type;
+ struct ipset_session *session;
+ const uint32_t *cadt_flags;
+ const uint32_t *timeout;
+ const uint32_t *maxelem;
+ struct ipset_data *data;
+ const uint8_t *netmask;
+ const char *comment;
+ uint32_t flags = 0;
+ uint8_t family;
+ char buf[64];
+ bool concat;
+ char *term;
+
+ session = ipset_session(ipset);
+ data = ipset_session_data(session);
+
+ set = ipset_data_get(data, IPSET_SETNAME);
+ family = ipset_data_family(data);
+
+ switch (cmd) {
+ case IPSET_CMD_CREATE:
+ /* Not supported. */
+ if (ipset_data_test(data, IPSET_OPT_MARKMASK)) {
+ printf("# %s", ipset->cmdline);
+ break;
+ }
+ cadt_flags = ipset_data_get(data, IPSET_OPT_CADT_FLAGS);
+
+ /* Ignore:
+ * - IPSET_FLAG_WITH_COMMENT
+ * - IPSET_FLAG_WITH_FORCEADD
+ */
+ if (cadt_flags &&
+ (*cadt_flags & (IPSET_FLAG_BEFORE |
+ IPSET_FLAG_PHYSDEV |
+ IPSET_FLAG_NOMATCH |
+ IPSET_FLAG_WITH_SKBINFO |
+ IPSET_FLAG_IFACE_WILDCARD))) {
+ printf("# %s", ipset->cmdline);
+ break;
+ }
+
+ typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
+ type = ipset_xlate_set_type(typename);
+ nft_type = ipset_xlate_type_to_nftables(family, type, &flags);
+
+ printf("add set %s %s %s { type %s; ",
+ ipset_xlate_family(family), table, set, nft_type);
+ if (cadt_flags) {
+ if (*cadt_flags & IPSET_FLAG_WITH_COUNTERS)
+ printf("counter; ");
+ }
+ timeout = ipset_data_get(data, IPSET_OPT_TIMEOUT);
+ if (timeout)
+ printf("timeout %us; ", *timeout);
+ maxelem = ipset_data_get(data, IPSET_OPT_MAXELEM);
+ if (maxelem)
+ printf("size %u; ", *maxelem);
+
+ netmask = ipset_data_get(data, IPSET_OPT_NETMASK);
+ if (netmask &&
+ ((family == AF_INET && *netmask < 32) ||
+ (family == AF_INET6 && *netmask < 128)))
+ flags |= NFT_SET_INTERVAL;
+
+ if (flags & NFT_SET_INTERVAL)
+ printf("flags interval; ");
+
+ /* These create-specific options are safe to be ignored:
+ * - IPSET_OPT_GC
+ * - IPSET_OPT_HASHSIZE
+ * - IPSET_OPT_PROBES
+ * - IPSET_OPT_RESIZE
+ * - IPSET_OPT_SIZE
+ * - IPSET_OPT_FORCEADD
+ *
+ * Ranges and CIDR are safe to be ignored too:
+ * - IPSET_OPT_IP_FROM
+ * - IPSET_OPT_IP_TO
+ * - IPSET_OPT_PORT_FROM
+ * - IPSET_OPT_PORT_TO
+ */
+
+ printf("}\n");
+
+ xlate_set = calloc(1, sizeof(*xlate_set));
+ if (!xlate_set)
+ return -1;
+
+ snprintf(xlate_set->name, sizeof(xlate_set->name), "%s", set);
+ ipset_type = ipset_types();
+ while (ipset_type) {
+ if (!strcmp(ipset_type->name, typename))
+ break;
+ ipset_type = ipset_type->next;
+ }
+
+ xlate_set->family = family;
+ xlate_set->type = ipset_type;
+ if (netmask) {
+ xlate_set->netmask = *netmask;
+ xlate_set->interval = true;
+ }
+ list_add_tail(&xlate_set->list, &ipset->xlate_sets);
+ break;
+ case IPSET_CMD_DESTROY:
+ printf("del set %s %s %s\n",
+ ipset_xlate_family(family), table, set);
+ break;
+ case IPSET_CMD_FLUSH:
+ if (!set) {
+ printf("# %s", ipset->cmdline);
+ } else {
+ printf("flush set %s %s %s\n",
+ ipset_xlate_family(family), table, set);
+ }
+ break;
+ case IPSET_CMD_RENAME:
+ printf("# %s", ipset->cmdline);
+ return -1;
+ case IPSET_CMD_SWAP:
+ printf("# %s", ipset->cmdline);
+ return -1;
+ case IPSET_CMD_LIST:
+ if (!set) {
+ printf("list sets %s %s\n",
+ ipset_xlate_family(family), table);
+ } else {
+ printf("list set %s %s %s\n",
+ ipset_xlate_family(family), table, set);
+ }
+ break;
+ case IPSET_CMD_SAVE:
+ printf("# %s", ipset->cmdline);
+ return -1;
+ case IPSET_CMD_ADD:
+ case IPSET_CMD_DEL:
+ case IPSET_CMD_TEST:
+ /* Not supported. */
+ if (ipset_data_test(data, IPSET_OPT_NOMATCH) ||
+ ipset_data_test(data, IPSET_OPT_SKBINFO) ||
+ ipset_data_test(data, IPSET_OPT_SKBMARK) ||
+ ipset_data_test(data, IPSET_OPT_SKBPRIO) ||
+ ipset_data_test(data, IPSET_OPT_SKBQUEUE) ||
+ ipset_data_test(data, IPSET_OPT_IFACE_WILDCARD)) {
+ printf("# %s", ipset->cmdline);
+ break;
+ }
+ printf("%s element %s %s %s { ",
+ cmd == IPSET_CMD_ADD ? "add" :
+ cmd == IPSET_CMD_DEL ? "delete" : "get",
+ ipset_xlate_family(family), table, set);
+
+ xlate_set = (struct ipset_xlate_set *)
+ ipset_xlate_set_get(ipset, set);
+ if (xlate_set && xlate_set->interval)
+ netmask = &xlate_set->netmask;
+ else
+ netmask = NULL;
+
+ concat = false;
+ if (ipset_data_test(data, IPSET_OPT_IP)) {
+ ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_IP, 0);
+ printf("%s", buf);
+ if (netmask)
+ printf("/%u ", *netmask);
+ else
+ printf(" ");
+
+ concat = true;
+ }
+ if (ipset_data_test(data, IPSET_OPT_MARK)) {
+ ipset_print_mark(buf, sizeof(buf), data, IPSET_OPT_MARK, 0);
+ printf("%s%s ", concat ? ". " : "", buf);
+ }
+ if (ipset_data_test(data, IPSET_OPT_IFACE)) {
+ ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_IFACE, 0);
+ printf("%s%s ", concat ? ". " : "", buf);
+ }
+ if (ipset_data_test(data, IPSET_OPT_ETHER)) {
+ ipset_print_ether(buf, sizeof(buf), data, IPSET_OPT_ETHER, 0);
+ size_t i;
+
+ for (i = 0; i < strlen(buf); i++)
+ buf[i] = tolower(buf[i]);
+
+ printf("%s%s ", concat ? ". " : "", buf);
+ concat = true;
+ }
+ if (ipset_data_test(data, IPSET_OPT_PORT)) {
+ ipset_print_proto_port(buf, sizeof(buf), data, IPSET_OPT_PORT, 0);
+ term = strchr(buf, ':');
+ if (term) {
+ *term = '\0';
+ printf("%s%s ", concat ? ". " : "", buf);
+ }
+ ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_PORT, 0);
+ printf("%s%s ", concat ? ". " : "", buf);
+ }
+ if (ipset_data_test(data, IPSET_OPT_IP2)) {
+ ipset_print_ip(buf, sizeof(buf), data, IPSET_OPT_IP2, 0);
+ printf("%s%s", concat ? ". " : "", buf);
+ if (netmask)
+ printf("/%u ", *netmask);
+ else
+ printf(" ");
+ }
+ if (ipset_data_test(data, IPSET_OPT_PACKETS) &&
+ ipset_data_test(data, IPSET_OPT_BYTES)) {
+ const uint64_t *pkts, *bytes;
+
+ pkts = ipset_data_get(data, IPSET_OPT_PACKETS);
+ bytes = ipset_data_get(data, IPSET_OPT_BYTES);
+
+ printf("counter packets %" PRIu64 " bytes %" PRIu64 " ",
+ *pkts, *bytes);
+ }
+ timeout = ipset_data_get(data, IPSET_OPT_TIMEOUT);
+ if (timeout)
+ printf("timeout %us ", *timeout);
+
+ comment = ipset_data_get(data, IPSET_OPT_ADT_COMMENT);
+ if (comment)
+ printf("comment \"%s\" ", comment);
+
+ printf("}\n");
+ break;
+ case IPSET_CMD_GET_BYNAME:
+ printf("# %s", ipset->cmdline);
+ return -1;
+ case IPSET_CMD_GET_BYINDEX:
+ printf("# %s", ipset->cmdline);
+ return -1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int ipset_xlate_restore(struct ipset *ipset)
+{
+ struct ipset_session *session = ipset_session(ipset);
+ struct ipset_data *data = ipset_session_data(session);
+ void *p = ipset_session_printf_private(session);
+ enum ipset_cmd cmd;
+ FILE *f = stdin;
+ int ret = 0;
+ char *c;
+
+ if (ipset->filename) {
+ f = fopen(ipset->filename, "r");
+ if (!f) {
+ fprintf(stderr, "cannot open file `%s'\n", ipset->filename);
+ return -1;
+ }
+ }
+
+ /* TODO: Allow to specify the table name other than 'global'. */
+ printf("add table inet global\n");
+
+ while (fgets(ipset->cmdline, sizeof(ipset->cmdline), f)) {
+ ipset->restore_line++;
+ c = ipset->cmdline;
+ while (isspace(c[0]))
+ c++;
+ if (c[0] == '\0' || c[0] == '#')
+ continue;
+ else if (STREQ(c, "COMMIT\n") || STREQ(c, "COMMIT\r\n"))
+ continue;
+
+ ret = build_argv(ipset, c);
+ if (ret < 0)
+ break;
+
+ cmd = ipset_parser(ipset, ipset->newargc, ipset->newargv);
+ if (cmd < 0)
+ ipset->standard_error(ipset, p);
+
+ /* TODO: Allow to specify the table name other than 'global'. */
+ ret = ipset_xlate(ipset, cmd, "global");
+ if (ret < 0)
+ break;
+
+ ipset_data_reset(data);
+ }
+
+ if (ipset->filename)
+ fclose(f);
+
+ return ret;
+}
+
+int ipset_xlate_argv(struct ipset *ipset, int argc, char *argv[])
+{
+ enum ipset_cmd cmd;
+ int ret;
+
+ ipset->xlate = true;
+
+ cmd = ipset_parser(ipset, argc, argv);
+ if (cmd < 0)
+ return cmd;
+
+ if (cmd == IPSET_CMD_RESTORE) {
+ ret = ipset_xlate_restore(ipset);
+ } else {
+ fprintf(stderr, "This command is not supported, "
+ "use `ipset-translate restore < file'\n");
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/lib/ipset_hash_ip.c b/lib/ipset_hash_ip.c
index 2ef1af3..4f96ebb 100644
--- a/lib/ipset_hash_ip.c
+++ b/lib/ipset_hash_ip.c
@@ -393,6 +393,175 @@ static struct ipset_type ipset_hash_ip4 = {
.description = "skbinfo support",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_ip5 = {
+ .name = "hash:ip",
+ .alias = { "iphash", NULL },
+ .revision = 5,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_ONE,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_single6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_NETMASK,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ /* Ignored options: backward compatibilty */
+ IPSET_ARG_PROBES,
+ IPSET_ARG_RESIZE,
+ IPSET_ARG_GC,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO),
+ .help = "IP",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO),
+ .help = "IP",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO),
+ .help = "IP",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is a valid IPv4 or IPv6 address (or hostname),\n"
+ " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
+ " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
+ " is supported for IPv4.",
+ .description = "bucketsize, initval support",
+};
+
+/* bitmask support */
+static struct ipset_type ipset_hash_ip6 = {
+ .name = "hash:ip",
+ .alias = { "iphash", NULL },
+ .revision = 6,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_ONE,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_single6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_NETMASK,
+ IPSET_ARG_BITMASK,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ /* Ignored options: backward compatibilty */
+ IPSET_ARG_PROBES,
+ IPSET_ARG_RESIZE,
+ IPSET_ARG_GC,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO),
+ .help = "IP",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO),
+ .help = "IP",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO),
+ .help = "IP",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is a valid IPv4 or IPv6 address (or hostname),\n"
+ " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
+ " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
+ " is supported for IPv4.",
+ .description = "bitmask support",
+};
+
void _init(void);
void _init(void)
{
@@ -401,4 +570,6 @@ void _init(void)
ipset_type_add(&ipset_hash_ip2);
ipset_type_add(&ipset_hash_ip3);
ipset_type_add(&ipset_hash_ip4);
+ ipset_type_add(&ipset_hash_ip5);
+ ipset_type_add(&ipset_hash_ip6);
}
diff --git a/lib/ipset_hash_ipmac.c b/lib/ipset_hash_ipmac.c
index c64e1be..c15897b 100644
--- a/lib/ipset_hash_ipmac.c
+++ b/lib/ipset_hash_ipmac.c
@@ -91,8 +91,93 @@ static struct ipset_type ipset_hash_ipmac0 = {
.description = "Initial revision",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_ipmac1 = {
+ .name = "hash:ip,mac",
+ .alias = { "ipmachash", NULL },
+ .revision = 1,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_TWO,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_single6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_ether,
+ .print = ipset_print_ether,
+ .opt = IPSET_OPT_ETHER
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_ETHER),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_ETHER),
+ .help = "IP,MAC",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_ETHER),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_ETHER),
+ .help = "IP,MAC",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_ETHER),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_ETHER),
+ .help = "IP,MAC",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is a valid IPv4 or IPv6 address (or hostname),\n"
+ " MAC is a MAC address.",
+ .description = "bucketsize, initval support",
+};
+
void _init(void);
void _init(void)
{
ipset_type_add(&ipset_hash_ipmac0);
+ ipset_type_add(&ipset_hash_ipmac1);
}
diff --git a/lib/ipset_hash_ipmark.c b/lib/ipset_hash_ipmark.c
index 42b1979..7d6d977 100644
--- a/lib/ipset_hash_ipmark.c
+++ b/lib/ipset_hash_ipmark.c
@@ -289,10 +289,109 @@ static struct ipset_type ipset_hash_ipmark2 = {
.description = "skbinfo support",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_ipmark3 = {
+ .name = "hash:ip,mark",
+ .alias = { "ipmarkhash", NULL },
+ .revision = 3,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_TWO,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_single6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_mark,
+ .print = ipset_print_mark,
+ .opt = IPSET_OPT_MARK
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_MARKMASK,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ /* Ignored options: backward compatibilty */
+ IPSET_ARG_PROBES,
+ IPSET_ARG_RESIZE,
+ IPSET_ARG_IGNORED_FROM,
+ IPSET_ARG_IGNORED_TO,
+ IPSET_ARG_IGNORED_NETWORK,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_MARK),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_MARK),
+ .help = "IP,MARK",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_MARK),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_MARK),
+ .help = "IP,MARK",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_MARK),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_MARK),
+ .help = "IP,MARK",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is a valid IPv4 or IPv6 address (or hostname).\n"
+ " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
+ " is supported for IPv4.\n"
+ " Adding/deleting single mark element\n"
+ " is supported both for IPv4 and IPv6.",
+ .description = "bucketsize, initval support",
+};
+
void _init(void);
void _init(void)
{
ipset_type_add(&ipset_hash_ipmark0);
ipset_type_add(&ipset_hash_ipmark1);
ipset_type_add(&ipset_hash_ipmark2);
+ ipset_type_add(&ipset_hash_ipmark3);
}
diff --git a/lib/ipset_hash_ipport.c b/lib/ipset_hash_ipport.c
index b48cac2..2fa8abd 100644
--- a/lib/ipset_hash_ipport.c
+++ b/lib/ipset_hash_ipport.c
@@ -499,6 +499,218 @@ static struct ipset_type ipset_hash_ipport5 = {
.description = "skbinfo support",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_ipport6 = {
+ .name = "hash:ip,port",
+ .alias = { "ipporthash", NULL },
+ .revision = 6,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_TWO,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_single6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_proto_port,
+ .print = ipset_print_proto_port,
+ .opt = IPSET_OPT_PORT
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ /* Ignored options: backward compatibilty */
+ IPSET_ARG_PROBES,
+ IPSET_ARG_RESIZE,
+ IPSET_ARG_IGNORED_FROM,
+ IPSET_ARG_IGNORED_TO,
+ IPSET_ARG_IGNORED_NETWORK,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO),
+ .help = "IP,[PROTO:]PORT",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO),
+ .help = "IP,[PROTO:]PORT",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT),
+ .help = "IP,[PROTO:]PORT",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is a valid IPv4 or IPv6 address (or hostname).\n"
+ " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
+ " is supported for IPv4.\n"
+ " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
+ " port range is supported both for IPv4 and IPv6.",
+ .usagefn = ipset_port_usage,
+ .description = "bucketsize, initval support",
+};
+
+/* bitmask support */
+static struct ipset_type ipset_hash_ipport7 = {
+ .name = "hash:ip,port",
+ .alias = { "ipporthash", NULL },
+ .revision = 7,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_TWO,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_single6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_proto_port,
+ .print = ipset_print_proto_port,
+ .opt = IPSET_OPT_PORT
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ IPSET_ARG_NETMASK,
+ IPSET_ARG_BITMASK,
+ /* Ignored options: backward compatibilty */
+ IPSET_ARG_PROBES,
+ IPSET_ARG_RESIZE,
+ IPSET_ARG_IGNORED_FROM,
+ IPSET_ARG_IGNORED_TO,
+ IPSET_ARG_IGNORED_NETWORK,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO),
+ .help = "IP,[PROTO:]PORT",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO),
+ .help = "IP,[PROTO:]PORT",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT),
+ .help = "IP,[PROTO:]PORT",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is a valid IPv4 or IPv6 address (or hostname).\n"
+ " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
+ " is supported for IPv4.\n"
+ " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
+ " port range is supported both for IPv4 and IPv6.",
+ .usagefn = ipset_port_usage,
+ .description = "netmask and bitmask support",
+};
+
void _init(void);
void _init(void)
{
@@ -507,4 +719,6 @@ void _init(void)
ipset_type_add(&ipset_hash_ipport3);
ipset_type_add(&ipset_hash_ipport4);
ipset_type_add(&ipset_hash_ipport5);
+ ipset_type_add(&ipset_hash_ipport6);
+ ipset_type_add(&ipset_hash_ipport7);
}
diff --git a/lib/ipset_hash_ipportip.c b/lib/ipset_hash_ipportip.c
index 545e50c..6b2e92e 100644
--- a/lib/ipset_hash_ipportip.c
+++ b/lib/ipset_hash_ipportip.c
@@ -554,6 +554,122 @@ static struct ipset_type ipset_hash_ipportip5 = {
.description = "skbinfo support",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_ipportip6 = {
+ .name = "hash:ip,port,ip",
+ .alias = { "ipportiphash", NULL },
+ .revision = 6,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_THREE,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_single6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_proto_port,
+ .print = ipset_print_proto_port,
+ .opt = IPSET_OPT_PORT
+ },
+ [IPSET_DIM_THREE - 1] = {
+ .parse = ipset_parse_single_ip,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP2
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ /* Ignored options: backward compatibilty */
+ IPSET_ARG_PROBES,
+ IPSET_ARG_RESIZE,
+ IPSET_ARG_IGNORED_FROM,
+ IPSET_ARG_IGNORED_TO,
+ IPSET_ARG_IGNORED_NETWORK,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .help = "IP,[PROTO:]PORT,IP",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .help = "IP,[PROTO:]PORT,IP",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .help = "IP,[PROTO:]PORT,IP",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is a valid IPv4 or IPv6 address (or hostname).\n"
+ " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
+ " in the first IP component is supported for IPv4.\n"
+ " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
+ " port range is supported both for IPv4 and IPv6.",
+ .usagefn = ipset_port_usage,
+ .description = "bucketsize, initval support",
+};
+
void _init(void);
void _init(void)
{
@@ -562,4 +678,5 @@ void _init(void)
ipset_type_add(&ipset_hash_ipportip3);
ipset_type_add(&ipset_hash_ipportip4);
ipset_type_add(&ipset_hash_ipportip5);
+ ipset_type_add(&ipset_hash_ipportip6);
}
diff --git a/lib/ipset_hash_ipportnet.c b/lib/ipset_hash_ipportnet.c
index 94a680e..2552cdb 100644
--- a/lib/ipset_hash_ipportnet.c
+++ b/lib/ipset_hash_ipportnet.c
@@ -812,6 +812,130 @@ static struct ipset_type ipset_hash_ipportnet7 = {
.description = "skbinfo support",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_ipportnet8 = {
+ .name = "hash:ip,port,net",
+ .alias = { "ipportnethash", NULL },
+ .revision = 8,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_THREE,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_single6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_proto_port,
+ .print = ipset_print_proto_port,
+ .opt = IPSET_OPT_PORT
+ },
+ [IPSET_DIM_THREE - 1] = {
+ .parse = ipset_parse_ip4_net6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP2
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ /* Ignored options: backward compatibilty */
+ IPSET_ARG_PROBES,
+ IPSET_ARG_RESIZE,
+ IPSET_ARG_IGNORED_FROM,
+ IPSET_ARG_IGNORED_TO,
+ IPSET_ARG_IGNORED_NETWORK,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2)
+ | IPSET_FLAG(IPSET_OPT_IP2_TO),
+ .help = "IP,[PROTO:]PORT,IP[/CIDR]",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2)
+ | IPSET_FLAG(IPSET_OPT_IP2_TO),
+ .help = "IP,[PROTO:]PORT,IP[/CIDR]",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2),
+ .help = "IP,[PROTO:]PORT,IP[/CIDR]",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP are valid IPv4 or IPv6 addresses (or hostnames),\n"
+ " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
+ " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
+ " in the first IP component is supported for IPv4.\n"
+ " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
+ " port range is supported both for IPv4 and IPv6.",
+ .usagefn = ipset_port_usage,
+ .description = "bucketsize, initval support",
+};
+
void _init(void);
void _init(void)
{
@@ -822,4 +946,5 @@ void _init(void)
ipset_type_add(&ipset_hash_ipportnet5);
ipset_type_add(&ipset_hash_ipportnet6);
ipset_type_add(&ipset_hash_ipportnet7);
+ ipset_type_add(&ipset_hash_ipportnet8);
}
diff --git a/lib/ipset_hash_mac.c b/lib/ipset_hash_mac.c
index 426c384..4b20247 100644
--- a/lib/ipset_hash_mac.c
+++ b/lib/ipset_hash_mac.c
@@ -75,8 +75,77 @@ static struct ipset_type ipset_hash_mac0 = {
.description = "Initial revision",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_mac1 = {
+ .name = "hash:mac",
+ .alias = { "machash", NULL },
+ .revision = 1,
+ .family = NFPROTO_UNSPEC,
+ .dimension = IPSET_DIM_ONE,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ether,
+ .print = ipset_print_ether,
+ .opt = IPSET_OPT_ETHER
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_ETHER),
+ .full = IPSET_FLAG(IPSET_OPT_ETHER),
+ .help = "MAC",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_ETHER),
+ .full = IPSET_FLAG(IPSET_OPT_ETHER),
+ .help = "MAC",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_ETHER),
+ .full = IPSET_FLAG(IPSET_OPT_ETHER),
+ .help = "MAC",
+ },
+ },
+ .usage = "",
+ .description = "bucketsize, initval support",
+};
+
void _init(void);
void _init(void)
{
ipset_type_add(&ipset_hash_mac0);
+ ipset_type_add(&ipset_hash_mac1);
}
diff --git a/lib/ipset_hash_net.c b/lib/ipset_hash_net.c
index ef9e19c..1da95bf 100644
--- a/lib/ipset_hash_net.c
+++ b/lib/ipset_hash_net.c
@@ -531,6 +531,90 @@ static struct ipset_type ipset_hash_net6 = {
.description = "skbinfo support",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_net7 = {
+ .name = "hash:net",
+ .alias = { "nethash", NULL },
+ .revision = 7,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_ONE,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_net6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ /* Ignored options: backward compatibilty */
+ IPSET_ARG_PROBES,
+ IPSET_ARG_RESIZE,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO),
+ .help = "IP[/CIDR]",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO),
+ .help = "IP[/CIDR]",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR),
+ .help = "IP[/CIDR]",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is an IPv4 or IPv6 address (or hostname),\n"
+ " CIDR is a valid IPv4 or IPv6 CIDR prefix.",
+ .description = "bucketsize, initval support",
+};
+
void _init(void);
void _init(void)
{
@@ -541,4 +625,5 @@ void _init(void)
ipset_type_add(&ipset_hash_net4);
ipset_type_add(&ipset_hash_net5);
ipset_type_add(&ipset_hash_net6);
+ ipset_type_add(&ipset_hash_net7);
}
diff --git a/lib/ipset_hash_netiface.c b/lib/ipset_hash_netiface.c
index 6755782..172c2a9 100644
--- a/lib/ipset_hash_netiface.c
+++ b/lib/ipset_hash_netiface.c
@@ -619,6 +619,7 @@ static struct ipset_type ipset_hash_netiface6 = {
" Adding/deleting multiple elements with IPv4 is supported.",
.description = "skbinfo support",
};
+
/* interface wildcard support */
static struct ipset_type ipset_hash_netiface7 = {
.name = "hash:net,iface",
@@ -714,6 +715,103 @@ static struct ipset_type ipset_hash_netiface7 = {
.description = "skbinfo and wildcard support",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_netiface8 = {
+ .name = "hash:net,iface",
+ .alias = { "netifacehash", NULL },
+ .revision = 8,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_TWO,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_net6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_iface,
+ .print = ipset_print_iface,
+ .opt = IPSET_OPT_IFACE
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_IFACE_WILDCARD,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IFACE),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_IFACE)
+ | IPSET_FLAG(IPSET_OPT_PHYSDEV),
+ .help = "IP[/CIDR]|FROM-TO,[physdev:]IFACE",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IFACE),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_IFACE)
+ | IPSET_FLAG(IPSET_OPT_PHYSDEV),
+ .help = "IP[/CIDR]|FROM-TO,[physdev:]IFACE",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IFACE),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IFACE)
+ | IPSET_FLAG(IPSET_OPT_PHYSDEV),
+ .help = "IP[/CIDR],[physdev:]IFACE",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is a valid IPv4 or IPv6 address (or hostname),\n"
+ " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
+ " Adding/deleting multiple elements with IPv4 is supported.",
+ .description = "bucketsize, initval support",
+};
+
void _init(void);
void _init(void)
{
@@ -725,4 +823,5 @@ void _init(void)
ipset_type_add(&ipset_hash_netiface5);
ipset_type_add(&ipset_hash_netiface6);
ipset_type_add(&ipset_hash_netiface7);
+ ipset_type_add(&ipset_hash_netiface8);
}
diff --git a/lib/ipset_hash_netnet.c b/lib/ipset_hash_netnet.c
index 9918b47..0e176e3 100644
--- a/lib/ipset_hash_netnet.c
+++ b/lib/ipset_hash_netnet.c
@@ -289,10 +289,210 @@ static struct ipset_type ipset_hash_netnet2 = {
.description = "skbinfo support",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_netnet3 = {
+ .name = "hash:net,net",
+ .alias = { "netnethash", NULL },
+ .revision = 3,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_TWO,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_net6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_ip4_net6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP2
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2)
+ | IPSET_FLAG(IPSET_OPT_IP2_TO),
+ .help = "IP[/CIDR]|FROM-TO,IP[/CIDR]|FROM-TO",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2)
+ | IPSET_FLAG(IPSET_OPT_IP2_TO),
+ .help = "IP[/CIDR]|FROM-TO,IP[/CIDR]|FROM-TO",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2),
+ .help = "IP[/CIDR],IP[/CIDR]",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is an IPv4 or IPv6 address (or hostname),\n"
+ " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
+ " IP range is not supported with IPv6.",
+ .description = "bucketsize, initval support",
+};
+
+/* bitmask support */
+static struct ipset_type ipset_hash_netnet4 = {
+ .name = "hash:net,net",
+ .alias = { "netnethash", NULL },
+ .revision = 4,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_TWO,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_net6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_ip4_net6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP2
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ IPSET_ARG_BITMASK,
+ IPSET_ARG_NETMASK,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2)
+ | IPSET_FLAG(IPSET_OPT_IP2_TO),
+ .help = "IP[/CIDR]|FROM-TO,IP[/CIDR]|FROM-TO",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2)
+ | IPSET_FLAG(IPSET_OPT_IP2_TO),
+ .help = "IP[/CIDR]|FROM-TO,IP[/CIDR]|FROM-TO",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2),
+ .help = "IP[/CIDR],IP[/CIDR]",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is an IPv4 or IPv6 address (or hostname),\n"
+ " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
+ " IP range is not supported with IPv6.",
+ .description = "netmask and bitmask support",
+};
+
void _init(void);
void _init(void)
{
ipset_type_add(&ipset_hash_netnet0);
ipset_type_add(&ipset_hash_netnet1);
ipset_type_add(&ipset_hash_netnet2);
+ ipset_type_add(&ipset_hash_netnet3);
+ ipset_type_add(&ipset_hash_netnet4);
}
diff --git a/lib/ipset_hash_netport.c b/lib/ipset_hash_netport.c
index 48501ce..f09de83 100644
--- a/lib/ipset_hash_netport.c
+++ b/lib/ipset_hash_netport.c
@@ -665,6 +665,109 @@ static struct ipset_type ipset_hash_netport7 = {
.description = "skbinfo support",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_netport8 = {
+ .name = "hash:net,port",
+ .alias = { "netporthash", NULL },
+ .revision = 8,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_TWO,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_net6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_proto_port,
+ .print = ipset_print_proto_port,
+ .opt = IPSET_OPT_PORT
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO),
+ .help = "IP[/CIDR]|FROM-TO,[PROTO:]PORT",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO),
+ .help = "IP[/CIDR]|FROM-TO,[PROTO:]PORT",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_CIDR),
+ .help = "IP[/CIDR],[PROTO:]PORT",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP is a valid IPv4 or IPv6 address (or hostname),\n"
+ " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
+ " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
+ " port range is supported both for IPv4 and IPv6.",
+ .usagefn = ipset_port_usage,
+ .description = "bucketsize, initval support",
+};
+
void _init(void);
void _init(void)
{
@@ -675,4 +778,5 @@ void _init(void)
ipset_type_add(&ipset_hash_netport5);
ipset_type_add(&ipset_hash_netport6);
ipset_type_add(&ipset_hash_netport7);
+ ipset_type_add(&ipset_hash_netport8);
}
diff --git a/lib/ipset_hash_netportnet.c b/lib/ipset_hash_netportnet.c
index 0b36bd5..a4a7240 100644
--- a/lib/ipset_hash_netportnet.c
+++ b/lib/ipset_hash_netportnet.c
@@ -358,10 +358,132 @@ static struct ipset_type ipset_hash_netportnet2 = {
.description = "skbinfo support",
};
+/* bucketsize support */
+static struct ipset_type ipset_hash_netportnet3 = {
+ .name = "hash:net,port,net",
+ .alias = { "netportnethash", NULL },
+ .revision = 3,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_THREE,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_net6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_proto_port,
+ .print = ipset_print_proto_port,
+ .opt = IPSET_OPT_PORT
+ },
+ [IPSET_DIM_THREE - 1] = {
+ .parse = ipset_parse_ip4_net6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP2
+ },
+ },
+ .cmd = {
+ [IPSET_CREATE] = {
+ .args = {
+ IPSET_ARG_FAMILY,
+ /* Aliases */
+ IPSET_ARG_INET,
+ IPSET_ARG_INET6,
+ IPSET_ARG_HASHSIZE,
+ IPSET_ARG_MAXELEM,
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_COUNTERS,
+ IPSET_ARG_COMMENT,
+ IPSET_ARG_FORCEADD,
+ IPSET_ARG_SKBINFO,
+ IPSET_ARG_BUCKETSIZE,
+ IPSET_ARG_INITVAL,
+ IPSET_ARG_NONE,
+ },
+ .need = 0,
+ .full = 0,
+ .help = "",
+ },
+ [IPSET_ADD] = {
+ .args = {
+ IPSET_ARG_TIMEOUT,
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_PACKETS,
+ IPSET_ARG_BYTES,
+ IPSET_ARG_ADT_COMMENT,
+ IPSET_ARG_SKBMARK,
+ IPSET_ARG_SKBPRIO,
+ IPSET_ARG_SKBQUEUE,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2)
+ | IPSET_FLAG(IPSET_OPT_IP2_TO),
+ .help = "IP[/CIDR],[PROTO:]PORT,IP[/CIDR]",
+ },
+ [IPSET_DEL] = {
+ .args = {
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_PORT_TO)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2)
+ | IPSET_FLAG(IPSET_OPT_IP2_TO),
+ .help = "IP[/CIDR],[PROTO:]PORT,IP[/CIDR]",
+ },
+ [IPSET_TEST] = {
+ .args = {
+ IPSET_ARG_NOMATCH,
+ IPSET_ARG_NONE,
+ },
+ .need = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_IP2),
+ .full = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_PROTO)
+ | IPSET_FLAG(IPSET_OPT_PORT)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP2)
+ | IPSET_FLAG(IPSET_OPT_CIDR2),
+ .help = "IP[/CIDR],[PROTO:]PORT,IP[/CIDR]",
+ },
+ },
+ .usage = "where depending on the INET family\n"
+ " IP are valid IPv4 or IPv6 addresses (or hostnames),\n"
+ " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
+ " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
+ " in both IP components are supported for IPv4.\n"
+ " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
+ " port range is supported both for IPv4 and IPv6.",
+ .usagefn = ipset_port_usage,
+ .description = "bucketsize, initval support",
+};
+
void _init(void);
void _init(void)
{
ipset_type_add(&ipset_hash_netportnet0);
ipset_type_add(&ipset_hash_netportnet1);
ipset_type_add(&ipset_hash_netportnet2);
+ ipset_type_add(&ipset_hash_netportnet3);
}
diff --git a/lib/libipset.map b/lib/libipset.map
index 7a4a33c..c69b738 100644
--- a/lib/libipset.map
+++ b/lib/libipset.map
@@ -202,3 +202,18 @@ global:
ipset_session_report_msg;
ipset_session_report_type;
} LIBIPSET_4.8;
+
+LIBIPSET_4.10 {
+global:
+ ipset_print_hexnumber;
+} LIBIPSET_4.9;
+
+LIBIPSET_4.11 {
+global:
+ ipset_xlate_argv;
+} LIBIPSET_4.10;
+
+LIBIPSET_4.12 {
+global:
+ ipset_parse_bitmask;
+} LIBIPSET_4.10;
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..6ea79cb 100644
--- a/lib/print.c
+++ b/lib/print.c
@@ -265,7 +265,7 @@ ipset_print_ip(char *buf, unsigned int len,
assert(buf);
assert(len > 0);
assert(data);
- assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
+ assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2 || opt == IPSET_OPT_BITMASK);
D("len: %u", len);
family = ipset_data_family(data);
@@ -397,6 +397,51 @@ ipset_print_number(char *buf, unsigned int len,
}
/**
+ * ipset_print_hexnumber - print number in hex to string
+ * @buf: printing buffer
+ * @len: length of available buffer space
+ * @data: data blob
+ * @opt: the option kind
+ * @env: environment flags
+ *
+ * Print number in hex to output buffer.
+ *
+ * Return lenght of printed string or error size.
+ */
+int
+ipset_print_hexnumber(char *buf, unsigned int len,
+ const struct ipset_data *data, enum ipset_opt opt,
+ uint8_t env)
+{
+ size_t maxsize;
+ const void *number;
+ const char *quoted = env & IPSET_ENV_QUOTED ? "\"" : "";
+
+ assert(buf);
+ assert(len > 0);
+ assert(data);
+
+ number = ipset_data_get(data, opt);
+ maxsize = ipset_data_sizeof(opt, AF_INET);
+ D("opt: %u, maxsize %zu", opt, maxsize);
+ if (maxsize == sizeof(uint8_t))
+ return snprintf(buf, len, "%s0x%02"PRIx8"%s",
+ quoted, *(const uint8_t *) number, quoted);
+ else if (maxsize == sizeof(uint16_t))
+ return snprintf(buf, len, "%s0x%04"PRIx16"%s",
+ quoted, *(const uint16_t *) number, quoted);
+ else if (maxsize == sizeof(uint32_t))
+ return snprintf(buf, len, "%s0x%08"PRIx32"%s",
+ quoted, *(const uint32_t *) number, quoted);
+ else if (maxsize == sizeof(uint64_t))
+ return snprintf(buf, len, "%s0x%016"PRIx64"%s",
+ quoted, *(const uint64_t *) number, quoted);
+ else
+ assert(0);
+ return 0;
+}
+
+/**
* ipset_print_name - print setname element string
* @buf: printing buffer
* @len: length of available buffer space
@@ -932,6 +977,7 @@ ipset_print_data(char *buf, unsigned int len,
size = ipset_print_elem(buf, len, data, opt, env);
break;
case IPSET_OPT_IP:
+ case IPSET_OPT_BITMASK:
size = ipset_print_ip(buf, len, data, opt, env);
break;
case IPSET_OPT_PORT:
@@ -940,12 +986,12 @@ ipset_print_data(char *buf, unsigned int len,
case IPSET_OPT_IFACE:
size = ipset_print_iface(buf, len, data, opt, env);
break;
- case IPSET_OPT_GC:
+ case IPSET_OPT_INITVAL:
case IPSET_OPT_HASHSIZE:
case IPSET_OPT_MAXELEM:
case IPSET_OPT_MARKMASK:
case IPSET_OPT_NETMASK:
- case IPSET_OPT_PROBES:
+ case IPSET_OPT_BUCKETSIZE:
case IPSET_OPT_RESIZE:
case IPSET_OPT_TIMEOUT:
case IPSET_OPT_REFERENCES:
diff --git a/lib/session.c b/lib/session.c
index 9e3eae3..f822288 100644
--- a/lib/session.c
+++ b/lib/session.c
@@ -418,9 +418,9 @@ static const struct ipset_attr_policy create_attrs[] = {
.type = MNL_TYPE_U32,
.opt = IPSET_OPT_CADT_FLAGS,
},
- [IPSET_ATTR_GC] = {
+ [IPSET_ATTR_INITVAL] = {
.type = MNL_TYPE_U32,
- .opt = IPSET_OPT_GC,
+ .opt = IPSET_OPT_INITVAL,
},
[IPSET_ATTR_HASHSIZE] = {
.type = MNL_TYPE_U32,
@@ -438,9 +438,9 @@ static const struct ipset_attr_policy create_attrs[] = {
.type = MNL_TYPE_U8,
.opt = IPSET_OPT_NETMASK,
},
- [IPSET_ATTR_PROBES] = {
+ [IPSET_ATTR_BUCKETSIZE] = {
.type = MNL_TYPE_U8,
- .opt = IPSET_OPT_PROBES,
+ .opt = IPSET_OPT_BUCKETSIZE,
},
[IPSET_ATTR_RESIZE] = {
.type = MNL_TYPE_U8,
@@ -462,6 +462,10 @@ static const struct ipset_attr_policy create_attrs[] = {
.type = MNL_TYPE_U32,
.opt = IPSET_OPT_MEMSIZE,
},
+ [IPSET_ATTR_BITMASK] = {
+ .type = MNL_TYPE_NESTED,
+ .opt = IPSET_OPT_BITMASK,
+ },
};
static const struct ipset_attr_policy adt_attrs[] = {
@@ -856,6 +860,7 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
const struct ipset_arg *arg;
size_t offset = 0;
int i, found = 0;
+ static char last_setname[IPSET_MAXNAMELEN] = "";
D("enter");
/* Check and load type, family */
@@ -890,6 +895,13 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
case IPSET_LIST_XML:
safe_snprintf(session, "<member><elem>");
break;
+ case IPSET_LIST_JSON:
+ /* print separator if a member for this set was printed before */
+ if (STREQ(ipset_data_setname(data), last_setname))
+ safe_snprintf(session, ",");
+ strcpy(last_setname, ipset_data_setname(data));
+ safe_snprintf(session, "\n {\n \"elem\" : \"");
+ break;
case IPSET_LIST_PLAIN:
default:
break;
@@ -898,6 +910,8 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
safe_dprintf(session, ipset_print_elem, IPSET_OPT_ELEM);
if (session->mode == IPSET_LIST_XML)
safe_snprintf(session, "</elem>");
+ if (session->mode == IPSET_LIST_JSON)
+ safe_snprintf(session, "\"");
for (i = 0; type->cmd[IPSET_ADD].args[i] != IPSET_ARG_NONE; i++) {
arg = ipset_keyword(type->cmd[IPSET_ADD].args[i]);
@@ -925,6 +939,15 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
safe_dprintf(session, arg->print, arg->opt);
safe_snprintf(session, "</%s>", arg->name[0]);
break;
+ case IPSET_LIST_JSON:
+ if (arg->has_arg == IPSET_NO_ARG) {
+ safe_snprintf(session,
+ ",\n \"%s\" : true", arg->name[0]);
+ break;
+ }
+ safe_snprintf(session, ",\n \"%s\" : ", arg->name[0]);
+ safe_dprintf(session, arg->print, arg->opt);
+ break;
default:
break;
}
@@ -932,6 +955,8 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
if (session->mode == IPSET_LIST_XML)
safe_snprintf(session, "</member>\n");
+ else if (session->mode == IPSET_LIST_JSON)
+ safe_snprintf(session, "\n }");
else
safe_snprintf(session, "\n");
@@ -968,6 +993,7 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
const struct ipset_arg *arg;
uint8_t family;
int i;
+ static bool firstipset = true;
for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_CREATE_MAX; i++)
if (nla[i]) {
@@ -1003,6 +1029,19 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
ipset_data_setname(data),
type->name, type->revision);
break;
+ case IPSET_LIST_JSON:
+ if (!firstipset)
+ safe_snprintf(session, ",\n");
+ firstipset = false;
+ safe_snprintf(session,
+ " \{\n"
+ " \"name\" : \"%s\",\n"
+ " \"type\" : \"%s\",\n"
+ " \"revision\" : %u,\n"
+ " \"header\" : \{\n",
+ ipset_data_setname(data),
+ type->name, type->revision);
+ break;
default:
break;
}
@@ -1038,6 +1077,22 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
safe_dprintf(session, arg->print, arg->opt);
safe_snprintf(session, "</%s>", arg->name[0]);
break;
+ case IPSET_LIST_JSON:
+ if (arg->has_arg == IPSET_NO_ARG) {
+ safe_snprintf(session,
+ " \"%s\" : true,\n", arg->name[0]);
+ break;
+ }
+ if (arg->opt == IPSET_OPT_FAMILY) {
+ safe_snprintf(session, " \"%s\" : \"", arg->name[0]);
+ safe_dprintf(session, arg->print, arg->opt);
+ safe_snprintf(session, "\",\n");
+ break;
+ }
+ safe_snprintf(session, " \"%s\" : ", arg->name[0]);
+ safe_dprintf(session, arg->print, arg->opt);
+ safe_snprintf(session, ",\n");
+ break;
default:
break;
}
@@ -1075,6 +1130,21 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
"</header>\n" :
"</header>\n<members>\n");
break;
+ case IPSET_LIST_JSON:
+ safe_snprintf(session, " \"memsize\" : ");
+ safe_dprintf(session, ipset_print_number, IPSET_OPT_MEMSIZE);
+ safe_snprintf(session, ",\n \"references\" : ");
+ safe_dprintf(session, ipset_print_number, IPSET_OPT_REFERENCES);
+ if (ipset_data_test(data, IPSET_OPT_ELEMENTS)) {
+ safe_snprintf(session, ",\n \"numentries\" : ");
+ safe_dprintf(session, ipset_print_number, IPSET_OPT_ELEMENTS);
+ }
+ safe_snprintf(session, "\n");
+ safe_snprintf(session,
+ session->envopts & IPSET_ENV_LIST_HEADER ?
+ " },\n" :
+ " },\n \"members\" : [");
+ break;
default:
break;
}
@@ -1210,11 +1280,24 @@ print_set_done(struct ipset_session *session, bool callback_done)
if (session->saved_setname[0] != '\0')
safe_snprintf(session, "</members>\n</ipset>\n");
break;
+ case IPSET_LIST_JSON:
+ if (session->envopts & IPSET_ENV_LIST_SETNAME)
+ break;
+ if (session->envopts & IPSET_ENV_LIST_HEADER) {
+ if (session->saved_setname[0] != '\0')
+ safe_snprintf(session, " }");
+ break;
+ }
+ if (session->saved_setname[0] != '\0')
+ safe_snprintf(session, "\n ]\n }");
+ break;
default:
break;
}
if (callback_done && session->mode == IPSET_LIST_XML)
safe_snprintf(session, "</ipsets>\n");
+ if (callback_done && session->mode == IPSET_LIST_JSON)
+ safe_snprintf(session, "\n]\n");
return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_STOP;
}
@@ -1223,6 +1306,7 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
enum ipset_cmd cmd)
{
struct ipset_data *data = session->data;
+ static bool firstipset = true;
if (setjmp(printf_failure)) {
session->saved_setname[0] = '\0';
@@ -1241,7 +1325,13 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
if (session->mode == IPSET_LIST_XML)
safe_snprintf(session, "<ipset name=\"%s\"/>\n",
ipset_data_setname(data));
- else
+ else if (session->mode == IPSET_LIST_JSON) {
+ if (!firstipset)
+ safe_snprintf(session, ",\n");
+ firstipset = false;
+ safe_snprintf(session, " { \"name\" : \"%s\" }",
+ ipset_data_setname(data));
+ } else
safe_snprintf(session, "%s\n",
ipset_data_setname(data));
return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_OK;
@@ -1721,6 +1811,10 @@ rawdata2attr(struct ipset_session *session, struct nlmsghdr *nlh,
if (attr->type == MNL_TYPE_NESTED) {
/* IP addresses */
struct nlattr *nested;
+
+ if (type == IPSET_ATTR_BITMASK)
+ family = ipset_data_family(session->data);
+
int atype = family == NFPROTO_IPV4 ? IPSET_ATTR_IPADDR_IPV4
: IPSET_ATTR_IPADDR_IPV6;
@@ -1982,7 +2076,7 @@ build_msg(struct ipset_session *session, bool aggregate)
break;
case IPSET_CMD_ADD:
case IPSET_CMD_DEL: {
- const struct ipset_type *type;
+ DD(const struct ipset_type *type);
if (!aggregate) {
/* Setname, type not checked/added yet */
@@ -2007,7 +2101,7 @@ build_msg(struct ipset_session *session, bool aggregate)
open_nested(session, nlh, IPSET_ATTR_ADT);
}
}
- type = ipset_data_get(data, IPSET_OPT_TYPE);
+ DD(type = ipset_data_get(data, IPSET_OPT_TYPE));
D("family: %u, type family %u",
ipset_data_family(data), type->family);
if (open_nested(session, nlh, IPSET_ATTR_DATA)) {
@@ -2027,7 +2121,7 @@ build_msg(struct ipset_session *session, bool aggregate)
break;
}
case IPSET_CMD_TEST: {
- const struct ipset_type *type;
+ DD(const struct ipset_type *type);
/* Return codes are not aggregated, so tests cannot be either */
/* Setname, type not checked/added yet */
@@ -2040,7 +2134,7 @@ build_msg(struct ipset_session *session, bool aggregate)
return ipset_err(session,
"Invalid test command: missing settype");
- type = ipset_data_get(data, IPSET_OPT_TYPE);
+ DD(type = ipset_data_get(data, IPSET_OPT_TYPE));
D("family: %u, type family %u",
ipset_data_family(data), type->family);
ADDATTR_SETNAME(session, nlh, data);
@@ -2187,18 +2281,27 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
session->cmd = cmd;
session->lineno = lineno;
- /* Set default output mode */
- if (cmd == IPSET_CMD_LIST) {
- if (session->mode == IPSET_LIST_NONE)
- session->mode = IPSET_LIST_PLAIN;
- } else if (cmd == IPSET_CMD_SAVE) {
+ if (cmd == IPSET_CMD_LIST || cmd == IPSET_CMD_SAVE) {
+ /* Set default output mode */
if (session->mode == IPSET_LIST_NONE)
- session->mode = IPSET_LIST_SAVE;
+ session->mode = cmd == IPSET_CMD_LIST ?
+ IPSET_LIST_PLAIN : IPSET_LIST_SAVE;
+ /* Reset just in case there are multiple modes in a session */
+ ipset_envopt_unset(session, IPSET_ENV_QUOTED);
+ switch (session->mode) {
+ case IPSET_LIST_XML:
+ /* Start the root element in XML mode */
+ safe_snprintf(session, "<ipsets>\n");
+ break;
+ case IPSET_LIST_JSON:
+ /* Start the root element in json mode */
+ ipset_envopt_set(session, IPSET_ENV_QUOTED);
+ safe_snprintf(session, "[\n");
+ break;
+ default:
+ break;
+ }
}
- /* Start the root element in XML mode */
- if ((cmd == IPSET_CMD_LIST || cmd == IPSET_CMD_SAVE) &&
- session->mode == IPSET_LIST_XML)
- safe_snprintf(session, "<ipsets>\n");
D("next: build_msg");
/* Build new message or append buffered commands */
diff --git a/src/Makefile.am b/src/Makefile.am
index 438fcec..95dea07 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,10 +12,16 @@ AM_LDFLAGS = -static
endif
endif
-dist_man_MANS = ipset.8
+dist_man_MANS = ipset.8 ipset-translate.8
sparse-check: $(ipset_SOURCES:.c=.d)
%.d: %.c
$(IPSET_AM_V_CHECK)\
$(SPARSE) -I.. $(SPARSE_FLAGS) $(AM_CFLAGS) $(AM_CPPFLAGS) $< || :
+
+install-exec-hook:
+ ${LN_S} -f "${sbindir}/ipset" "${DESTDIR}${sbindir}/ipset-translate";
+
+uninstall-hook:
+ rm -f ${DESTDIR}${sbindir}/ipset-translate
diff --git a/src/ipset-translate.8 b/src/ipset-translate.8
new file mode 100644
index 0000000..55ce2a9
--- /dev/null
+++ b/src/ipset-translate.8
@@ -0,0 +1,91 @@
+.\"
+.\" (C) Copyright 2021, Pablo Neira Ayuso <pablo@netfilter.org>
+.\"
+.\" %%%LICENSE_START(GPLv2+_DOC_FULL)
+.\" This is free documentation; you can redistribute it and/or
+.\" modify it under the terms of the GNU General Public License as
+.\" published by the Free Software Foundation; either version 2 of
+.\" the License, or (at your option) any later version.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public
+.\" License along with this manual; if not, see
+.\" <http://www.gnu.org/licenses/>.
+.\" %%%LICENSE_END
+.\"
+.TH IPSET-TRANSLATE 8 "May 31, 2021"
+
+.SH NAME
+ipset-translate \(em translation tool to migrate from ipset to nftables
+.SH DESCRIPTION
+This tool allows system administrators to translate a given IP sets file
+to \fBnftables(8)\fP.
+
+The only available command is:
+
+.IP \[bu] 2
+ipset-translate restore < file.ipt
+
+.SH USAGE
+The \fBipset-translate\fP tool reads an IP sets file in the syntax produced by
+\fBipset(8)\fP save. No set modifications occur, this tool is a text converter.
+
+.SH EXAMPLES
+Basic operation examples.
+
+Single command translation, assuming the original file:
+
+.nf
+create test1 hash:ip,port family inet counters timeout 300 hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5c4be5d
+add test1 1.1.1.1,udp:20
+add test1 1.1.1.1,21
+create test2 hash:ip,port family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5c4be5d
+.fi
+
+which results in the following translation:
+
+.nf
+root@machine:~# ipset-translate restore < file.ipt
+add set inet global test1 { type ipv4_addr . inet_proto . inet_service; counter; timeout 300s; size 65536; }
+add element inet global test1 { 1.1.1.1 . udp . 20 }
+add element inet global test1 { 1.1.1.1 . tcp . 21 }
+add set inet global test2 { type ipv4_addr . inet_proto . inet_service; size 65536; }
+.fi
+
+.SH LIMITATIONS
+A few IP sets options may be not supported because they are not yet implemented
+in \fBnftables(8)\fP.
+
+Contrary to \fBnftables(8)\fP, IP sets are not attached to a specific table.
+The translation utility assumes that sets are created in a table whose name
+is \fBglobal\fP and family is \fBinet\fP. You might want to update the
+resulting translation to use a different table name and family for your sets.
+
+To get up-to-date information about this, please head to
+\fBhttps://wiki.nftables.org/\fP.
+
+.SH SEE ALSO
+\fBnft(8)\fP, \fBipset(8)\fP
+
+.SH AUTHORS
+The nftables framework has been written by the Netfilter Project
+(https://www.netfilter.org).
+
+This manual page was written by Pablo Neira Ayuso
+<pablo@netfilter.org>.
+
+This documentation is free/libre under the terms of the GPLv2+.
+
+This tool was funded through the NGI0 PET Fund, a fund established by NLnet with
+financial support from the European Commission's Next Generation Internet
+programme, under the aegis of DG Communications Networks, Content and Technology
+under grant agreement No 825310.
diff --git a/src/ipset.8 b/src/ipset.8
index 7787d79..04febda 100644
--- a/src/ipset.8
+++ b/src/ipset.8
@@ -21,7 +21,7 @@ ipset \(em administration tool for IP sets
.PP
COMMANDS := { \fBcreate\fR | \fBadd\fR | \fBdel\fR | \fBtest\fR | \fBdestroy\fR | \fBlist\fR | \fBsave\fR | \fBrestore\fR | \fBflush\fR | \fBrename\fR | \fBswap\fR | \fBhelp\fR | \fBversion\fR | \fB\-\fR }
.PP
-\fIOPTIONS\fR := { \fB\-exist\fR | \fB\-output\fR { \fBplain\fR | \fBsave\fR | \fBxml\fR } | \fB\-quiet\fR | \fB\-resolve\fR | \fB\-sorted\fR | \fB\-name\fR | \fB\-terse\fR | \fB\-file\fR \fIfilename\fR }
+\fIOPTIONS\fR := { \fB\-exist\fR | \fB\-output\fR { \fBplain\fR | \fBsave\fR | \fBxml\fR } | \fBjson\fR } | \fB\-quiet\fR | \fB\-resolve\fR | \fB\-sorted\fR | \fB\-name\fR | \fB\-terse\fR | \fB\-file\fR \fIfilename\fR }
.PP
\fBipset\fR \fBcreate\fR \fISETNAME\fR \fITYPENAME\fR [ \fICREATE\-OPTIONS\fR ]
.PP
@@ -118,7 +118,7 @@ option is given, the entries are listed/saved sorted (which may be slow).
The option
\fB\-output\fR
can be used to control the format of the listing:
-\fBplain\fR, \fBsave\fR or \fBxml\fR.
+\fBplain\fR, \fBsave\fR, \fBxml\fR or \fBjson\fR.
(The default is
\fBplain\fR.)
If the option
@@ -187,7 +187,7 @@ cannot be abbreviated.
Ignore errors when exactly the same set is to be created or already
added entry is added or missing entry is deleted.
.TP
-\fB\-o\fP, \fB\-output\fP { \fBplain\fR | \fBsave\fR | \fBxml\fR }
+\fB\-o\fP, \fB\-output\fP { \fBplain\fR | \fBsave\fR | \fBxml\fR | \fBjson\fR }
Select the output format to the
\fBlist\fR
command.
@@ -333,7 +333,7 @@ are hex without 0x prefix.
.IP
ipset create foo hash:ip skbinfo
.IP
-ipset add foo skbmark 0x1111/0xff00ffff skbprio 1:10 skbqueue 10
+ipset add foo 192.168.0.1 skbmark 0x1111/0xff00ffff skbprio 1:10 skbqueue 10
.PP
.SS hashsize
This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets.
@@ -346,10 +346,20 @@ ipset create test hash:ip hashsize 1536
.PP
.SS maxelem
This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets.
-It does define the maximal number of elements which can be stored in the set, default 65536.
+It defines the maximal number of elements which can be stored in the set, default 65536.
Example:
.IP
-ipset create test hash:ip maxelem 2048.
+ipset create test hash:ip maxelem 2048
+.PP
+.SS bucketsize
+This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets.
+It specifies the maximal number of elements which can be stored in a hash
+bucket. Possible values are any even number between 2-14 and the default is
+14. Setting the value lower forces ipset to create larger hashes which
+consumes more memory but gives more speed at matching in the set.
+Example:
+.IP
+ipset create test hash:ip bucketsize 2
.PP
.SS family { inet | inet6 }
This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets
@@ -514,7 +524,7 @@ The \fBhash:ip\fR set type uses a hash to store IP host addresses (default) or
network addresses. Zero valued IP address cannot be stored in a \fBhash:ip\fR
type of set.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBbitmask\fP \fImask\fP ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fIipaddr\fR
.PP
@@ -539,11 +549,14 @@ ipset create foo hash:ip netmask 30
ipset add foo 192.168.1.0/24
.IP
ipset test foo 192.168.1.2
+.TP
+\fBbitmask\fP \fImask\fP
+This works similar to \fBnetmask\fP but it will accept any valid IPv4/v6 address. It does not have to be a valid netmask.
.SS hash:mac
The \fBhash:mac\fR set type uses a hash to store MAC addresses. Zero valued MAC addresses cannot be stored in a \fBhash:mac\fR
type of set. For matches on destination MAC addresses, see COMMENTS below.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fImacaddr\fR
.PP
@@ -565,7 +578,7 @@ ipset test foo 01:02:03:04:05:06
The \fBhash:ip,mac\fR set type uses a hash to store IP and a MAC address pairs. Zero valued MAC addresses cannot be stored in a \fBhash:ip,mac\fR
type of set. For matches on destination MAC addresses, see COMMENTS below.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fIipaddr\fR,\fImacaddr\fR
.PP
@@ -587,7 +600,7 @@ ipset test foo 1.1.1.1,01:02:03:04:05:06
The \fBhash:net\fR set type uses a hash to store different sized IP network addresses.
Network address with zero prefix size cannot be stored in this type of sets.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fInetaddr\fR
.PP
@@ -638,7 +651,7 @@ over the second, so a nomatch entry could be potentially be ineffective if a mor
first parameter existed with a suitable second parameter.
Network address with zero prefix size cannot be stored in this type of set.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBbitmask\fP \fImask\fP ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fInetaddr\fR,\fInetaddr\fR
.PP
@@ -670,6 +683,18 @@ values added to the first parameter of the set. The number of secondary prefixes
further increases this as the list of secondary prefixes is traversed per primary
prefix.
.PP
+Optional \fBcreate\fR options:
+.TP
+\fBnetmask\fP \fIcidr\fP
+When the optional \fBnetmask\fP parameter specified, network addresses will be
+stored in the set instead of IP host addresses. The \fIcidr\fP prefix value must be
+between 1\-32 for IPv4 and between 1\-128 for IPv6. An IP address will be in the set
+if the network address, which is resulted by masking the address with the netmask,
+can be found in the set.
+.TP
+\fBbitmask\fP \fImask\fP
+This works similar to \fBnetmask\fP but it will accept any valid IPv4/v6 address. It does not have to be a valid netmask.
+.PP
Example:
.IP
ipset create foo hash:net,net
@@ -691,7 +716,7 @@ The \fBhash:ip,port\fR set type uses a hash to store IP address and port number
The port number is interpreted together with a protocol (default TCP) and zero
protocol number cannot be used.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBbitmask\fP \fImask\fP ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR
.PP
@@ -731,6 +756,18 @@ The \fBhash:ip,port\fR type of sets require
two \fBsrc\fR/\fBdst\fR parameters of the \fBset\fR match and \fBSET\fR
target kernel modules.
.PP
+Optional \fBcreate\fR options:
+.TP
+\fBnetmask\fP \fIcidr\fP
+When the optional \fBnetmask\fP parameter specified, network addresses will be
+stored in the set instead of IP host addresses. The \fIcidr\fP prefix value must be
+between 1\-32 for IPv4 and between 1\-128 for IPv6. An IP address will be in the set
+if the network address, which is resulted by masking the address with the netmask,
+can be found in the set.
+.TP
+\fBbitmask\fP \fImask\fP
+This works similar to \fBnetmask\fP but it will accept any valid IPv4/v6 address. It does not have to be a valid netmask.
+.PP
Examples:
.IP
ipset create foo hash:ip,port
@@ -748,7 +785,7 @@ address and port pairs. The port number is interpreted together with a protocol
(default TCP) and zero protocol number cannot be used. Network
address with zero prefix size is not accepted either.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fInetaddr\fR,[\fIproto\fR:]\fIport\fR
.PP
@@ -798,7 +835,7 @@ The \fBhash:ip,port,ip\fR set type uses a hash to store IP address, port number
and a second IP address triples. The port number is interpreted together with a
protocol (default TCP) and zero protocol number cannot be used.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIip\fR
.PP
@@ -830,7 +867,7 @@ and IP network address triples. The port number is interpreted together with a
protocol (default TCP) and zero protocol number cannot be used. Network
address with zero prefix size cannot be stored either.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fInetaddr\fR
.PP
@@ -875,7 +912,7 @@ ipset test foo 192.168.1,80.10.0.0/24
.SS hash:ip,mark
The \fBhash:ip,mark\fR set type uses a hash to store IP address and packet mark pairs.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBmarkmask\fR \fIvalue\fR ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBmarkmask\fR \fIvalue\fR ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fIipaddr\fR,\fImark\fR
.PP
@@ -913,7 +950,7 @@ The \fBhash:net,port,net\fR set type behaves similarly to hash:ip,port,net but a
cidr value for both the first and last parameter. Either subnet is permitted to be a /0
should you wish to match port between all destinations.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fInetaddr\fR,[\fIproto\fR:]\fIport\fR,\fInetaddr\fR
.PP
@@ -960,7 +997,7 @@ ipset test foo 192.168.1.1,80,10.0.0.1
The \fBhash:net,iface\fR set type uses a hash to store different sized IP network
address and interface name pairs.
.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBbucketsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
.PP
\fIADD\-ENTRY\fR := \fInetaddr\fR,[\fBphysdev\fR:]\fIiface\fR
.PP
diff --git a/src/ipset.c b/src/ipset.c
index ee36a06..162f477 100644
--- a/src/ipset.c
+++ b/src/ipset.c
@@ -6,12 +6,15 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#define _GNU_SOURCE
#include <assert.h> /* assert */
#include <stdio.h> /* fprintf */
#include <stdlib.h> /* exit */
+#include <string.h> /* strcmp */
#include <config.h>
#include <libipset/ipset.h> /* ipset library */
+#include <libipset/xlate.h> /* translate to nftables */
int
main(int argc, char *argv[])
@@ -29,7 +32,11 @@ main(int argc, char *argv[])
exit(1);
}
- ret = ipset_parse_argv(ipset, argc, argv);
+ if (!strcmp(basename(argv[0]), "ipset-translate")) {
+ ret = ipset_xlate_argv(ipset, argc, argv);
+ } else {
+ ret = ipset_parse_argv(ipset, argc, argv);
+ }
ipset_fini(ipset);
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..2c4d939 100755
--- a/tests/cidr.sh
+++ b/tests/cidr.sh
@@ -37,6 +37,30 @@ NETS="0.0.0.0/1
ipset="../src/ipset"
+if which netmask >/dev/null 2>&1; then
+ net_first_addr() {
+ netmask -r $1 | cut -d - -f 1
+ }
+ net_last_addr() {
+ netmask -r $1 | cut -d - -f 2 | cut -d ' ' -f 1
+ }
+elif which ipcalc >/dev/null 2>&1; then
+ net_first_addr() {
+ ipcalc $1 | awk '/^Address:/{print $2}'
+ }
+ net_last_addr() {
+ # Netmask tool prints broadcast address as last one, so
+ # prefer that instead of HostMax. Also fix for /31 and /32
+ # being recognized as special by ipcalc.
+ ipcalc $1 | awk '/^(Hostroute|HostMax):/{out=$2}
+ /^Broadcast:/{out=$2}
+ END{print out}'
+ }
+else
+ echo "need either netmask or ipcalc tools"
+ exit 1
+fi
+
case "$1" in
net)
$ipset n test hash:net
@@ -46,9 +70,9 @@ net)
done <<<"$NETS"
while IFS= read x; do
- first=`netmask -r $x | cut -d - -f 1`
+ first=`net_first_addr $x`
$ipset test test $first >/dev/null 2>&1
- last=`netmask -r $x | cut -d - -f 2 | cut -d ' ' -f 1`
+ last=`net_last_addr $x`
$ipset test test $last >/dev/null 2>&1
done <<<"$NETS"
@@ -67,9 +91,9 @@ net,port)
n=1
while IFS= read x; do
- first=`netmask -r $x | cut -d - -f 1`
+ first=`net_first_addr $x`
$ipset test test $first,$n >/dev/null 2>&1
- last=`netmask -r $x | cut -d - -f 2 | cut -d ' ' -f 1`
+ last=`net_last_addr $x`
$ipset test test $last,$n >/dev/null 2>&1
n=$((n+1))
done <<<"$NETS"
diff --git a/tests/comment.t b/tests/comment.t
index b12609b..8f57919 100644
--- a/tests/comment.t
+++ b/tests/comment.t
@@ -9,9 +9,9 @@
# Bitmap comment: Test element with comment
0 ipset test test 2.0.0.1
# Bitmap comment: List set
-0 ipset list test | grep -v Revision: > .foo
+0 ipset list test > .foo
# Bitmap comment: Check listing
-0 diff -u -I 'Size in memory.*' .foo comment.t.list0
+0 ./diff.sh .foo comment.t.list0
# Bitmap comment: Delete element with comment
0 ipset del test 2.0.0.1
# Bitmap comment: Test deleted element
@@ -31,9 +31,9 @@
# Bitmap comment: Add multiple elements with comment
0 for x in `seq 1 255`; do echo "add test 2.0.0.$x comment \\\"text message $x\\\""; done | ipset restore
# Bitmap comment: List set
-0 ipset list test | grep -v Revision: > .foo
+0 ipset list test > .foo
# Bitmap comment: Check listing
-0 diff -u -I 'Size in memory.*' .foo comment.t.list1
+0 ./diff.sh .foo comment.t.list1
# Bitmap comment: Delete test set
0 ipset destroy test
# Bitmap comment: create set with timeout
@@ -43,15 +43,15 @@
# Bitmap comment: Add multiple elements with zero timeout
0 for x in `seq 1 255`; do echo "add test 2.0.1.$x timeout 0 comment \\\"text message $x\\\""; done | ipset restore
# Bitmap comment: List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo
+0 ipset list test > .foo
# Bitmap comment: Check listing
-0 diff -u -I 'Size in memory.*' .foo comment.t.list11
+0 ./diff.sh .foo comment.t.list11
# Sleep 5s so that entries can time out
0 sleep 5s
# Bitmap comment: List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo
+0 ipset list test > .foo
# Bitmap comment: Check listing
-0 diff -u -I 'Size in memory.*' -I 'Number of entries' .foo comment.t.list12
+0 ./diff.sh .foo comment.t.list12
# Bitmap comment: Flush set
0 ipset flush test
# Bitmap comment: Delete test set
@@ -87,9 +87,9 @@
# Hash comment: Try to add IP address
0 ipset add test 2.0.0.1,2.0.0.2
# Hash comment: List set
-0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Hash comment: Check listing
-0 diff -u -I 'Size in memory.*' .foo comment.t.list2
+0 ./diff.sh .foo comment.t.list2
# Hash comment: Update element with comment
0 ipset -! add test 2.0.0.1,2.0.0.2 comment "text 2.0.0.1,2.0.0.2"
# Hash comment: Check updated element
@@ -113,7 +113,7 @@
# Hash comment: Stress test with comments and timeout
0 ./netnetgen.sh comment timeout | ipset restore
# Hash comment: List set and check the number of elements
-0 n=`ipset -L test|grep '^10.'|wc -l` && test $n -eq 87040
+0 n=`ipset save test|grep 'add test 10.'|wc -l` && test $n -eq 87040
# Hash comment: Destroy test set
0 ipset destroy test
# Hash comment: create set with timeout
@@ -123,15 +123,15 @@
# Hash comment: Add multiple elements with zero timeout
0 for x in `seq 0 255`; do echo "add test 2.0.1.$x timeout 0 comment \\\"text message $x\\\""; done | ipset restore
# Hash comment: List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Hash comment: Check listing
-0 diff -u -I 'Size in memory.*' .foo comment.t.list21
+0 ./diff.sh .foo comment.t.list21
# Sleep 5s so that entries can time out
0 sleep 5s
# Hash comment: List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Hash comment: Check listing
-0 diff -u -I 'Size in memory.*' .foo comment.t.list22
+0 ./diff.sh .foo comment.t.list22
# Hash comment: Flush set
0 ipset flush test
# Hash comment: Delete test set
@@ -147,9 +147,9 @@
# List comment: Add b set with comment
0 ipset a test b after a comment "b set comment"
# List comment: List sets
-0 ipset list | grep -v Revision: > .foo
+0 ipset list > .foo
# List comment: Check listing
-0 diff -u -I 'Size in memory.*' .foo comment.t.list3
+0 ./diff.sh .foo comment.t.list3
# Flush sets
0 ipset f
# Destroy sets
diff --git a/tests/comment.t.list11 b/tests/comment.t.list11
index 7d6990f..498ba5f 100644
--- a/tests/comment.t.list11
+++ b/tests/comment.t.list11
@@ -1,517 +1,518 @@
Name: test
Type: bitmap:ip
-Header: range 2.0.0.1-2.1.0.0 timeout x comment
-Size in memory: 1056928
+Revision: 3
+Header: range 2.0.0.1-2.1.0.0 timeout 3 comment
+Size in memory: 1073510
References: 0
Number of entries: 510
Members:
-2.0.0.1 timeout x comment "text message 1"
-2.0.0.2 timeout x comment "text message 2"
-2.0.0.3 timeout x comment "text message 3"
-2.0.0.4 timeout x comment "text message 4"
-2.0.0.5 timeout x comment "text message 5"
-2.0.0.6 timeout x comment "text message 6"
-2.0.0.7 timeout x comment "text message 7"
-2.0.0.8 timeout x comment "text message 8"
-2.0.0.9 timeout x comment "text message 9"
-2.0.0.10 timeout x comment "text message 10"
-2.0.0.11 timeout x comment "text message 11"
-2.0.0.12 timeout x comment "text message 12"
-2.0.0.13 timeout x comment "text message 13"
-2.0.0.14 timeout x comment "text message 14"
-2.0.0.15 timeout x comment "text message 15"
-2.0.0.16 timeout x comment "text message 16"
-2.0.0.17 timeout x comment "text message 17"
-2.0.0.18 timeout x comment "text message 18"
-2.0.0.19 timeout x comment "text message 19"
-2.0.0.20 timeout x comment "text message 20"
-2.0.0.21 timeout x comment "text message 21"
-2.0.0.22 timeout x comment "text message 22"
-2.0.0.23 timeout x comment "text message 23"
-2.0.0.24 timeout x comment "text message 24"
-2.0.0.25 timeout x comment "text message 25"
-2.0.0.26 timeout x comment "text message 26"
-2.0.0.27 timeout x comment "text message 27"
-2.0.0.28 timeout x comment "text message 28"
-2.0.0.29 timeout x comment "text message 29"
-2.0.0.30 timeout x comment "text message 30"
-2.0.0.31 timeout x comment "text message 31"
-2.0.0.32 timeout x comment "text message 32"
-2.0.0.33 timeout x comment "text message 33"
-2.0.0.34 timeout x comment "text message 34"
-2.0.0.35 timeout x comment "text message 35"
-2.0.0.36 timeout x comment "text message 36"
-2.0.0.37 timeout x comment "text message 37"
-2.0.0.38 timeout x comment "text message 38"
-2.0.0.39 timeout x comment "text message 39"
-2.0.0.40 timeout x comment "text message 40"
-2.0.0.41 timeout x comment "text message 41"
-2.0.0.42 timeout x comment "text message 42"
-2.0.0.43 timeout x comment "text message 43"
-2.0.0.44 timeout x comment "text message 44"
-2.0.0.45 timeout x comment "text message 45"
-2.0.0.46 timeout x comment "text message 46"
-2.0.0.47 timeout x comment "text message 47"
-2.0.0.48 timeout x comment "text message 48"
-2.0.0.49 timeout x comment "text message 49"
-2.0.0.50 timeout x comment "text message 50"
-2.0.0.51 timeout x comment "text message 51"
-2.0.0.52 timeout x comment "text message 52"
-2.0.0.53 timeout x comment "text message 53"
-2.0.0.54 timeout x comment "text message 54"
-2.0.0.55 timeout x comment "text message 55"
-2.0.0.56 timeout x comment "text message 56"
-2.0.0.57 timeout x comment "text message 57"
-2.0.0.58 timeout x comment "text message 58"
-2.0.0.59 timeout x comment "text message 59"
-2.0.0.60 timeout x comment "text message 60"
-2.0.0.61 timeout x comment "text message 61"
-2.0.0.62 timeout x comment "text message 62"
-2.0.0.63 timeout x comment "text message 63"
-2.0.0.64 timeout x comment "text message 64"
-2.0.0.65 timeout x comment "text message 65"
-2.0.0.66 timeout x comment "text message 66"
-2.0.0.67 timeout x comment "text message 67"
-2.0.0.68 timeout x comment "text message 68"
-2.0.0.69 timeout x comment "text message 69"
-2.0.0.70 timeout x comment "text message 70"
-2.0.0.71 timeout x comment "text message 71"
-2.0.0.72 timeout x comment "text message 72"
-2.0.0.73 timeout x comment "text message 73"
-2.0.0.74 timeout x comment "text message 74"
-2.0.0.75 timeout x comment "text message 75"
-2.0.0.76 timeout x comment "text message 76"
-2.0.0.77 timeout x comment "text message 77"
-2.0.0.78 timeout x comment "text message 78"
-2.0.0.79 timeout x comment "text message 79"
-2.0.0.80 timeout x comment "text message 80"
-2.0.0.81 timeout x comment "text message 81"
-2.0.0.82 timeout x comment "text message 82"
-2.0.0.83 timeout x comment "text message 83"
-2.0.0.84 timeout x comment "text message 84"
-2.0.0.85 timeout x comment "text message 85"
-2.0.0.86 timeout x comment "text message 86"
-2.0.0.87 timeout x comment "text message 87"
-2.0.0.88 timeout x comment "text message 88"
-2.0.0.89 timeout x comment "text message 89"
-2.0.0.90 timeout x comment "text message 90"
-2.0.0.91 timeout x comment "text message 91"
-2.0.0.92 timeout x comment "text message 92"
-2.0.0.93 timeout x comment "text message 93"
-2.0.0.94 timeout x comment "text message 94"
-2.0.0.95 timeout x comment "text message 95"
-2.0.0.96 timeout x comment "text message 96"
-2.0.0.97 timeout x comment "text message 97"
-2.0.0.98 timeout x comment "text message 98"
-2.0.0.99 timeout x comment "text message 99"
-2.0.0.100 timeout x comment "text message 100"
-2.0.0.101 timeout x comment "text message 101"
-2.0.0.102 timeout x comment "text message 102"
-2.0.0.103 timeout x comment "text message 103"
-2.0.0.104 timeout x comment "text message 104"
-2.0.0.105 timeout x comment "text message 105"
-2.0.0.106 timeout x comment "text message 106"
-2.0.0.107 timeout x comment "text message 107"
-2.0.0.108 timeout x comment "text message 108"
-2.0.0.109 timeout x comment "text message 109"
-2.0.0.110 timeout x comment "text message 110"
-2.0.0.111 timeout x comment "text message 111"
-2.0.0.112 timeout x comment "text message 112"
-2.0.0.113 timeout x comment "text message 113"
-2.0.0.114 timeout x comment "text message 114"
-2.0.0.115 timeout x comment "text message 115"
-2.0.0.116 timeout x comment "text message 116"
-2.0.0.117 timeout x comment "text message 117"
-2.0.0.118 timeout x comment "text message 118"
-2.0.0.119 timeout x comment "text message 119"
-2.0.0.120 timeout x comment "text message 120"
-2.0.0.121 timeout x comment "text message 121"
-2.0.0.122 timeout x comment "text message 122"
-2.0.0.123 timeout x comment "text message 123"
-2.0.0.124 timeout x comment "text message 124"
-2.0.0.125 timeout x comment "text message 125"
-2.0.0.126 timeout x comment "text message 126"
-2.0.0.127 timeout x comment "text message 127"
-2.0.0.128 timeout x comment "text message 128"
-2.0.0.129 timeout x comment "text message 129"
-2.0.0.130 timeout x comment "text message 130"
-2.0.0.131 timeout x comment "text message 131"
-2.0.0.132 timeout x comment "text message 132"
-2.0.0.133 timeout x comment "text message 133"
-2.0.0.134 timeout x comment "text message 134"
-2.0.0.135 timeout x comment "text message 135"
-2.0.0.136 timeout x comment "text message 136"
-2.0.0.137 timeout x comment "text message 137"
-2.0.0.138 timeout x comment "text message 138"
-2.0.0.139 timeout x comment "text message 139"
-2.0.0.140 timeout x comment "text message 140"
-2.0.0.141 timeout x comment "text message 141"
-2.0.0.142 timeout x comment "text message 142"
-2.0.0.143 timeout x comment "text message 143"
-2.0.0.144 timeout x comment "text message 144"
-2.0.0.145 timeout x comment "text message 145"
-2.0.0.146 timeout x comment "text message 146"
-2.0.0.147 timeout x comment "text message 147"
-2.0.0.148 timeout x comment "text message 148"
-2.0.0.149 timeout x comment "text message 149"
-2.0.0.150 timeout x comment "text message 150"
-2.0.0.151 timeout x comment "text message 151"
-2.0.0.152 timeout x comment "text message 152"
-2.0.0.153 timeout x comment "text message 153"
-2.0.0.154 timeout x comment "text message 154"
-2.0.0.155 timeout x comment "text message 155"
-2.0.0.156 timeout x comment "text message 156"
-2.0.0.157 timeout x comment "text message 157"
-2.0.0.158 timeout x comment "text message 158"
-2.0.0.159 timeout x comment "text message 159"
-2.0.0.160 timeout x comment "text message 160"
-2.0.0.161 timeout x comment "text message 161"
-2.0.0.162 timeout x comment "text message 162"
-2.0.0.163 timeout x comment "text message 163"
-2.0.0.164 timeout x comment "text message 164"
-2.0.0.165 timeout x comment "text message 165"
-2.0.0.166 timeout x comment "text message 166"
-2.0.0.167 timeout x comment "text message 167"
-2.0.0.168 timeout x comment "text message 168"
-2.0.0.169 timeout x comment "text message 169"
-2.0.0.170 timeout x comment "text message 170"
-2.0.0.171 timeout x comment "text message 171"
-2.0.0.172 timeout x comment "text message 172"
-2.0.0.173 timeout x comment "text message 173"
-2.0.0.174 timeout x comment "text message 174"
-2.0.0.175 timeout x comment "text message 175"
-2.0.0.176 timeout x comment "text message 176"
-2.0.0.177 timeout x comment "text message 177"
-2.0.0.178 timeout x comment "text message 178"
-2.0.0.179 timeout x comment "text message 179"
-2.0.0.180 timeout x comment "text message 180"
-2.0.0.181 timeout x comment "text message 181"
-2.0.0.182 timeout x comment "text message 182"
-2.0.0.183 timeout x comment "text message 183"
-2.0.0.184 timeout x comment "text message 184"
-2.0.0.185 timeout x comment "text message 185"
-2.0.0.186 timeout x comment "text message 186"
-2.0.0.187 timeout x comment "text message 187"
-2.0.0.188 timeout x comment "text message 188"
-2.0.0.189 timeout x comment "text message 189"
-2.0.0.190 timeout x comment "text message 190"
-2.0.0.191 timeout x comment "text message 191"
-2.0.0.192 timeout x comment "text message 192"
-2.0.0.193 timeout x comment "text message 193"
-2.0.0.194 timeout x comment "text message 194"
-2.0.0.195 timeout x comment "text message 195"
-2.0.0.196 timeout x comment "text message 196"
-2.0.0.197 timeout x comment "text message 197"
-2.0.0.198 timeout x comment "text message 198"
-2.0.0.199 timeout x comment "text message 199"
-2.0.0.200 timeout x comment "text message 200"
-2.0.0.201 timeout x comment "text message 201"
-2.0.0.202 timeout x comment "text message 202"
-2.0.0.203 timeout x comment "text message 203"
-2.0.0.204 timeout x comment "text message 204"
-2.0.0.205 timeout x comment "text message 205"
-2.0.0.206 timeout x comment "text message 206"
-2.0.0.207 timeout x comment "text message 207"
-2.0.0.208 timeout x comment "text message 208"
-2.0.0.209 timeout x comment "text message 209"
-2.0.0.210 timeout x comment "text message 210"
-2.0.0.211 timeout x comment "text message 211"
-2.0.0.212 timeout x comment "text message 212"
-2.0.0.213 timeout x comment "text message 213"
-2.0.0.214 timeout x comment "text message 214"
-2.0.0.215 timeout x comment "text message 215"
-2.0.0.216 timeout x comment "text message 216"
-2.0.0.217 timeout x comment "text message 217"
-2.0.0.218 timeout x comment "text message 218"
-2.0.0.219 timeout x comment "text message 219"
-2.0.0.220 timeout x comment "text message 220"
-2.0.0.221 timeout x comment "text message 221"
-2.0.0.222 timeout x comment "text message 222"
-2.0.0.223 timeout x comment "text message 223"
-2.0.0.224 timeout x comment "text message 224"
-2.0.0.225 timeout x comment "text message 225"
-2.0.0.226 timeout x comment "text message 226"
-2.0.0.227 timeout x comment "text message 227"
-2.0.0.228 timeout x comment "text message 228"
-2.0.0.229 timeout x comment "text message 229"
-2.0.0.230 timeout x comment "text message 230"
-2.0.0.231 timeout x comment "text message 231"
-2.0.0.232 timeout x comment "text message 232"
-2.0.0.233 timeout x comment "text message 233"
-2.0.0.234 timeout x comment "text message 234"
-2.0.0.235 timeout x comment "text message 235"
-2.0.0.236 timeout x comment "text message 236"
-2.0.0.237 timeout x comment "text message 237"
-2.0.0.238 timeout x comment "text message 238"
-2.0.0.239 timeout x comment "text message 239"
-2.0.0.240 timeout x comment "text message 240"
-2.0.0.241 timeout x comment "text message 241"
-2.0.0.242 timeout x comment "text message 242"
-2.0.0.243 timeout x comment "text message 243"
-2.0.0.244 timeout x comment "text message 244"
-2.0.0.245 timeout x comment "text message 245"
-2.0.0.246 timeout x comment "text message 246"
-2.0.0.247 timeout x comment "text message 247"
-2.0.0.248 timeout x comment "text message 248"
-2.0.0.249 timeout x comment "text message 249"
-2.0.0.250 timeout x comment "text message 250"
-2.0.0.251 timeout x comment "text message 251"
-2.0.0.252 timeout x comment "text message 252"
-2.0.0.253 timeout x comment "text message 253"
-2.0.0.254 timeout x comment "text message 254"
-2.0.0.255 timeout x comment "text message 255"
-2.0.1.1 timeout x comment "text message 1"
-2.0.1.2 timeout x comment "text message 2"
-2.0.1.3 timeout x comment "text message 3"
-2.0.1.4 timeout x comment "text message 4"
-2.0.1.5 timeout x comment "text message 5"
-2.0.1.6 timeout x comment "text message 6"
-2.0.1.7 timeout x comment "text message 7"
-2.0.1.8 timeout x comment "text message 8"
-2.0.1.9 timeout x comment "text message 9"
-2.0.1.10 timeout x comment "text message 10"
-2.0.1.11 timeout x comment "text message 11"
-2.0.1.12 timeout x comment "text message 12"
-2.0.1.13 timeout x comment "text message 13"
-2.0.1.14 timeout x comment "text message 14"
-2.0.1.15 timeout x comment "text message 15"
-2.0.1.16 timeout x comment "text message 16"
-2.0.1.17 timeout x comment "text message 17"
-2.0.1.18 timeout x comment "text message 18"
-2.0.1.19 timeout x comment "text message 19"
-2.0.1.20 timeout x comment "text message 20"
-2.0.1.21 timeout x comment "text message 21"
-2.0.1.22 timeout x comment "text message 22"
-2.0.1.23 timeout x comment "text message 23"
-2.0.1.24 timeout x comment "text message 24"
-2.0.1.25 timeout x comment "text message 25"
-2.0.1.26 timeout x comment "text message 26"
-2.0.1.27 timeout x comment "text message 27"
-2.0.1.28 timeout x comment "text message 28"
-2.0.1.29 timeout x comment "text message 29"
-2.0.1.30 timeout x comment "text message 30"
-2.0.1.31 timeout x comment "text message 31"
-2.0.1.32 timeout x comment "text message 32"
-2.0.1.33 timeout x comment "text message 33"
-2.0.1.34 timeout x comment "text message 34"
-2.0.1.35 timeout x comment "text message 35"
-2.0.1.36 timeout x comment "text message 36"
-2.0.1.37 timeout x comment "text message 37"
-2.0.1.38 timeout x comment "text message 38"
-2.0.1.39 timeout x comment "text message 39"
-2.0.1.40 timeout x comment "text message 40"
-2.0.1.41 timeout x comment "text message 41"
-2.0.1.42 timeout x comment "text message 42"
-2.0.1.43 timeout x comment "text message 43"
-2.0.1.44 timeout x comment "text message 44"
-2.0.1.45 timeout x comment "text message 45"
-2.0.1.46 timeout x comment "text message 46"
-2.0.1.47 timeout x comment "text message 47"
-2.0.1.48 timeout x comment "text message 48"
-2.0.1.49 timeout x comment "text message 49"
-2.0.1.50 timeout x comment "text message 50"
-2.0.1.51 timeout x comment "text message 51"
-2.0.1.52 timeout x comment "text message 52"
-2.0.1.53 timeout x comment "text message 53"
-2.0.1.54 timeout x comment "text message 54"
-2.0.1.55 timeout x comment "text message 55"
-2.0.1.56 timeout x comment "text message 56"
-2.0.1.57 timeout x comment "text message 57"
-2.0.1.58 timeout x comment "text message 58"
-2.0.1.59 timeout x comment "text message 59"
-2.0.1.60 timeout x comment "text message 60"
-2.0.1.61 timeout x comment "text message 61"
-2.0.1.62 timeout x comment "text message 62"
-2.0.1.63 timeout x comment "text message 63"
-2.0.1.64 timeout x comment "text message 64"
-2.0.1.65 timeout x comment "text message 65"
-2.0.1.66 timeout x comment "text message 66"
-2.0.1.67 timeout x comment "text message 67"
-2.0.1.68 timeout x comment "text message 68"
-2.0.1.69 timeout x comment "text message 69"
-2.0.1.70 timeout x comment "text message 70"
-2.0.1.71 timeout x comment "text message 71"
-2.0.1.72 timeout x comment "text message 72"
-2.0.1.73 timeout x comment "text message 73"
-2.0.1.74 timeout x comment "text message 74"
-2.0.1.75 timeout x comment "text message 75"
-2.0.1.76 timeout x comment "text message 76"
-2.0.1.77 timeout x comment "text message 77"
-2.0.1.78 timeout x comment "text message 78"
-2.0.1.79 timeout x comment "text message 79"
-2.0.1.80 timeout x comment "text message 80"
-2.0.1.81 timeout x comment "text message 81"
-2.0.1.82 timeout x comment "text message 82"
-2.0.1.83 timeout x comment "text message 83"
-2.0.1.84 timeout x comment "text message 84"
-2.0.1.85 timeout x comment "text message 85"
-2.0.1.86 timeout x comment "text message 86"
-2.0.1.87 timeout x comment "text message 87"
-2.0.1.88 timeout x comment "text message 88"
-2.0.1.89 timeout x comment "text message 89"
-2.0.1.90 timeout x comment "text message 90"
-2.0.1.91 timeout x comment "text message 91"
-2.0.1.92 timeout x comment "text message 92"
-2.0.1.93 timeout x comment "text message 93"
-2.0.1.94 timeout x comment "text message 94"
-2.0.1.95 timeout x comment "text message 95"
-2.0.1.96 timeout x comment "text message 96"
-2.0.1.97 timeout x comment "text message 97"
-2.0.1.98 timeout x comment "text message 98"
-2.0.1.99 timeout x comment "text message 99"
-2.0.1.100 timeout x comment "text message 100"
-2.0.1.101 timeout x comment "text message 101"
-2.0.1.102 timeout x comment "text message 102"
-2.0.1.103 timeout x comment "text message 103"
-2.0.1.104 timeout x comment "text message 104"
-2.0.1.105 timeout x comment "text message 105"
-2.0.1.106 timeout x comment "text message 106"
-2.0.1.107 timeout x comment "text message 107"
-2.0.1.108 timeout x comment "text message 108"
-2.0.1.109 timeout x comment "text message 109"
-2.0.1.110 timeout x comment "text message 110"
-2.0.1.111 timeout x comment "text message 111"
-2.0.1.112 timeout x comment "text message 112"
-2.0.1.113 timeout x comment "text message 113"
-2.0.1.114 timeout x comment "text message 114"
-2.0.1.115 timeout x comment "text message 115"
-2.0.1.116 timeout x comment "text message 116"
-2.0.1.117 timeout x comment "text message 117"
-2.0.1.118 timeout x comment "text message 118"
-2.0.1.119 timeout x comment "text message 119"
-2.0.1.120 timeout x comment "text message 120"
-2.0.1.121 timeout x comment "text message 121"
-2.0.1.122 timeout x comment "text message 122"
-2.0.1.123 timeout x comment "text message 123"
-2.0.1.124 timeout x comment "text message 124"
-2.0.1.125 timeout x comment "text message 125"
-2.0.1.126 timeout x comment "text message 126"
-2.0.1.127 timeout x comment "text message 127"
-2.0.1.128 timeout x comment "text message 128"
-2.0.1.129 timeout x comment "text message 129"
-2.0.1.130 timeout x comment "text message 130"
-2.0.1.131 timeout x comment "text message 131"
-2.0.1.132 timeout x comment "text message 132"
-2.0.1.133 timeout x comment "text message 133"
-2.0.1.134 timeout x comment "text message 134"
-2.0.1.135 timeout x comment "text message 135"
-2.0.1.136 timeout x comment "text message 136"
-2.0.1.137 timeout x comment "text message 137"
-2.0.1.138 timeout x comment "text message 138"
-2.0.1.139 timeout x comment "text message 139"
-2.0.1.140 timeout x comment "text message 140"
-2.0.1.141 timeout x comment "text message 141"
-2.0.1.142 timeout x comment "text message 142"
-2.0.1.143 timeout x comment "text message 143"
-2.0.1.144 timeout x comment "text message 144"
-2.0.1.145 timeout x comment "text message 145"
-2.0.1.146 timeout x comment "text message 146"
-2.0.1.147 timeout x comment "text message 147"
-2.0.1.148 timeout x comment "text message 148"
-2.0.1.149 timeout x comment "text message 149"
-2.0.1.150 timeout x comment "text message 150"
-2.0.1.151 timeout x comment "text message 151"
-2.0.1.152 timeout x comment "text message 152"
-2.0.1.153 timeout x comment "text message 153"
-2.0.1.154 timeout x comment "text message 154"
-2.0.1.155 timeout x comment "text message 155"
-2.0.1.156 timeout x comment "text message 156"
-2.0.1.157 timeout x comment "text message 157"
-2.0.1.158 timeout x comment "text message 158"
-2.0.1.159 timeout x comment "text message 159"
-2.0.1.160 timeout x comment "text message 160"
-2.0.1.161 timeout x comment "text message 161"
-2.0.1.162 timeout x comment "text message 162"
-2.0.1.163 timeout x comment "text message 163"
-2.0.1.164 timeout x comment "text message 164"
-2.0.1.165 timeout x comment "text message 165"
-2.0.1.166 timeout x comment "text message 166"
-2.0.1.167 timeout x comment "text message 167"
-2.0.1.168 timeout x comment "text message 168"
-2.0.1.169 timeout x comment "text message 169"
-2.0.1.170 timeout x comment "text message 170"
-2.0.1.171 timeout x comment "text message 171"
-2.0.1.172 timeout x comment "text message 172"
-2.0.1.173 timeout x comment "text message 173"
-2.0.1.174 timeout x comment "text message 174"
-2.0.1.175 timeout x comment "text message 175"
-2.0.1.176 timeout x comment "text message 176"
-2.0.1.177 timeout x comment "text message 177"
-2.0.1.178 timeout x comment "text message 178"
-2.0.1.179 timeout x comment "text message 179"
-2.0.1.180 timeout x comment "text message 180"
-2.0.1.181 timeout x comment "text message 181"
-2.0.1.182 timeout x comment "text message 182"
-2.0.1.183 timeout x comment "text message 183"
-2.0.1.184 timeout x comment "text message 184"
-2.0.1.185 timeout x comment "text message 185"
-2.0.1.186 timeout x comment "text message 186"
-2.0.1.187 timeout x comment "text message 187"
-2.0.1.188 timeout x comment "text message 188"
-2.0.1.189 timeout x comment "text message 189"
-2.0.1.190 timeout x comment "text message 190"
-2.0.1.191 timeout x comment "text message 191"
-2.0.1.192 timeout x comment "text message 192"
-2.0.1.193 timeout x comment "text message 193"
-2.0.1.194 timeout x comment "text message 194"
-2.0.1.195 timeout x comment "text message 195"
-2.0.1.196 timeout x comment "text message 196"
-2.0.1.197 timeout x comment "text message 197"
-2.0.1.198 timeout x comment "text message 198"
-2.0.1.199 timeout x comment "text message 199"
-2.0.1.200 timeout x comment "text message 200"
-2.0.1.201 timeout x comment "text message 201"
-2.0.1.202 timeout x comment "text message 202"
-2.0.1.203 timeout x comment "text message 203"
-2.0.1.204 timeout x comment "text message 204"
-2.0.1.205 timeout x comment "text message 205"
-2.0.1.206 timeout x comment "text message 206"
-2.0.1.207 timeout x comment "text message 207"
-2.0.1.208 timeout x comment "text message 208"
-2.0.1.209 timeout x comment "text message 209"
-2.0.1.210 timeout x comment "text message 210"
-2.0.1.211 timeout x comment "text message 211"
-2.0.1.212 timeout x comment "text message 212"
-2.0.1.213 timeout x comment "text message 213"
-2.0.1.214 timeout x comment "text message 214"
-2.0.1.215 timeout x comment "text message 215"
-2.0.1.216 timeout x comment "text message 216"
-2.0.1.217 timeout x comment "text message 217"
-2.0.1.218 timeout x comment "text message 218"
-2.0.1.219 timeout x comment "text message 219"
-2.0.1.220 timeout x comment "text message 220"
-2.0.1.221 timeout x comment "text message 221"
-2.0.1.222 timeout x comment "text message 222"
-2.0.1.223 timeout x comment "text message 223"
-2.0.1.224 timeout x comment "text message 224"
-2.0.1.225 timeout x comment "text message 225"
-2.0.1.226 timeout x comment "text message 226"
-2.0.1.227 timeout x comment "text message 227"
-2.0.1.228 timeout x comment "text message 228"
-2.0.1.229 timeout x comment "text message 229"
-2.0.1.230 timeout x comment "text message 230"
-2.0.1.231 timeout x comment "text message 231"
-2.0.1.232 timeout x comment "text message 232"
-2.0.1.233 timeout x comment "text message 233"
-2.0.1.234 timeout x comment "text message 234"
-2.0.1.235 timeout x comment "text message 235"
-2.0.1.236 timeout x comment "text message 236"
-2.0.1.237 timeout x comment "text message 237"
-2.0.1.238 timeout x comment "text message 238"
-2.0.1.239 timeout x comment "text message 239"
-2.0.1.240 timeout x comment "text message 240"
-2.0.1.241 timeout x comment "text message 241"
-2.0.1.242 timeout x comment "text message 242"
-2.0.1.243 timeout x comment "text message 243"
-2.0.1.244 timeout x comment "text message 244"
-2.0.1.245 timeout x comment "text message 245"
-2.0.1.246 timeout x comment "text message 246"
-2.0.1.247 timeout x comment "text message 247"
-2.0.1.248 timeout x comment "text message 248"
-2.0.1.249 timeout x comment "text message 249"
-2.0.1.250 timeout x comment "text message 250"
-2.0.1.251 timeout x comment "text message 251"
-2.0.1.252 timeout x comment "text message 252"
-2.0.1.253 timeout x comment "text message 253"
-2.0.1.254 timeout x comment "text message 254"
-2.0.1.255 timeout x comment "text message 255"
+2.0.0.1 timeout 2 comment "text message 1"
+2.0.0.2 timeout 2 comment "text message 2"
+2.0.0.3 timeout 2 comment "text message 3"
+2.0.0.4 timeout 2 comment "text message 4"
+2.0.0.5 timeout 2 comment "text message 5"
+2.0.0.6 timeout 2 comment "text message 6"
+2.0.0.7 timeout 2 comment "text message 7"
+2.0.0.8 timeout 2 comment "text message 8"
+2.0.0.9 timeout 2 comment "text message 9"
+2.0.0.10 timeout 2 comment "text message 10"
+2.0.0.11 timeout 2 comment "text message 11"
+2.0.0.12 timeout 2 comment "text message 12"
+2.0.0.13 timeout 2 comment "text message 13"
+2.0.0.14 timeout 2 comment "text message 14"
+2.0.0.15 timeout 2 comment "text message 15"
+2.0.0.16 timeout 2 comment "text message 16"
+2.0.0.17 timeout 2 comment "text message 17"
+2.0.0.18 timeout 2 comment "text message 18"
+2.0.0.19 timeout 2 comment "text message 19"
+2.0.0.20 timeout 2 comment "text message 20"
+2.0.0.21 timeout 2 comment "text message 21"
+2.0.0.22 timeout 2 comment "text message 22"
+2.0.0.23 timeout 2 comment "text message 23"
+2.0.0.24 timeout 2 comment "text message 24"
+2.0.0.25 timeout 2 comment "text message 25"
+2.0.0.26 timeout 2 comment "text message 26"
+2.0.0.27 timeout 2 comment "text message 27"
+2.0.0.28 timeout 2 comment "text message 28"
+2.0.0.29 timeout 2 comment "text message 29"
+2.0.0.30 timeout 2 comment "text message 30"
+2.0.0.31 timeout 2 comment "text message 31"
+2.0.0.32 timeout 2 comment "text message 32"
+2.0.0.33 timeout 2 comment "text message 33"
+2.0.0.34 timeout 2 comment "text message 34"
+2.0.0.35 timeout 2 comment "text message 35"
+2.0.0.36 timeout 2 comment "text message 36"
+2.0.0.37 timeout 2 comment "text message 37"
+2.0.0.38 timeout 2 comment "text message 38"
+2.0.0.39 timeout 2 comment "text message 39"
+2.0.0.40 timeout 2 comment "text message 40"
+2.0.0.41 timeout 2 comment "text message 41"
+2.0.0.42 timeout 2 comment "text message 42"
+2.0.0.43 timeout 2 comment "text message 43"
+2.0.0.44 timeout 2 comment "text message 44"
+2.0.0.45 timeout 2 comment "text message 45"
+2.0.0.46 timeout 2 comment "text message 46"
+2.0.0.47 timeout 2 comment "text message 47"
+2.0.0.48 timeout 2 comment "text message 48"
+2.0.0.49 timeout 2 comment "text message 49"
+2.0.0.50 timeout 2 comment "text message 50"
+2.0.0.51 timeout 2 comment "text message 51"
+2.0.0.52 timeout 2 comment "text message 52"
+2.0.0.53 timeout 2 comment "text message 53"
+2.0.0.54 timeout 2 comment "text message 54"
+2.0.0.55 timeout 2 comment "text message 55"
+2.0.0.56 timeout 2 comment "text message 56"
+2.0.0.57 timeout 2 comment "text message 57"
+2.0.0.58 timeout 2 comment "text message 58"
+2.0.0.59 timeout 2 comment "text message 59"
+2.0.0.60 timeout 2 comment "text message 60"
+2.0.0.61 timeout 2 comment "text message 61"
+2.0.0.62 timeout 2 comment "text message 62"
+2.0.0.63 timeout 2 comment "text message 63"
+2.0.0.64 timeout 2 comment "text message 64"
+2.0.0.65 timeout 2 comment "text message 65"
+2.0.0.66 timeout 2 comment "text message 66"
+2.0.0.67 timeout 2 comment "text message 67"
+2.0.0.68 timeout 2 comment "text message 68"
+2.0.0.69 timeout 2 comment "text message 69"
+2.0.0.70 timeout 2 comment "text message 70"
+2.0.0.71 timeout 2 comment "text message 71"
+2.0.0.72 timeout 2 comment "text message 72"
+2.0.0.73 timeout 2 comment "text message 73"
+2.0.0.74 timeout 2 comment "text message 74"
+2.0.0.75 timeout 2 comment "text message 75"
+2.0.0.76 timeout 2 comment "text message 76"
+2.0.0.77 timeout 2 comment "text message 77"
+2.0.0.78 timeout 2 comment "text message 78"
+2.0.0.79 timeout 2 comment "text message 79"
+2.0.0.80 timeout 2 comment "text message 80"
+2.0.0.81 timeout 2 comment "text message 81"
+2.0.0.82 timeout 2 comment "text message 82"
+2.0.0.83 timeout 2 comment "text message 83"
+2.0.0.84 timeout 2 comment "text message 84"
+2.0.0.85 timeout 2 comment "text message 85"
+2.0.0.86 timeout 2 comment "text message 86"
+2.0.0.87 timeout 2 comment "text message 87"
+2.0.0.88 timeout 2 comment "text message 88"
+2.0.0.89 timeout 2 comment "text message 89"
+2.0.0.90 timeout 2 comment "text message 90"
+2.0.0.91 timeout 2 comment "text message 91"
+2.0.0.92 timeout 2 comment "text message 92"
+2.0.0.93 timeout 2 comment "text message 93"
+2.0.0.94 timeout 2 comment "text message 94"
+2.0.0.95 timeout 2 comment "text message 95"
+2.0.0.96 timeout 2 comment "text message 96"
+2.0.0.97 timeout 2 comment "text message 97"
+2.0.0.98 timeout 2 comment "text message 98"
+2.0.0.99 timeout 2 comment "text message 99"
+2.0.0.100 timeout 2 comment "text message 100"
+2.0.0.101 timeout 2 comment "text message 101"
+2.0.0.102 timeout 2 comment "text message 102"
+2.0.0.103 timeout 2 comment "text message 103"
+2.0.0.104 timeout 2 comment "text message 104"
+2.0.0.105 timeout 2 comment "text message 105"
+2.0.0.106 timeout 2 comment "text message 106"
+2.0.0.107 timeout 2 comment "text message 107"
+2.0.0.108 timeout 2 comment "text message 108"
+2.0.0.109 timeout 2 comment "text message 109"
+2.0.0.110 timeout 2 comment "text message 110"
+2.0.0.111 timeout 2 comment "text message 111"
+2.0.0.112 timeout 2 comment "text message 112"
+2.0.0.113 timeout 2 comment "text message 113"
+2.0.0.114 timeout 2 comment "text message 114"
+2.0.0.115 timeout 2 comment "text message 115"
+2.0.0.116 timeout 2 comment "text message 116"
+2.0.0.117 timeout 2 comment "text message 117"
+2.0.0.118 timeout 2 comment "text message 118"
+2.0.0.119 timeout 2 comment "text message 119"
+2.0.0.120 timeout 2 comment "text message 120"
+2.0.0.121 timeout 2 comment "text message 121"
+2.0.0.122 timeout 2 comment "text message 122"
+2.0.0.123 timeout 2 comment "text message 123"
+2.0.0.124 timeout 2 comment "text message 124"
+2.0.0.125 timeout 2 comment "text message 125"
+2.0.0.126 timeout 2 comment "text message 126"
+2.0.0.127 timeout 2 comment "text message 127"
+2.0.0.128 timeout 2 comment "text message 128"
+2.0.0.129 timeout 2 comment "text message 129"
+2.0.0.130 timeout 2 comment "text message 130"
+2.0.0.131 timeout 2 comment "text message 131"
+2.0.0.132 timeout 2 comment "text message 132"
+2.0.0.133 timeout 2 comment "text message 133"
+2.0.0.134 timeout 2 comment "text message 134"
+2.0.0.135 timeout 2 comment "text message 135"
+2.0.0.136 timeout 2 comment "text message 136"
+2.0.0.137 timeout 2 comment "text message 137"
+2.0.0.138 timeout 2 comment "text message 138"
+2.0.0.139 timeout 2 comment "text message 139"
+2.0.0.140 timeout 2 comment "text message 140"
+2.0.0.141 timeout 2 comment "text message 141"
+2.0.0.142 timeout 2 comment "text message 142"
+2.0.0.143 timeout 2 comment "text message 143"
+2.0.0.144 timeout 2 comment "text message 144"
+2.0.0.145 timeout 2 comment "text message 145"
+2.0.0.146 timeout 2 comment "text message 146"
+2.0.0.147 timeout 2 comment "text message 147"
+2.0.0.148 timeout 2 comment "text message 148"
+2.0.0.149 timeout 2 comment "text message 149"
+2.0.0.150 timeout 2 comment "text message 150"
+2.0.0.151 timeout 2 comment "text message 151"
+2.0.0.152 timeout 2 comment "text message 152"
+2.0.0.153 timeout 2 comment "text message 153"
+2.0.0.154 timeout 2 comment "text message 154"
+2.0.0.155 timeout 2 comment "text message 155"
+2.0.0.156 timeout 2 comment "text message 156"
+2.0.0.157 timeout 2 comment "text message 157"
+2.0.0.158 timeout 2 comment "text message 158"
+2.0.0.159 timeout 2 comment "text message 159"
+2.0.0.160 timeout 2 comment "text message 160"
+2.0.0.161 timeout 2 comment "text message 161"
+2.0.0.162 timeout 2 comment "text message 162"
+2.0.0.163 timeout 2 comment "text message 163"
+2.0.0.164 timeout 2 comment "text message 164"
+2.0.0.165 timeout 2 comment "text message 165"
+2.0.0.166 timeout 2 comment "text message 166"
+2.0.0.167 timeout 2 comment "text message 167"
+2.0.0.168 timeout 2 comment "text message 168"
+2.0.0.169 timeout 2 comment "text message 169"
+2.0.0.170 timeout 2 comment "text message 170"
+2.0.0.171 timeout 2 comment "text message 171"
+2.0.0.172 timeout 2 comment "text message 172"
+2.0.0.173 timeout 2 comment "text message 173"
+2.0.0.174 timeout 2 comment "text message 174"
+2.0.0.175 timeout 2 comment "text message 175"
+2.0.0.176 timeout 2 comment "text message 176"
+2.0.0.177 timeout 2 comment "text message 177"
+2.0.0.178 timeout 2 comment "text message 178"
+2.0.0.179 timeout 2 comment "text message 179"
+2.0.0.180 timeout 2 comment "text message 180"
+2.0.0.181 timeout 2 comment "text message 181"
+2.0.0.182 timeout 2 comment "text message 182"
+2.0.0.183 timeout 2 comment "text message 183"
+2.0.0.184 timeout 2 comment "text message 184"
+2.0.0.185 timeout 2 comment "text message 185"
+2.0.0.186 timeout 2 comment "text message 186"
+2.0.0.187 timeout 2 comment "text message 187"
+2.0.0.188 timeout 2 comment "text message 188"
+2.0.0.189 timeout 2 comment "text message 189"
+2.0.0.190 timeout 2 comment "text message 190"
+2.0.0.191 timeout 2 comment "text message 191"
+2.0.0.192 timeout 2 comment "text message 192"
+2.0.0.193 timeout 2 comment "text message 193"
+2.0.0.194 timeout 2 comment "text message 194"
+2.0.0.195 timeout 2 comment "text message 195"
+2.0.0.196 timeout 2 comment "text message 196"
+2.0.0.197 timeout 2 comment "text message 197"
+2.0.0.198 timeout 2 comment "text message 198"
+2.0.0.199 timeout 2 comment "text message 199"
+2.0.0.200 timeout 2 comment "text message 200"
+2.0.0.201 timeout 2 comment "text message 201"
+2.0.0.202 timeout 2 comment "text message 202"
+2.0.0.203 timeout 2 comment "text message 203"
+2.0.0.204 timeout 2 comment "text message 204"
+2.0.0.205 timeout 2 comment "text message 205"
+2.0.0.206 timeout 2 comment "text message 206"
+2.0.0.207 timeout 2 comment "text message 207"
+2.0.0.208 timeout 2 comment "text message 208"
+2.0.0.209 timeout 2 comment "text message 209"
+2.0.0.210 timeout 2 comment "text message 210"
+2.0.0.211 timeout 2 comment "text message 211"
+2.0.0.212 timeout 2 comment "text message 212"
+2.0.0.213 timeout 2 comment "text message 213"
+2.0.0.214 timeout 2 comment "text message 214"
+2.0.0.215 timeout 2 comment "text message 215"
+2.0.0.216 timeout 2 comment "text message 216"
+2.0.0.217 timeout 2 comment "text message 217"
+2.0.0.218 timeout 2 comment "text message 218"
+2.0.0.219 timeout 2 comment "text message 219"
+2.0.0.220 timeout 2 comment "text message 220"
+2.0.0.221 timeout 2 comment "text message 221"
+2.0.0.222 timeout 2 comment "text message 222"
+2.0.0.223 timeout 2 comment "text message 223"
+2.0.0.224 timeout 2 comment "text message 224"
+2.0.0.225 timeout 2 comment "text message 225"
+2.0.0.226 timeout 2 comment "text message 226"
+2.0.0.227 timeout 2 comment "text message 227"
+2.0.0.228 timeout 2 comment "text message 228"
+2.0.0.229 timeout 2 comment "text message 229"
+2.0.0.230 timeout 2 comment "text message 230"
+2.0.0.231 timeout 2 comment "text message 231"
+2.0.0.232 timeout 2 comment "text message 232"
+2.0.0.233 timeout 2 comment "text message 233"
+2.0.0.234 timeout 2 comment "text message 234"
+2.0.0.235 timeout 2 comment "text message 235"
+2.0.0.236 timeout 2 comment "text message 236"
+2.0.0.237 timeout 2 comment "text message 237"
+2.0.0.238 timeout 2 comment "text message 238"
+2.0.0.239 timeout 2 comment "text message 239"
+2.0.0.240 timeout 2 comment "text message 240"
+2.0.0.241 timeout 2 comment "text message 241"
+2.0.0.242 timeout 2 comment "text message 242"
+2.0.0.243 timeout 2 comment "text message 243"
+2.0.0.244 timeout 2 comment "text message 244"
+2.0.0.245 timeout 2 comment "text message 245"
+2.0.0.246 timeout 2 comment "text message 246"
+2.0.0.247 timeout 2 comment "text message 247"
+2.0.0.248 timeout 2 comment "text message 248"
+2.0.0.249 timeout 2 comment "text message 249"
+2.0.0.250 timeout 2 comment "text message 250"
+2.0.0.251 timeout 2 comment "text message 251"
+2.0.0.252 timeout 2 comment "text message 252"
+2.0.0.253 timeout 2 comment "text message 253"
+2.0.0.254 timeout 2 comment "text message 254"
+2.0.0.255 timeout 2 comment "text message 255"
+2.0.1.1 timeout 0 comment "text message 1"
+2.0.1.2 timeout 0 comment "text message 2"
+2.0.1.3 timeout 0 comment "text message 3"
+2.0.1.4 timeout 0 comment "text message 4"
+2.0.1.5 timeout 0 comment "text message 5"
+2.0.1.6 timeout 0 comment "text message 6"
+2.0.1.7 timeout 0 comment "text message 7"
+2.0.1.8 timeout 0 comment "text message 8"
+2.0.1.9 timeout 0 comment "text message 9"
+2.0.1.10 timeout 0 comment "text message 10"
+2.0.1.11 timeout 0 comment "text message 11"
+2.0.1.12 timeout 0 comment "text message 12"
+2.0.1.13 timeout 0 comment "text message 13"
+2.0.1.14 timeout 0 comment "text message 14"
+2.0.1.15 timeout 0 comment "text message 15"
+2.0.1.16 timeout 0 comment "text message 16"
+2.0.1.17 timeout 0 comment "text message 17"
+2.0.1.18 timeout 0 comment "text message 18"
+2.0.1.19 timeout 0 comment "text message 19"
+2.0.1.20 timeout 0 comment "text message 20"
+2.0.1.21 timeout 0 comment "text message 21"
+2.0.1.22 timeout 0 comment "text message 22"
+2.0.1.23 timeout 0 comment "text message 23"
+2.0.1.24 timeout 0 comment "text message 24"
+2.0.1.25 timeout 0 comment "text message 25"
+2.0.1.26 timeout 0 comment "text message 26"
+2.0.1.27 timeout 0 comment "text message 27"
+2.0.1.28 timeout 0 comment "text message 28"
+2.0.1.29 timeout 0 comment "text message 29"
+2.0.1.30 timeout 0 comment "text message 30"
+2.0.1.31 timeout 0 comment "text message 31"
+2.0.1.32 timeout 0 comment "text message 32"
+2.0.1.33 timeout 0 comment "text message 33"
+2.0.1.34 timeout 0 comment "text message 34"
+2.0.1.35 timeout 0 comment "text message 35"
+2.0.1.36 timeout 0 comment "text message 36"
+2.0.1.37 timeout 0 comment "text message 37"
+2.0.1.38 timeout 0 comment "text message 38"
+2.0.1.39 timeout 0 comment "text message 39"
+2.0.1.40 timeout 0 comment "text message 40"
+2.0.1.41 timeout 0 comment "text message 41"
+2.0.1.42 timeout 0 comment "text message 42"
+2.0.1.43 timeout 0 comment "text message 43"
+2.0.1.44 timeout 0 comment "text message 44"
+2.0.1.45 timeout 0 comment "text message 45"
+2.0.1.46 timeout 0 comment "text message 46"
+2.0.1.47 timeout 0 comment "text message 47"
+2.0.1.48 timeout 0 comment "text message 48"
+2.0.1.49 timeout 0 comment "text message 49"
+2.0.1.50 timeout 0 comment "text message 50"
+2.0.1.51 timeout 0 comment "text message 51"
+2.0.1.52 timeout 0 comment "text message 52"
+2.0.1.53 timeout 0 comment "text message 53"
+2.0.1.54 timeout 0 comment "text message 54"
+2.0.1.55 timeout 0 comment "text message 55"
+2.0.1.56 timeout 0 comment "text message 56"
+2.0.1.57 timeout 0 comment "text message 57"
+2.0.1.58 timeout 0 comment "text message 58"
+2.0.1.59 timeout 0 comment "text message 59"
+2.0.1.60 timeout 0 comment "text message 60"
+2.0.1.61 timeout 0 comment "text message 61"
+2.0.1.62 timeout 0 comment "text message 62"
+2.0.1.63 timeout 0 comment "text message 63"
+2.0.1.64 timeout 0 comment "text message 64"
+2.0.1.65 timeout 0 comment "text message 65"
+2.0.1.66 timeout 0 comment "text message 66"
+2.0.1.67 timeout 0 comment "text message 67"
+2.0.1.68 timeout 0 comment "text message 68"
+2.0.1.69 timeout 0 comment "text message 69"
+2.0.1.70 timeout 0 comment "text message 70"
+2.0.1.71 timeout 0 comment "text message 71"
+2.0.1.72 timeout 0 comment "text message 72"
+2.0.1.73 timeout 0 comment "text message 73"
+2.0.1.74 timeout 0 comment "text message 74"
+2.0.1.75 timeout 0 comment "text message 75"
+2.0.1.76 timeout 0 comment "text message 76"
+2.0.1.77 timeout 0 comment "text message 77"
+2.0.1.78 timeout 0 comment "text message 78"
+2.0.1.79 timeout 0 comment "text message 79"
+2.0.1.80 timeout 0 comment "text message 80"
+2.0.1.81 timeout 0 comment "text message 81"
+2.0.1.82 timeout 0 comment "text message 82"
+2.0.1.83 timeout 0 comment "text message 83"
+2.0.1.84 timeout 0 comment "text message 84"
+2.0.1.85 timeout 0 comment "text message 85"
+2.0.1.86 timeout 0 comment "text message 86"
+2.0.1.87 timeout 0 comment "text message 87"
+2.0.1.88 timeout 0 comment "text message 88"
+2.0.1.89 timeout 0 comment "text message 89"
+2.0.1.90 timeout 0 comment "text message 90"
+2.0.1.91 timeout 0 comment "text message 91"
+2.0.1.92 timeout 0 comment "text message 92"
+2.0.1.93 timeout 0 comment "text message 93"
+2.0.1.94 timeout 0 comment "text message 94"
+2.0.1.95 timeout 0 comment "text message 95"
+2.0.1.96 timeout 0 comment "text message 96"
+2.0.1.97 timeout 0 comment "text message 97"
+2.0.1.98 timeout 0 comment "text message 98"
+2.0.1.99 timeout 0 comment "text message 99"
+2.0.1.100 timeout 0 comment "text message 100"
+2.0.1.101 timeout 0 comment "text message 101"
+2.0.1.102 timeout 0 comment "text message 102"
+2.0.1.103 timeout 0 comment "text message 103"
+2.0.1.104 timeout 0 comment "text message 104"
+2.0.1.105 timeout 0 comment "text message 105"
+2.0.1.106 timeout 0 comment "text message 106"
+2.0.1.107 timeout 0 comment "text message 107"
+2.0.1.108 timeout 0 comment "text message 108"
+2.0.1.109 timeout 0 comment "text message 109"
+2.0.1.110 timeout 0 comment "text message 110"
+2.0.1.111 timeout 0 comment "text message 111"
+2.0.1.112 timeout 0 comment "text message 112"
+2.0.1.113 timeout 0 comment "text message 113"
+2.0.1.114 timeout 0 comment "text message 114"
+2.0.1.115 timeout 0 comment "text message 115"
+2.0.1.116 timeout 0 comment "text message 116"
+2.0.1.117 timeout 0 comment "text message 117"
+2.0.1.118 timeout 0 comment "text message 118"
+2.0.1.119 timeout 0 comment "text message 119"
+2.0.1.120 timeout 0 comment "text message 120"
+2.0.1.121 timeout 0 comment "text message 121"
+2.0.1.122 timeout 0 comment "text message 122"
+2.0.1.123 timeout 0 comment "text message 123"
+2.0.1.124 timeout 0 comment "text message 124"
+2.0.1.125 timeout 0 comment "text message 125"
+2.0.1.126 timeout 0 comment "text message 126"
+2.0.1.127 timeout 0 comment "text message 127"
+2.0.1.128 timeout 0 comment "text message 128"
+2.0.1.129 timeout 0 comment "text message 129"
+2.0.1.130 timeout 0 comment "text message 130"
+2.0.1.131 timeout 0 comment "text message 131"
+2.0.1.132 timeout 0 comment "text message 132"
+2.0.1.133 timeout 0 comment "text message 133"
+2.0.1.134 timeout 0 comment "text message 134"
+2.0.1.135 timeout 0 comment "text message 135"
+2.0.1.136 timeout 0 comment "text message 136"
+2.0.1.137 timeout 0 comment "text message 137"
+2.0.1.138 timeout 0 comment "text message 138"
+2.0.1.139 timeout 0 comment "text message 139"
+2.0.1.140 timeout 0 comment "text message 140"
+2.0.1.141 timeout 0 comment "text message 141"
+2.0.1.142 timeout 0 comment "text message 142"
+2.0.1.143 timeout 0 comment "text message 143"
+2.0.1.144 timeout 0 comment "text message 144"
+2.0.1.145 timeout 0 comment "text message 145"
+2.0.1.146 timeout 0 comment "text message 146"
+2.0.1.147 timeout 0 comment "text message 147"
+2.0.1.148 timeout 0 comment "text message 148"
+2.0.1.149 timeout 0 comment "text message 149"
+2.0.1.150 timeout 0 comment "text message 150"
+2.0.1.151 timeout 0 comment "text message 151"
+2.0.1.152 timeout 0 comment "text message 152"
+2.0.1.153 timeout 0 comment "text message 153"
+2.0.1.154 timeout 0 comment "text message 154"
+2.0.1.155 timeout 0 comment "text message 155"
+2.0.1.156 timeout 0 comment "text message 156"
+2.0.1.157 timeout 0 comment "text message 157"
+2.0.1.158 timeout 0 comment "text message 158"
+2.0.1.159 timeout 0 comment "text message 159"
+2.0.1.160 timeout 0 comment "text message 160"
+2.0.1.161 timeout 0 comment "text message 161"
+2.0.1.162 timeout 0 comment "text message 162"
+2.0.1.163 timeout 0 comment "text message 163"
+2.0.1.164 timeout 0 comment "text message 164"
+2.0.1.165 timeout 0 comment "text message 165"
+2.0.1.166 timeout 0 comment "text message 166"
+2.0.1.167 timeout 0 comment "text message 167"
+2.0.1.168 timeout 0 comment "text message 168"
+2.0.1.169 timeout 0 comment "text message 169"
+2.0.1.170 timeout 0 comment "text message 170"
+2.0.1.171 timeout 0 comment "text message 171"
+2.0.1.172 timeout 0 comment "text message 172"
+2.0.1.173 timeout 0 comment "text message 173"
+2.0.1.174 timeout 0 comment "text message 174"
+2.0.1.175 timeout 0 comment "text message 175"
+2.0.1.176 timeout 0 comment "text message 176"
+2.0.1.177 timeout 0 comment "text message 177"
+2.0.1.178 timeout 0 comment "text message 178"
+2.0.1.179 timeout 0 comment "text message 179"
+2.0.1.180 timeout 0 comment "text message 180"
+2.0.1.181 timeout 0 comment "text message 181"
+2.0.1.182 timeout 0 comment "text message 182"
+2.0.1.183 timeout 0 comment "text message 183"
+2.0.1.184 timeout 0 comment "text message 184"
+2.0.1.185 timeout 0 comment "text message 185"
+2.0.1.186 timeout 0 comment "text message 186"
+2.0.1.187 timeout 0 comment "text message 187"
+2.0.1.188 timeout 0 comment "text message 188"
+2.0.1.189 timeout 0 comment "text message 189"
+2.0.1.190 timeout 0 comment "text message 190"
+2.0.1.191 timeout 0 comment "text message 191"
+2.0.1.192 timeout 0 comment "text message 192"
+2.0.1.193 timeout 0 comment "text message 193"
+2.0.1.194 timeout 0 comment "text message 194"
+2.0.1.195 timeout 0 comment "text message 195"
+2.0.1.196 timeout 0 comment "text message 196"
+2.0.1.197 timeout 0 comment "text message 197"
+2.0.1.198 timeout 0 comment "text message 198"
+2.0.1.199 timeout 0 comment "text message 199"
+2.0.1.200 timeout 0 comment "text message 200"
+2.0.1.201 timeout 0 comment "text message 201"
+2.0.1.202 timeout 0 comment "text message 202"
+2.0.1.203 timeout 0 comment "text message 203"
+2.0.1.204 timeout 0 comment "text message 204"
+2.0.1.205 timeout 0 comment "text message 205"
+2.0.1.206 timeout 0 comment "text message 206"
+2.0.1.207 timeout 0 comment "text message 207"
+2.0.1.208 timeout 0 comment "text message 208"
+2.0.1.209 timeout 0 comment "text message 209"
+2.0.1.210 timeout 0 comment "text message 210"
+2.0.1.211 timeout 0 comment "text message 211"
+2.0.1.212 timeout 0 comment "text message 212"
+2.0.1.213 timeout 0 comment "text message 213"
+2.0.1.214 timeout 0 comment "text message 214"
+2.0.1.215 timeout 0 comment "text message 215"
+2.0.1.216 timeout 0 comment "text message 216"
+2.0.1.217 timeout 0 comment "text message 217"
+2.0.1.218 timeout 0 comment "text message 218"
+2.0.1.219 timeout 0 comment "text message 219"
+2.0.1.220 timeout 0 comment "text message 220"
+2.0.1.221 timeout 0 comment "text message 221"
+2.0.1.222 timeout 0 comment "text message 222"
+2.0.1.223 timeout 0 comment "text message 223"
+2.0.1.224 timeout 0 comment "text message 224"
+2.0.1.225 timeout 0 comment "text message 225"
+2.0.1.226 timeout 0 comment "text message 226"
+2.0.1.227 timeout 0 comment "text message 227"
+2.0.1.228 timeout 0 comment "text message 228"
+2.0.1.229 timeout 0 comment "text message 229"
+2.0.1.230 timeout 0 comment "text message 230"
+2.0.1.231 timeout 0 comment "text message 231"
+2.0.1.232 timeout 0 comment "text message 232"
+2.0.1.233 timeout 0 comment "text message 233"
+2.0.1.234 timeout 0 comment "text message 234"
+2.0.1.235 timeout 0 comment "text message 235"
+2.0.1.236 timeout 0 comment "text message 236"
+2.0.1.237 timeout 0 comment "text message 237"
+2.0.1.238 timeout 0 comment "text message 238"
+2.0.1.239 timeout 0 comment "text message 239"
+2.0.1.240 timeout 0 comment "text message 240"
+2.0.1.241 timeout 0 comment "text message 241"
+2.0.1.242 timeout 0 comment "text message 242"
+2.0.1.243 timeout 0 comment "text message 243"
+2.0.1.244 timeout 0 comment "text message 244"
+2.0.1.245 timeout 0 comment "text message 245"
+2.0.1.246 timeout 0 comment "text message 246"
+2.0.1.247 timeout 0 comment "text message 247"
+2.0.1.248 timeout 0 comment "text message 248"
+2.0.1.249 timeout 0 comment "text message 249"
+2.0.1.250 timeout 0 comment "text message 250"
+2.0.1.251 timeout 0 comment "text message 251"
+2.0.1.252 timeout 0 comment "text message 252"
+2.0.1.253 timeout 0 comment "text message 253"
+2.0.1.254 timeout 0 comment "text message 254"
+2.0.1.255 timeout 0 comment "text message 255"
diff --git a/tests/comment.t.list12 b/tests/comment.t.list12
index 9440b75..202c841 100644
--- a/tests/comment.t.list12
+++ b/tests/comment.t.list12
@@ -1,262 +1,263 @@
Name: test
Type: bitmap:ip
-Header: range 2.0.0.1-2.1.0.0 timeout x comment
-Size in memory: 1056928
+Revision: 3
+Header: range 2.0.0.1-2.1.0.0 timeout 3 comment
+Size in memory: 1065203
References: 0
-Number of entries: 510
+Number of entries: 255
Members:
-2.0.1.1 timeout x comment "text message 1"
-2.0.1.2 timeout x comment "text message 2"
-2.0.1.3 timeout x comment "text message 3"
-2.0.1.4 timeout x comment "text message 4"
-2.0.1.5 timeout x comment "text message 5"
-2.0.1.6 timeout x comment "text message 6"
-2.0.1.7 timeout x comment "text message 7"
-2.0.1.8 timeout x comment "text message 8"
-2.0.1.9 timeout x comment "text message 9"
-2.0.1.10 timeout x comment "text message 10"
-2.0.1.11 timeout x comment "text message 11"
-2.0.1.12 timeout x comment "text message 12"
-2.0.1.13 timeout x comment "text message 13"
-2.0.1.14 timeout x comment "text message 14"
-2.0.1.15 timeout x comment "text message 15"
-2.0.1.16 timeout x comment "text message 16"
-2.0.1.17 timeout x comment "text message 17"
-2.0.1.18 timeout x comment "text message 18"
-2.0.1.19 timeout x comment "text message 19"
-2.0.1.20 timeout x comment "text message 20"
-2.0.1.21 timeout x comment "text message 21"
-2.0.1.22 timeout x comment "text message 22"
-2.0.1.23 timeout x comment "text message 23"
-2.0.1.24 timeout x comment "text message 24"
-2.0.1.25 timeout x comment "text message 25"
-2.0.1.26 timeout x comment "text message 26"
-2.0.1.27 timeout x comment "text message 27"
-2.0.1.28 timeout x comment "text message 28"
-2.0.1.29 timeout x comment "text message 29"
-2.0.1.30 timeout x comment "text message 30"
-2.0.1.31 timeout x comment "text message 31"
-2.0.1.32 timeout x comment "text message 32"
-2.0.1.33 timeout x comment "text message 33"
-2.0.1.34 timeout x comment "text message 34"
-2.0.1.35 timeout x comment "text message 35"
-2.0.1.36 timeout x comment "text message 36"
-2.0.1.37 timeout x comment "text message 37"
-2.0.1.38 timeout x comment "text message 38"
-2.0.1.39 timeout x comment "text message 39"
-2.0.1.40 timeout x comment "text message 40"
-2.0.1.41 timeout x comment "text message 41"
-2.0.1.42 timeout x comment "text message 42"
-2.0.1.43 timeout x comment "text message 43"
-2.0.1.44 timeout x comment "text message 44"
-2.0.1.45 timeout x comment "text message 45"
-2.0.1.46 timeout x comment "text message 46"
-2.0.1.47 timeout x comment "text message 47"
-2.0.1.48 timeout x comment "text message 48"
-2.0.1.49 timeout x comment "text message 49"
-2.0.1.50 timeout x comment "text message 50"
-2.0.1.51 timeout x comment "text message 51"
-2.0.1.52 timeout x comment "text message 52"
-2.0.1.53 timeout x comment "text message 53"
-2.0.1.54 timeout x comment "text message 54"
-2.0.1.55 timeout x comment "text message 55"
-2.0.1.56 timeout x comment "text message 56"
-2.0.1.57 timeout x comment "text message 57"
-2.0.1.58 timeout x comment "text message 58"
-2.0.1.59 timeout x comment "text message 59"
-2.0.1.60 timeout x comment "text message 60"
-2.0.1.61 timeout x comment "text message 61"
-2.0.1.62 timeout x comment "text message 62"
-2.0.1.63 timeout x comment "text message 63"
-2.0.1.64 timeout x comment "text message 64"
-2.0.1.65 timeout x comment "text message 65"
-2.0.1.66 timeout x comment "text message 66"
-2.0.1.67 timeout x comment "text message 67"
-2.0.1.68 timeout x comment "text message 68"
-2.0.1.69 timeout x comment "text message 69"
-2.0.1.70 timeout x comment "text message 70"
-2.0.1.71 timeout x comment "text message 71"
-2.0.1.72 timeout x comment "text message 72"
-2.0.1.73 timeout x comment "text message 73"
-2.0.1.74 timeout x comment "text message 74"
-2.0.1.75 timeout x comment "text message 75"
-2.0.1.76 timeout x comment "text message 76"
-2.0.1.77 timeout x comment "text message 77"
-2.0.1.78 timeout x comment "text message 78"
-2.0.1.79 timeout x comment "text message 79"
-2.0.1.80 timeout x comment "text message 80"
-2.0.1.81 timeout x comment "text message 81"
-2.0.1.82 timeout x comment "text message 82"
-2.0.1.83 timeout x comment "text message 83"
-2.0.1.84 timeout x comment "text message 84"
-2.0.1.85 timeout x comment "text message 85"
-2.0.1.86 timeout x comment "text message 86"
-2.0.1.87 timeout x comment "text message 87"
-2.0.1.88 timeout x comment "text message 88"
-2.0.1.89 timeout x comment "text message 89"
-2.0.1.90 timeout x comment "text message 90"
-2.0.1.91 timeout x comment "text message 91"
-2.0.1.92 timeout x comment "text message 92"
-2.0.1.93 timeout x comment "text message 93"
-2.0.1.94 timeout x comment "text message 94"
-2.0.1.95 timeout x comment "text message 95"
-2.0.1.96 timeout x comment "text message 96"
-2.0.1.97 timeout x comment "text message 97"
-2.0.1.98 timeout x comment "text message 98"
-2.0.1.99 timeout x comment "text message 99"
-2.0.1.100 timeout x comment "text message 100"
-2.0.1.101 timeout x comment "text message 101"
-2.0.1.102 timeout x comment "text message 102"
-2.0.1.103 timeout x comment "text message 103"
-2.0.1.104 timeout x comment "text message 104"
-2.0.1.105 timeout x comment "text message 105"
-2.0.1.106 timeout x comment "text message 106"
-2.0.1.107 timeout x comment "text message 107"
-2.0.1.108 timeout x comment "text message 108"
-2.0.1.109 timeout x comment "text message 109"
-2.0.1.110 timeout x comment "text message 110"
-2.0.1.111 timeout x comment "text message 111"
-2.0.1.112 timeout x comment "text message 112"
-2.0.1.113 timeout x comment "text message 113"
-2.0.1.114 timeout x comment "text message 114"
-2.0.1.115 timeout x comment "text message 115"
-2.0.1.116 timeout x comment "text message 116"
-2.0.1.117 timeout x comment "text message 117"
-2.0.1.118 timeout x comment "text message 118"
-2.0.1.119 timeout x comment "text message 119"
-2.0.1.120 timeout x comment "text message 120"
-2.0.1.121 timeout x comment "text message 121"
-2.0.1.122 timeout x comment "text message 122"
-2.0.1.123 timeout x comment "text message 123"
-2.0.1.124 timeout x comment "text message 124"
-2.0.1.125 timeout x comment "text message 125"
-2.0.1.126 timeout x comment "text message 126"
-2.0.1.127 timeout x comment "text message 127"
-2.0.1.128 timeout x comment "text message 128"
-2.0.1.129 timeout x comment "text message 129"
-2.0.1.130 timeout x comment "text message 130"
-2.0.1.131 timeout x comment "text message 131"
-2.0.1.132 timeout x comment "text message 132"
-2.0.1.133 timeout x comment "text message 133"
-2.0.1.134 timeout x comment "text message 134"
-2.0.1.135 timeout x comment "text message 135"
-2.0.1.136 timeout x comment "text message 136"
-2.0.1.137 timeout x comment "text message 137"
-2.0.1.138 timeout x comment "text message 138"
-2.0.1.139 timeout x comment "text message 139"
-2.0.1.140 timeout x comment "text message 140"
-2.0.1.141 timeout x comment "text message 141"
-2.0.1.142 timeout x comment "text message 142"
-2.0.1.143 timeout x comment "text message 143"
-2.0.1.144 timeout x comment "text message 144"
-2.0.1.145 timeout x comment "text message 145"
-2.0.1.146 timeout x comment "text message 146"
-2.0.1.147 timeout x comment "text message 147"
-2.0.1.148 timeout x comment "text message 148"
-2.0.1.149 timeout x comment "text message 149"
-2.0.1.150 timeout x comment "text message 150"
-2.0.1.151 timeout x comment "text message 151"
-2.0.1.152 timeout x comment "text message 152"
-2.0.1.153 timeout x comment "text message 153"
-2.0.1.154 timeout x comment "text message 154"
-2.0.1.155 timeout x comment "text message 155"
-2.0.1.156 timeout x comment "text message 156"
-2.0.1.157 timeout x comment "text message 157"
-2.0.1.158 timeout x comment "text message 158"
-2.0.1.159 timeout x comment "text message 159"
-2.0.1.160 timeout x comment "text message 160"
-2.0.1.161 timeout x comment "text message 161"
-2.0.1.162 timeout x comment "text message 162"
-2.0.1.163 timeout x comment "text message 163"
-2.0.1.164 timeout x comment "text message 164"
-2.0.1.165 timeout x comment "text message 165"
-2.0.1.166 timeout x comment "text message 166"
-2.0.1.167 timeout x comment "text message 167"
-2.0.1.168 timeout x comment "text message 168"
-2.0.1.169 timeout x comment "text message 169"
-2.0.1.170 timeout x comment "text message 170"
-2.0.1.171 timeout x comment "text message 171"
-2.0.1.172 timeout x comment "text message 172"
-2.0.1.173 timeout x comment "text message 173"
-2.0.1.174 timeout x comment "text message 174"
-2.0.1.175 timeout x comment "text message 175"
-2.0.1.176 timeout x comment "text message 176"
-2.0.1.177 timeout x comment "text message 177"
-2.0.1.178 timeout x comment "text message 178"
-2.0.1.179 timeout x comment "text message 179"
-2.0.1.180 timeout x comment "text message 180"
-2.0.1.181 timeout x comment "text message 181"
-2.0.1.182 timeout x comment "text message 182"
-2.0.1.183 timeout x comment "text message 183"
-2.0.1.184 timeout x comment "text message 184"
-2.0.1.185 timeout x comment "text message 185"
-2.0.1.186 timeout x comment "text message 186"
-2.0.1.187 timeout x comment "text message 187"
-2.0.1.188 timeout x comment "text message 188"
-2.0.1.189 timeout x comment "text message 189"
-2.0.1.190 timeout x comment "text message 190"
-2.0.1.191 timeout x comment "text message 191"
-2.0.1.192 timeout x comment "text message 192"
-2.0.1.193 timeout x comment "text message 193"
-2.0.1.194 timeout x comment "text message 194"
-2.0.1.195 timeout x comment "text message 195"
-2.0.1.196 timeout x comment "text message 196"
-2.0.1.197 timeout x comment "text message 197"
-2.0.1.198 timeout x comment "text message 198"
-2.0.1.199 timeout x comment "text message 199"
-2.0.1.200 timeout x comment "text message 200"
-2.0.1.201 timeout x comment "text message 201"
-2.0.1.202 timeout x comment "text message 202"
-2.0.1.203 timeout x comment "text message 203"
-2.0.1.204 timeout x comment "text message 204"
-2.0.1.205 timeout x comment "text message 205"
-2.0.1.206 timeout x comment "text message 206"
-2.0.1.207 timeout x comment "text message 207"
-2.0.1.208 timeout x comment "text message 208"
-2.0.1.209 timeout x comment "text message 209"
-2.0.1.210 timeout x comment "text message 210"
-2.0.1.211 timeout x comment "text message 211"
-2.0.1.212 timeout x comment "text message 212"
-2.0.1.213 timeout x comment "text message 213"
-2.0.1.214 timeout x comment "text message 214"
-2.0.1.215 timeout x comment "text message 215"
-2.0.1.216 timeout x comment "text message 216"
-2.0.1.217 timeout x comment "text message 217"
-2.0.1.218 timeout x comment "text message 218"
-2.0.1.219 timeout x comment "text message 219"
-2.0.1.220 timeout x comment "text message 220"
-2.0.1.221 timeout x comment "text message 221"
-2.0.1.222 timeout x comment "text message 222"
-2.0.1.223 timeout x comment "text message 223"
-2.0.1.224 timeout x comment "text message 224"
-2.0.1.225 timeout x comment "text message 225"
-2.0.1.226 timeout x comment "text message 226"
-2.0.1.227 timeout x comment "text message 227"
-2.0.1.228 timeout x comment "text message 228"
-2.0.1.229 timeout x comment "text message 229"
-2.0.1.230 timeout x comment "text message 230"
-2.0.1.231 timeout x comment "text message 231"
-2.0.1.232 timeout x comment "text message 232"
-2.0.1.233 timeout x comment "text message 233"
-2.0.1.234 timeout x comment "text message 234"
-2.0.1.235 timeout x comment "text message 235"
-2.0.1.236 timeout x comment "text message 236"
-2.0.1.237 timeout x comment "text message 237"
-2.0.1.238 timeout x comment "text message 238"
-2.0.1.239 timeout x comment "text message 239"
-2.0.1.240 timeout x comment "text message 240"
-2.0.1.241 timeout x comment "text message 241"
-2.0.1.242 timeout x comment "text message 242"
-2.0.1.243 timeout x comment "text message 243"
-2.0.1.244 timeout x comment "text message 244"
-2.0.1.245 timeout x comment "text message 245"
-2.0.1.246 timeout x comment "text message 246"
-2.0.1.247 timeout x comment "text message 247"
-2.0.1.248 timeout x comment "text message 248"
-2.0.1.249 timeout x comment "text message 249"
-2.0.1.250 timeout x comment "text message 250"
-2.0.1.251 timeout x comment "text message 251"
-2.0.1.252 timeout x comment "text message 252"
-2.0.1.253 timeout x comment "text message 253"
-2.0.1.254 timeout x comment "text message 254"
-2.0.1.255 timeout x comment "text message 255"
+2.0.1.1 timeout 0 comment "text message 1"
+2.0.1.2 timeout 0 comment "text message 2"
+2.0.1.3 timeout 0 comment "text message 3"
+2.0.1.4 timeout 0 comment "text message 4"
+2.0.1.5 timeout 0 comment "text message 5"
+2.0.1.6 timeout 0 comment "text message 6"
+2.0.1.7 timeout 0 comment "text message 7"
+2.0.1.8 timeout 0 comment "text message 8"
+2.0.1.9 timeout 0 comment "text message 9"
+2.0.1.10 timeout 0 comment "text message 10"
+2.0.1.11 timeout 0 comment "text message 11"
+2.0.1.12 timeout 0 comment "text message 12"
+2.0.1.13 timeout 0 comment "text message 13"
+2.0.1.14 timeout 0 comment "text message 14"
+2.0.1.15 timeout 0 comment "text message 15"
+2.0.1.16 timeout 0 comment "text message 16"
+2.0.1.17 timeout 0 comment "text message 17"
+2.0.1.18 timeout 0 comment "text message 18"
+2.0.1.19 timeout 0 comment "text message 19"
+2.0.1.20 timeout 0 comment "text message 20"
+2.0.1.21 timeout 0 comment "text message 21"
+2.0.1.22 timeout 0 comment "text message 22"
+2.0.1.23 timeout 0 comment "text message 23"
+2.0.1.24 timeout 0 comment "text message 24"
+2.0.1.25 timeout 0 comment "text message 25"
+2.0.1.26 timeout 0 comment "text message 26"
+2.0.1.27 timeout 0 comment "text message 27"
+2.0.1.28 timeout 0 comment "text message 28"
+2.0.1.29 timeout 0 comment "text message 29"
+2.0.1.30 timeout 0 comment "text message 30"
+2.0.1.31 timeout 0 comment "text message 31"
+2.0.1.32 timeout 0 comment "text message 32"
+2.0.1.33 timeout 0 comment "text message 33"
+2.0.1.34 timeout 0 comment "text message 34"
+2.0.1.35 timeout 0 comment "text message 35"
+2.0.1.36 timeout 0 comment "text message 36"
+2.0.1.37 timeout 0 comment "text message 37"
+2.0.1.38 timeout 0 comment "text message 38"
+2.0.1.39 timeout 0 comment "text message 39"
+2.0.1.40 timeout 0 comment "text message 40"
+2.0.1.41 timeout 0 comment "text message 41"
+2.0.1.42 timeout 0 comment "text message 42"
+2.0.1.43 timeout 0 comment "text message 43"
+2.0.1.44 timeout 0 comment "text message 44"
+2.0.1.45 timeout 0 comment "text message 45"
+2.0.1.46 timeout 0 comment "text message 46"
+2.0.1.47 timeout 0 comment "text message 47"
+2.0.1.48 timeout 0 comment "text message 48"
+2.0.1.49 timeout 0 comment "text message 49"
+2.0.1.50 timeout 0 comment "text message 50"
+2.0.1.51 timeout 0 comment "text message 51"
+2.0.1.52 timeout 0 comment "text message 52"
+2.0.1.53 timeout 0 comment "text message 53"
+2.0.1.54 timeout 0 comment "text message 54"
+2.0.1.55 timeout 0 comment "text message 55"
+2.0.1.56 timeout 0 comment "text message 56"
+2.0.1.57 timeout 0 comment "text message 57"
+2.0.1.58 timeout 0 comment "text message 58"
+2.0.1.59 timeout 0 comment "text message 59"
+2.0.1.60 timeout 0 comment "text message 60"
+2.0.1.61 timeout 0 comment "text message 61"
+2.0.1.62 timeout 0 comment "text message 62"
+2.0.1.63 timeout 0 comment "text message 63"
+2.0.1.64 timeout 0 comment "text message 64"
+2.0.1.65 timeout 0 comment "text message 65"
+2.0.1.66 timeout 0 comment "text message 66"
+2.0.1.67 timeout 0 comment "text message 67"
+2.0.1.68 timeout 0 comment "text message 68"
+2.0.1.69 timeout 0 comment "text message 69"
+2.0.1.70 timeout 0 comment "text message 70"
+2.0.1.71 timeout 0 comment "text message 71"
+2.0.1.72 timeout 0 comment "text message 72"
+2.0.1.73 timeout 0 comment "text message 73"
+2.0.1.74 timeout 0 comment "text message 74"
+2.0.1.75 timeout 0 comment "text message 75"
+2.0.1.76 timeout 0 comment "text message 76"
+2.0.1.77 timeout 0 comment "text message 77"
+2.0.1.78 timeout 0 comment "text message 78"
+2.0.1.79 timeout 0 comment "text message 79"
+2.0.1.80 timeout 0 comment "text message 80"
+2.0.1.81 timeout 0 comment "text message 81"
+2.0.1.82 timeout 0 comment "text message 82"
+2.0.1.83 timeout 0 comment "text message 83"
+2.0.1.84 timeout 0 comment "text message 84"
+2.0.1.85 timeout 0 comment "text message 85"
+2.0.1.86 timeout 0 comment "text message 86"
+2.0.1.87 timeout 0 comment "text message 87"
+2.0.1.88 timeout 0 comment "text message 88"
+2.0.1.89 timeout 0 comment "text message 89"
+2.0.1.90 timeout 0 comment "text message 90"
+2.0.1.91 timeout 0 comment "text message 91"
+2.0.1.92 timeout 0 comment "text message 92"
+2.0.1.93 timeout 0 comment "text message 93"
+2.0.1.94 timeout 0 comment "text message 94"
+2.0.1.95 timeout 0 comment "text message 95"
+2.0.1.96 timeout 0 comment "text message 96"
+2.0.1.97 timeout 0 comment "text message 97"
+2.0.1.98 timeout 0 comment "text message 98"
+2.0.1.99 timeout 0 comment "text message 99"
+2.0.1.100 timeout 0 comment "text message 100"
+2.0.1.101 timeout 0 comment "text message 101"
+2.0.1.102 timeout 0 comment "text message 102"
+2.0.1.103 timeout 0 comment "text message 103"
+2.0.1.104 timeout 0 comment "text message 104"
+2.0.1.105 timeout 0 comment "text message 105"
+2.0.1.106 timeout 0 comment "text message 106"
+2.0.1.107 timeout 0 comment "text message 107"
+2.0.1.108 timeout 0 comment "text message 108"
+2.0.1.109 timeout 0 comment "text message 109"
+2.0.1.110 timeout 0 comment "text message 110"
+2.0.1.111 timeout 0 comment "text message 111"
+2.0.1.112 timeout 0 comment "text message 112"
+2.0.1.113 timeout 0 comment "text message 113"
+2.0.1.114 timeout 0 comment "text message 114"
+2.0.1.115 timeout 0 comment "text message 115"
+2.0.1.116 timeout 0 comment "text message 116"
+2.0.1.117 timeout 0 comment "text message 117"
+2.0.1.118 timeout 0 comment "text message 118"
+2.0.1.119 timeout 0 comment "text message 119"
+2.0.1.120 timeout 0 comment "text message 120"
+2.0.1.121 timeout 0 comment "text message 121"
+2.0.1.122 timeout 0 comment "text message 122"
+2.0.1.123 timeout 0 comment "text message 123"
+2.0.1.124 timeout 0 comment "text message 124"
+2.0.1.125 timeout 0 comment "text message 125"
+2.0.1.126 timeout 0 comment "text message 126"
+2.0.1.127 timeout 0 comment "text message 127"
+2.0.1.128 timeout 0 comment "text message 128"
+2.0.1.129 timeout 0 comment "text message 129"
+2.0.1.130 timeout 0 comment "text message 130"
+2.0.1.131 timeout 0 comment "text message 131"
+2.0.1.132 timeout 0 comment "text message 132"
+2.0.1.133 timeout 0 comment "text message 133"
+2.0.1.134 timeout 0 comment "text message 134"
+2.0.1.135 timeout 0 comment "text message 135"
+2.0.1.136 timeout 0 comment "text message 136"
+2.0.1.137 timeout 0 comment "text message 137"
+2.0.1.138 timeout 0 comment "text message 138"
+2.0.1.139 timeout 0 comment "text message 139"
+2.0.1.140 timeout 0 comment "text message 140"
+2.0.1.141 timeout 0 comment "text message 141"
+2.0.1.142 timeout 0 comment "text message 142"
+2.0.1.143 timeout 0 comment "text message 143"
+2.0.1.144 timeout 0 comment "text message 144"
+2.0.1.145 timeout 0 comment "text message 145"
+2.0.1.146 timeout 0 comment "text message 146"
+2.0.1.147 timeout 0 comment "text message 147"
+2.0.1.148 timeout 0 comment "text message 148"
+2.0.1.149 timeout 0 comment "text message 149"
+2.0.1.150 timeout 0 comment "text message 150"
+2.0.1.151 timeout 0 comment "text message 151"
+2.0.1.152 timeout 0 comment "text message 152"
+2.0.1.153 timeout 0 comment "text message 153"
+2.0.1.154 timeout 0 comment "text message 154"
+2.0.1.155 timeout 0 comment "text message 155"
+2.0.1.156 timeout 0 comment "text message 156"
+2.0.1.157 timeout 0 comment "text message 157"
+2.0.1.158 timeout 0 comment "text message 158"
+2.0.1.159 timeout 0 comment "text message 159"
+2.0.1.160 timeout 0 comment "text message 160"
+2.0.1.161 timeout 0 comment "text message 161"
+2.0.1.162 timeout 0 comment "text message 162"
+2.0.1.163 timeout 0 comment "text message 163"
+2.0.1.164 timeout 0 comment "text message 164"
+2.0.1.165 timeout 0 comment "text message 165"
+2.0.1.166 timeout 0 comment "text message 166"
+2.0.1.167 timeout 0 comment "text message 167"
+2.0.1.168 timeout 0 comment "text message 168"
+2.0.1.169 timeout 0 comment "text message 169"
+2.0.1.170 timeout 0 comment "text message 170"
+2.0.1.171 timeout 0 comment "text message 171"
+2.0.1.172 timeout 0 comment "text message 172"
+2.0.1.173 timeout 0 comment "text message 173"
+2.0.1.174 timeout 0 comment "text message 174"
+2.0.1.175 timeout 0 comment "text message 175"
+2.0.1.176 timeout 0 comment "text message 176"
+2.0.1.177 timeout 0 comment "text message 177"
+2.0.1.178 timeout 0 comment "text message 178"
+2.0.1.179 timeout 0 comment "text message 179"
+2.0.1.180 timeout 0 comment "text message 180"
+2.0.1.181 timeout 0 comment "text message 181"
+2.0.1.182 timeout 0 comment "text message 182"
+2.0.1.183 timeout 0 comment "text message 183"
+2.0.1.184 timeout 0 comment "text message 184"
+2.0.1.185 timeout 0 comment "text message 185"
+2.0.1.186 timeout 0 comment "text message 186"
+2.0.1.187 timeout 0 comment "text message 187"
+2.0.1.188 timeout 0 comment "text message 188"
+2.0.1.189 timeout 0 comment "text message 189"
+2.0.1.190 timeout 0 comment "text message 190"
+2.0.1.191 timeout 0 comment "text message 191"
+2.0.1.192 timeout 0 comment "text message 192"
+2.0.1.193 timeout 0 comment "text message 193"
+2.0.1.194 timeout 0 comment "text message 194"
+2.0.1.195 timeout 0 comment "text message 195"
+2.0.1.196 timeout 0 comment "text message 196"
+2.0.1.197 timeout 0 comment "text message 197"
+2.0.1.198 timeout 0 comment "text message 198"
+2.0.1.199 timeout 0 comment "text message 199"
+2.0.1.200 timeout 0 comment "text message 200"
+2.0.1.201 timeout 0 comment "text message 201"
+2.0.1.202 timeout 0 comment "text message 202"
+2.0.1.203 timeout 0 comment "text message 203"
+2.0.1.204 timeout 0 comment "text message 204"
+2.0.1.205 timeout 0 comment "text message 205"
+2.0.1.206 timeout 0 comment "text message 206"
+2.0.1.207 timeout 0 comment "text message 207"
+2.0.1.208 timeout 0 comment "text message 208"
+2.0.1.209 timeout 0 comment "text message 209"
+2.0.1.210 timeout 0 comment "text message 210"
+2.0.1.211 timeout 0 comment "text message 211"
+2.0.1.212 timeout 0 comment "text message 212"
+2.0.1.213 timeout 0 comment "text message 213"
+2.0.1.214 timeout 0 comment "text message 214"
+2.0.1.215 timeout 0 comment "text message 215"
+2.0.1.216 timeout 0 comment "text message 216"
+2.0.1.217 timeout 0 comment "text message 217"
+2.0.1.218 timeout 0 comment "text message 218"
+2.0.1.219 timeout 0 comment "text message 219"
+2.0.1.220 timeout 0 comment "text message 220"
+2.0.1.221 timeout 0 comment "text message 221"
+2.0.1.222 timeout 0 comment "text message 222"
+2.0.1.223 timeout 0 comment "text message 223"
+2.0.1.224 timeout 0 comment "text message 224"
+2.0.1.225 timeout 0 comment "text message 225"
+2.0.1.226 timeout 0 comment "text message 226"
+2.0.1.227 timeout 0 comment "text message 227"
+2.0.1.228 timeout 0 comment "text message 228"
+2.0.1.229 timeout 0 comment "text message 229"
+2.0.1.230 timeout 0 comment "text message 230"
+2.0.1.231 timeout 0 comment "text message 231"
+2.0.1.232 timeout 0 comment "text message 232"
+2.0.1.233 timeout 0 comment "text message 233"
+2.0.1.234 timeout 0 comment "text message 234"
+2.0.1.235 timeout 0 comment "text message 235"
+2.0.1.236 timeout 0 comment "text message 236"
+2.0.1.237 timeout 0 comment "text message 237"
+2.0.1.238 timeout 0 comment "text message 238"
+2.0.1.239 timeout 0 comment "text message 239"
+2.0.1.240 timeout 0 comment "text message 240"
+2.0.1.241 timeout 0 comment "text message 241"
+2.0.1.242 timeout 0 comment "text message 242"
+2.0.1.243 timeout 0 comment "text message 243"
+2.0.1.244 timeout 0 comment "text message 244"
+2.0.1.245 timeout 0 comment "text message 245"
+2.0.1.246 timeout 0 comment "text message 246"
+2.0.1.247 timeout 0 comment "text message 247"
+2.0.1.248 timeout 0 comment "text message 248"
+2.0.1.249 timeout 0 comment "text message 249"
+2.0.1.250 timeout 0 comment "text message 250"
+2.0.1.251 timeout 0 comment "text message 251"
+2.0.1.252 timeout 0 comment "text message 252"
+2.0.1.253 timeout 0 comment "text message 253"
+2.0.1.254 timeout 0 comment "text message 254"
+2.0.1.255 timeout 0 comment "text message 255"
diff --git a/tests/comment.t.list2 b/tests/comment.t.list2
index 90a7e9b..8fc69f2 100644
--- a/tests/comment.t.list2
+++ b/tests/comment.t.list2
@@ -1,7 +1,8 @@
Name: test
Type: hash:net,net
-Header: family inet hashsize 128 maxelem 65536 comment
-Size in memory: 1288
+Revision: 3
+Header: family inet hashsize 128 maxelem 65536 comment bucketsize 12 initval 0xa48336cf
+Size in memory: 1190
References: 0
Number of entries: 4
Members:
diff --git a/tests/comment.t.list21 b/tests/comment.t.list21
index 973b344..416db40 100644
--- a/tests/comment.t.list21
+++ b/tests/comment.t.list21
@@ -1,519 +1,520 @@
Name: test
Type: hash:ip
-Header: family inet hashsize 1024 maxelem 65536 timeout x comment
-Size in memory: 95168
+Revision: 5
+Header: family inet hashsize 1024 maxelem 65536 timeout 4 comment bucketsize 12 initval 0x8a1632dd
+Size in memory: 50132
References: 0
Number of entries: 512
Members:
-2.0.0.0 timeout x comment "text message 0"
-2.0.0.1 timeout x comment "text message 1"
-2.0.0.10 timeout x comment "text message 10"
-2.0.0.100 timeout x comment "text message 100"
-2.0.0.101 timeout x comment "text message 101"
-2.0.0.102 timeout x comment "text message 102"
-2.0.0.103 timeout x comment "text message 103"
-2.0.0.104 timeout x comment "text message 104"
-2.0.0.105 timeout x comment "text message 105"
-2.0.0.106 timeout x comment "text message 106"
-2.0.0.107 timeout x comment "text message 107"
-2.0.0.108 timeout x comment "text message 108"
-2.0.0.109 timeout x comment "text message 109"
-2.0.0.11 timeout x comment "text message 11"
-2.0.0.110 timeout x comment "text message 110"
-2.0.0.111 timeout x comment "text message 111"
-2.0.0.112 timeout x comment "text message 112"
-2.0.0.113 timeout x comment "text message 113"
-2.0.0.114 timeout x comment "text message 114"
-2.0.0.115 timeout x comment "text message 115"
-2.0.0.116 timeout x comment "text message 116"
-2.0.0.117 timeout x comment "text message 117"
-2.0.0.118 timeout x comment "text message 118"
-2.0.0.119 timeout x comment "text message 119"
-2.0.0.12 timeout x comment "text message 12"
-2.0.0.120 timeout x comment "text message 120"
-2.0.0.121 timeout x comment "text message 121"
-2.0.0.122 timeout x comment "text message 122"
-2.0.0.123 timeout x comment "text message 123"
-2.0.0.124 timeout x comment "text message 124"
-2.0.0.125 timeout x comment "text message 125"
-2.0.0.126 timeout x comment "text message 126"
-2.0.0.127 timeout x comment "text message 127"
-2.0.0.128 timeout x comment "text message 128"
-2.0.0.129 timeout x comment "text message 129"
-2.0.0.13 timeout x comment "text message 13"
-2.0.0.130 timeout x comment "text message 130"
-2.0.0.131 timeout x comment "text message 131"
-2.0.0.132 timeout x comment "text message 132"
-2.0.0.133 timeout x comment "text message 133"
-2.0.0.134 timeout x comment "text message 134"
-2.0.0.135 timeout x comment "text message 135"
-2.0.0.136 timeout x comment "text message 136"
-2.0.0.137 timeout x comment "text message 137"
-2.0.0.138 timeout x comment "text message 138"
-2.0.0.139 timeout x comment "text message 139"
-2.0.0.14 timeout x comment "text message 14"
-2.0.0.140 timeout x comment "text message 140"
-2.0.0.141 timeout x comment "text message 141"
-2.0.0.142 timeout x comment "text message 142"
-2.0.0.143 timeout x comment "text message 143"
-2.0.0.144 timeout x comment "text message 144"
-2.0.0.145 timeout x comment "text message 145"
-2.0.0.146 timeout x comment "text message 146"
-2.0.0.147 timeout x comment "text message 147"
-2.0.0.148 timeout x comment "text message 148"
-2.0.0.149 timeout x comment "text message 149"
-2.0.0.15 timeout x comment "text message 15"
-2.0.0.150 timeout x comment "text message 150"
-2.0.0.151 timeout x comment "text message 151"
-2.0.0.152 timeout x comment "text message 152"
-2.0.0.153 timeout x comment "text message 153"
-2.0.0.154 timeout x comment "text message 154"
-2.0.0.155 timeout x comment "text message 155"
-2.0.0.156 timeout x comment "text message 156"
-2.0.0.157 timeout x comment "text message 157"
-2.0.0.158 timeout x comment "text message 158"
-2.0.0.159 timeout x comment "text message 159"
-2.0.0.16 timeout x comment "text message 16"
-2.0.0.160 timeout x comment "text message 160"
-2.0.0.161 timeout x comment "text message 161"
-2.0.0.162 timeout x comment "text message 162"
-2.0.0.163 timeout x comment "text message 163"
-2.0.0.164 timeout x comment "text message 164"
-2.0.0.165 timeout x comment "text message 165"
-2.0.0.166 timeout x comment "text message 166"
-2.0.0.167 timeout x comment "text message 167"
-2.0.0.168 timeout x comment "text message 168"
-2.0.0.169 timeout x comment "text message 169"
-2.0.0.17 timeout x comment "text message 17"
-2.0.0.170 timeout x comment "text message 170"
-2.0.0.171 timeout x comment "text message 171"
-2.0.0.172 timeout x comment "text message 172"
-2.0.0.173 timeout x comment "text message 173"
-2.0.0.174 timeout x comment "text message 174"
-2.0.0.175 timeout x comment "text message 175"
-2.0.0.176 timeout x comment "text message 176"
-2.0.0.177 timeout x comment "text message 177"
-2.0.0.178 timeout x comment "text message 178"
-2.0.0.179 timeout x comment "text message 179"
-2.0.0.18 timeout x comment "text message 18"
-2.0.0.180 timeout x comment "text message 180"
-2.0.0.181 timeout x comment "text message 181"
-2.0.0.182 timeout x comment "text message 182"
-2.0.0.183 timeout x comment "text message 183"
-2.0.0.184 timeout x comment "text message 184"
-2.0.0.185 timeout x comment "text message 185"
-2.0.0.186 timeout x comment "text message 186"
-2.0.0.187 timeout x comment "text message 187"
-2.0.0.188 timeout x comment "text message 188"
-2.0.0.189 timeout x comment "text message 189"
-2.0.0.19 timeout x comment "text message 19"
-2.0.0.190 timeout x comment "text message 190"
-2.0.0.191 timeout x comment "text message 191"
-2.0.0.192 timeout x comment "text message 192"
-2.0.0.193 timeout x comment "text message 193"
-2.0.0.194 timeout x comment "text message 194"
-2.0.0.195 timeout x comment "text message 195"
-2.0.0.196 timeout x comment "text message 196"
-2.0.0.197 timeout x comment "text message 197"
-2.0.0.198 timeout x comment "text message 198"
-2.0.0.199 timeout x comment "text message 199"
-2.0.0.2 timeout x comment "text message 2"
-2.0.0.20 timeout x comment "text message 20"
-2.0.0.200 timeout x comment "text message 200"
-2.0.0.201 timeout x comment "text message 201"
-2.0.0.202 timeout x comment "text message 202"
-2.0.0.203 timeout x comment "text message 203"
-2.0.0.204 timeout x comment "text message 204"
-2.0.0.205 timeout x comment "text message 205"
-2.0.0.206 timeout x comment "text message 206"
-2.0.0.207 timeout x comment "text message 207"
-2.0.0.208 timeout x comment "text message 208"
-2.0.0.209 timeout x comment "text message 209"
-2.0.0.21 timeout x comment "text message 21"
-2.0.0.210 timeout x comment "text message 210"
-2.0.0.211 timeout x comment "text message 211"
-2.0.0.212 timeout x comment "text message 212"
-2.0.0.213 timeout x comment "text message 213"
-2.0.0.214 timeout x comment "text message 214"
-2.0.0.215 timeout x comment "text message 215"
-2.0.0.216 timeout x comment "text message 216"
-2.0.0.217 timeout x comment "text message 217"
-2.0.0.218 timeout x comment "text message 218"
-2.0.0.219 timeout x comment "text message 219"
-2.0.0.22 timeout x comment "text message 22"
-2.0.0.220 timeout x comment "text message 220"
-2.0.0.221 timeout x comment "text message 221"
-2.0.0.222 timeout x comment "text message 222"
-2.0.0.223 timeout x comment "text message 223"
-2.0.0.224 timeout x comment "text message 224"
-2.0.0.225 timeout x comment "text message 225"
-2.0.0.226 timeout x comment "text message 226"
-2.0.0.227 timeout x comment "text message 227"
-2.0.0.228 timeout x comment "text message 228"
-2.0.0.229 timeout x comment "text message 229"
-2.0.0.23 timeout x comment "text message 23"
-2.0.0.230 timeout x comment "text message 230"
-2.0.0.231 timeout x comment "text message 231"
-2.0.0.232 timeout x comment "text message 232"
-2.0.0.233 timeout x comment "text message 233"
-2.0.0.234 timeout x comment "text message 234"
-2.0.0.235 timeout x comment "text message 235"
-2.0.0.236 timeout x comment "text message 236"
-2.0.0.237 timeout x comment "text message 237"
-2.0.0.238 timeout x comment "text message 238"
-2.0.0.239 timeout x comment "text message 239"
-2.0.0.24 timeout x comment "text message 24"
-2.0.0.240 timeout x comment "text message 240"
-2.0.0.241 timeout x comment "text message 241"
-2.0.0.242 timeout x comment "text message 242"
-2.0.0.243 timeout x comment "text message 243"
-2.0.0.244 timeout x comment "text message 244"
-2.0.0.245 timeout x comment "text message 245"
-2.0.0.246 timeout x comment "text message 246"
-2.0.0.247 timeout x comment "text message 247"
-2.0.0.248 timeout x comment "text message 248"
-2.0.0.249 timeout x comment "text message 249"
-2.0.0.25 timeout x comment "text message 25"
-2.0.0.250 timeout x comment "text message 250"
-2.0.0.251 timeout x comment "text message 251"
-2.0.0.252 timeout x comment "text message 252"
-2.0.0.253 timeout x comment "text message 253"
-2.0.0.254 timeout x comment "text message 254"
-2.0.0.255 timeout x comment "text message 255"
-2.0.0.26 timeout x comment "text message 26"
-2.0.0.27 timeout x comment "text message 27"
-2.0.0.28 timeout x comment "text message 28"
-2.0.0.29 timeout x comment "text message 29"
-2.0.0.3 timeout x comment "text message 3"
-2.0.0.30 timeout x comment "text message 30"
-2.0.0.31 timeout x comment "text message 31"
-2.0.0.32 timeout x comment "text message 32"
-2.0.0.33 timeout x comment "text message 33"
-2.0.0.34 timeout x comment "text message 34"
-2.0.0.35 timeout x comment "text message 35"
-2.0.0.36 timeout x comment "text message 36"
-2.0.0.37 timeout x comment "text message 37"
-2.0.0.38 timeout x comment "text message 38"
-2.0.0.39 timeout x comment "text message 39"
-2.0.0.4 timeout x comment "text message 4"
-2.0.0.40 timeout x comment "text message 40"
-2.0.0.41 timeout x comment "text message 41"
-2.0.0.42 timeout x comment "text message 42"
-2.0.0.43 timeout x comment "text message 43"
-2.0.0.44 timeout x comment "text message 44"
-2.0.0.45 timeout x comment "text message 45"
-2.0.0.46 timeout x comment "text message 46"
-2.0.0.47 timeout x comment "text message 47"
-2.0.0.48 timeout x comment "text message 48"
-2.0.0.49 timeout x comment "text message 49"
-2.0.0.5 timeout x comment "text message 5"
-2.0.0.50 timeout x comment "text message 50"
-2.0.0.51 timeout x comment "text message 51"
-2.0.0.52 timeout x comment "text message 52"
-2.0.0.53 timeout x comment "text message 53"
-2.0.0.54 timeout x comment "text message 54"
-2.0.0.55 timeout x comment "text message 55"
-2.0.0.56 timeout x comment "text message 56"
-2.0.0.57 timeout x comment "text message 57"
-2.0.0.58 timeout x comment "text message 58"
-2.0.0.59 timeout x comment "text message 59"
-2.0.0.6 timeout x comment "text message 6"
-2.0.0.60 timeout x comment "text message 60"
-2.0.0.61 timeout x comment "text message 61"
-2.0.0.62 timeout x comment "text message 62"
-2.0.0.63 timeout x comment "text message 63"
-2.0.0.64 timeout x comment "text message 64"
-2.0.0.65 timeout x comment "text message 65"
-2.0.0.66 timeout x comment "text message 66"
-2.0.0.67 timeout x comment "text message 67"
-2.0.0.68 timeout x comment "text message 68"
-2.0.0.69 timeout x comment "text message 69"
-2.0.0.7 timeout x comment "text message 7"
-2.0.0.70 timeout x comment "text message 70"
-2.0.0.71 timeout x comment "text message 71"
-2.0.0.72 timeout x comment "text message 72"
-2.0.0.73 timeout x comment "text message 73"
-2.0.0.74 timeout x comment "text message 74"
-2.0.0.75 timeout x comment "text message 75"
-2.0.0.76 timeout x comment "text message 76"
-2.0.0.77 timeout x comment "text message 77"
-2.0.0.78 timeout x comment "text message 78"
-2.0.0.79 timeout x comment "text message 79"
-2.0.0.8 timeout x comment "text message 8"
-2.0.0.80 timeout x comment "text message 80"
-2.0.0.81 timeout x comment "text message 81"
-2.0.0.82 timeout x comment "text message 82"
-2.0.0.83 timeout x comment "text message 83"
-2.0.0.84 timeout x comment "text message 84"
-2.0.0.85 timeout x comment "text message 85"
-2.0.0.86 timeout x comment "text message 86"
-2.0.0.87 timeout x comment "text message 87"
-2.0.0.88 timeout x comment "text message 88"
-2.0.0.89 timeout x comment "text message 89"
-2.0.0.9 timeout x comment "text message 9"
-2.0.0.90 timeout x comment "text message 90"
-2.0.0.91 timeout x comment "text message 91"
-2.0.0.92 timeout x comment "text message 92"
-2.0.0.93 timeout x comment "text message 93"
-2.0.0.94 timeout x comment "text message 94"
-2.0.0.95 timeout x comment "text message 95"
-2.0.0.96 timeout x comment "text message 96"
-2.0.0.97 timeout x comment "text message 97"
-2.0.0.98 timeout x comment "text message 98"
-2.0.0.99 timeout x comment "text message 99"
-2.0.1.0 timeout x comment "text message 0"
-2.0.1.1 timeout x comment "text message 1"
-2.0.1.10 timeout x comment "text message 10"
-2.0.1.100 timeout x comment "text message 100"
-2.0.1.101 timeout x comment "text message 101"
-2.0.1.102 timeout x comment "text message 102"
-2.0.1.103 timeout x comment "text message 103"
-2.0.1.104 timeout x comment "text message 104"
-2.0.1.105 timeout x comment "text message 105"
-2.0.1.106 timeout x comment "text message 106"
-2.0.1.107 timeout x comment "text message 107"
-2.0.1.108 timeout x comment "text message 108"
-2.0.1.109 timeout x comment "text message 109"
-2.0.1.11 timeout x comment "text message 11"
-2.0.1.110 timeout x comment "text message 110"
-2.0.1.111 timeout x comment "text message 111"
-2.0.1.112 timeout x comment "text message 112"
-2.0.1.113 timeout x comment "text message 113"
-2.0.1.114 timeout x comment "text message 114"
-2.0.1.115 timeout x comment "text message 115"
-2.0.1.116 timeout x comment "text message 116"
-2.0.1.117 timeout x comment "text message 117"
-2.0.1.118 timeout x comment "text message 118"
-2.0.1.119 timeout x comment "text message 119"
-2.0.1.12 timeout x comment "text message 12"
-2.0.1.120 timeout x comment "text message 120"
-2.0.1.121 timeout x comment "text message 121"
-2.0.1.122 timeout x comment "text message 122"
-2.0.1.123 timeout x comment "text message 123"
-2.0.1.124 timeout x comment "text message 124"
-2.0.1.125 timeout x comment "text message 125"
-2.0.1.126 timeout x comment "text message 126"
-2.0.1.127 timeout x comment "text message 127"
-2.0.1.128 timeout x comment "text message 128"
-2.0.1.129 timeout x comment "text message 129"
-2.0.1.13 timeout x comment "text message 13"
-2.0.1.130 timeout x comment "text message 130"
-2.0.1.131 timeout x comment "text message 131"
-2.0.1.132 timeout x comment "text message 132"
-2.0.1.133 timeout x comment "text message 133"
-2.0.1.134 timeout x comment "text message 134"
-2.0.1.135 timeout x comment "text message 135"
-2.0.1.136 timeout x comment "text message 136"
-2.0.1.137 timeout x comment "text message 137"
-2.0.1.138 timeout x comment "text message 138"
-2.0.1.139 timeout x comment "text message 139"
-2.0.1.14 timeout x comment "text message 14"
-2.0.1.140 timeout x comment "text message 140"
-2.0.1.141 timeout x comment "text message 141"
-2.0.1.142 timeout x comment "text message 142"
-2.0.1.143 timeout x comment "text message 143"
-2.0.1.144 timeout x comment "text message 144"
-2.0.1.145 timeout x comment "text message 145"
-2.0.1.146 timeout x comment "text message 146"
-2.0.1.147 timeout x comment "text message 147"
-2.0.1.148 timeout x comment "text message 148"
-2.0.1.149 timeout x comment "text message 149"
-2.0.1.15 timeout x comment "text message 15"
-2.0.1.150 timeout x comment "text message 150"
-2.0.1.151 timeout x comment "text message 151"
-2.0.1.152 timeout x comment "text message 152"
-2.0.1.153 timeout x comment "text message 153"
-2.0.1.154 timeout x comment "text message 154"
-2.0.1.155 timeout x comment "text message 155"
-2.0.1.156 timeout x comment "text message 156"
-2.0.1.157 timeout x comment "text message 157"
-2.0.1.158 timeout x comment "text message 158"
-2.0.1.159 timeout x comment "text message 159"
-2.0.1.16 timeout x comment "text message 16"
-2.0.1.160 timeout x comment "text message 160"
-2.0.1.161 timeout x comment "text message 161"
-2.0.1.162 timeout x comment "text message 162"
-2.0.1.163 timeout x comment "text message 163"
-2.0.1.164 timeout x comment "text message 164"
-2.0.1.165 timeout x comment "text message 165"
-2.0.1.166 timeout x comment "text message 166"
-2.0.1.167 timeout x comment "text message 167"
-2.0.1.168 timeout x comment "text message 168"
-2.0.1.169 timeout x comment "text message 169"
-2.0.1.17 timeout x comment "text message 17"
-2.0.1.170 timeout x comment "text message 170"
-2.0.1.171 timeout x comment "text message 171"
-2.0.1.172 timeout x comment "text message 172"
-2.0.1.173 timeout x comment "text message 173"
-2.0.1.174 timeout x comment "text message 174"
-2.0.1.175 timeout x comment "text message 175"
-2.0.1.176 timeout x comment "text message 176"
-2.0.1.177 timeout x comment "text message 177"
-2.0.1.178 timeout x comment "text message 178"
-2.0.1.179 timeout x comment "text message 179"
-2.0.1.18 timeout x comment "text message 18"
-2.0.1.180 timeout x comment "text message 180"
-2.0.1.181 timeout x comment "text message 181"
-2.0.1.182 timeout x comment "text message 182"
-2.0.1.183 timeout x comment "text message 183"
-2.0.1.184 timeout x comment "text message 184"
-2.0.1.185 timeout x comment "text message 185"
-2.0.1.186 timeout x comment "text message 186"
-2.0.1.187 timeout x comment "text message 187"
-2.0.1.188 timeout x comment "text message 188"
-2.0.1.189 timeout x comment "text message 189"
-2.0.1.19 timeout x comment "text message 19"
-2.0.1.190 timeout x comment "text message 190"
-2.0.1.191 timeout x comment "text message 191"
-2.0.1.192 timeout x comment "text message 192"
-2.0.1.193 timeout x comment "text message 193"
-2.0.1.194 timeout x comment "text message 194"
-2.0.1.195 timeout x comment "text message 195"
-2.0.1.196 timeout x comment "text message 196"
-2.0.1.197 timeout x comment "text message 197"
-2.0.1.198 timeout x comment "text message 198"
-2.0.1.199 timeout x comment "text message 199"
-2.0.1.2 timeout x comment "text message 2"
-2.0.1.20 timeout x comment "text message 20"
-2.0.1.200 timeout x comment "text message 200"
-2.0.1.201 timeout x comment "text message 201"
-2.0.1.202 timeout x comment "text message 202"
-2.0.1.203 timeout x comment "text message 203"
-2.0.1.204 timeout x comment "text message 204"
-2.0.1.205 timeout x comment "text message 205"
-2.0.1.206 timeout x comment "text message 206"
-2.0.1.207 timeout x comment "text message 207"
-2.0.1.208 timeout x comment "text message 208"
-2.0.1.209 timeout x comment "text message 209"
-2.0.1.21 timeout x comment "text message 21"
-2.0.1.210 timeout x comment "text message 210"
-2.0.1.211 timeout x comment "text message 211"
-2.0.1.212 timeout x comment "text message 212"
-2.0.1.213 timeout x comment "text message 213"
-2.0.1.214 timeout x comment "text message 214"
-2.0.1.215 timeout x comment "text message 215"
-2.0.1.216 timeout x comment "text message 216"
-2.0.1.217 timeout x comment "text message 217"
-2.0.1.218 timeout x comment "text message 218"
-2.0.1.219 timeout x comment "text message 219"
-2.0.1.22 timeout x comment "text message 22"
-2.0.1.220 timeout x comment "text message 220"
-2.0.1.221 timeout x comment "text message 221"
-2.0.1.222 timeout x comment "text message 222"
-2.0.1.223 timeout x comment "text message 223"
-2.0.1.224 timeout x comment "text message 224"
-2.0.1.225 timeout x comment "text message 225"
-2.0.1.226 timeout x comment "text message 226"
-2.0.1.227 timeout x comment "text message 227"
-2.0.1.228 timeout x comment "text message 228"
-2.0.1.229 timeout x comment "text message 229"
-2.0.1.23 timeout x comment "text message 23"
-2.0.1.230 timeout x comment "text message 230"
-2.0.1.231 timeout x comment "text message 231"
-2.0.1.232 timeout x comment "text message 232"
-2.0.1.233 timeout x comment "text message 233"
-2.0.1.234 timeout x comment "text message 234"
-2.0.1.235 timeout x comment "text message 235"
-2.0.1.236 timeout x comment "text message 236"
-2.0.1.237 timeout x comment "text message 237"
-2.0.1.238 timeout x comment "text message 238"
-2.0.1.239 timeout x comment "text message 239"
-2.0.1.24 timeout x comment "text message 24"
-2.0.1.240 timeout x comment "text message 240"
-2.0.1.241 timeout x comment "text message 241"
-2.0.1.242 timeout x comment "text message 242"
-2.0.1.243 timeout x comment "text message 243"
-2.0.1.244 timeout x comment "text message 244"
-2.0.1.245 timeout x comment "text message 245"
-2.0.1.246 timeout x comment "text message 246"
-2.0.1.247 timeout x comment "text message 247"
-2.0.1.248 timeout x comment "text message 248"
-2.0.1.249 timeout x comment "text message 249"
-2.0.1.25 timeout x comment "text message 25"
-2.0.1.250 timeout x comment "text message 250"
-2.0.1.251 timeout x comment "text message 251"
-2.0.1.252 timeout x comment "text message 252"
-2.0.1.253 timeout x comment "text message 253"
-2.0.1.254 timeout x comment "text message 254"
-2.0.1.255 timeout x comment "text message 255"
-2.0.1.26 timeout x comment "text message 26"
-2.0.1.27 timeout x comment "text message 27"
-2.0.1.28 timeout x comment "text message 28"
-2.0.1.29 timeout x comment "text message 29"
-2.0.1.3 timeout x comment "text message 3"
-2.0.1.30 timeout x comment "text message 30"
-2.0.1.31 timeout x comment "text message 31"
-2.0.1.32 timeout x comment "text message 32"
-2.0.1.33 timeout x comment "text message 33"
-2.0.1.34 timeout x comment "text message 34"
-2.0.1.35 timeout x comment "text message 35"
-2.0.1.36 timeout x comment "text message 36"
-2.0.1.37 timeout x comment "text message 37"
-2.0.1.38 timeout x comment "text message 38"
-2.0.1.39 timeout x comment "text message 39"
-2.0.1.4 timeout x comment "text message 4"
-2.0.1.40 timeout x comment "text message 40"
-2.0.1.41 timeout x comment "text message 41"
-2.0.1.42 timeout x comment "text message 42"
-2.0.1.43 timeout x comment "text message 43"
-2.0.1.44 timeout x comment "text message 44"
-2.0.1.45 timeout x comment "text message 45"
-2.0.1.46 timeout x comment "text message 46"
-2.0.1.47 timeout x comment "text message 47"
-2.0.1.48 timeout x comment "text message 48"
-2.0.1.49 timeout x comment "text message 49"
-2.0.1.5 timeout x comment "text message 5"
-2.0.1.50 timeout x comment "text message 50"
-2.0.1.51 timeout x comment "text message 51"
-2.0.1.52 timeout x comment "text message 52"
-2.0.1.53 timeout x comment "text message 53"
-2.0.1.54 timeout x comment "text message 54"
-2.0.1.55 timeout x comment "text message 55"
-2.0.1.56 timeout x comment "text message 56"
-2.0.1.57 timeout x comment "text message 57"
-2.0.1.58 timeout x comment "text message 58"
-2.0.1.59 timeout x comment "text message 59"
-2.0.1.6 timeout x comment "text message 6"
-2.0.1.60 timeout x comment "text message 60"
-2.0.1.61 timeout x comment "text message 61"
-2.0.1.62 timeout x comment "text message 62"
-2.0.1.63 timeout x comment "text message 63"
-2.0.1.64 timeout x comment "text message 64"
-2.0.1.65 timeout x comment "text message 65"
-2.0.1.66 timeout x comment "text message 66"
-2.0.1.67 timeout x comment "text message 67"
-2.0.1.68 timeout x comment "text message 68"
-2.0.1.69 timeout x comment "text message 69"
-2.0.1.7 timeout x comment "text message 7"
-2.0.1.70 timeout x comment "text message 70"
-2.0.1.71 timeout x comment "text message 71"
-2.0.1.72 timeout x comment "text message 72"
-2.0.1.73 timeout x comment "text message 73"
-2.0.1.74 timeout x comment "text message 74"
-2.0.1.75 timeout x comment "text message 75"
-2.0.1.76 timeout x comment "text message 76"
-2.0.1.77 timeout x comment "text message 77"
-2.0.1.78 timeout x comment "text message 78"
-2.0.1.79 timeout x comment "text message 79"
-2.0.1.8 timeout x comment "text message 8"
-2.0.1.80 timeout x comment "text message 80"
-2.0.1.81 timeout x comment "text message 81"
-2.0.1.82 timeout x comment "text message 82"
-2.0.1.83 timeout x comment "text message 83"
-2.0.1.84 timeout x comment "text message 84"
-2.0.1.85 timeout x comment "text message 85"
-2.0.1.86 timeout x comment "text message 86"
-2.0.1.87 timeout x comment "text message 87"
-2.0.1.88 timeout x comment "text message 88"
-2.0.1.89 timeout x comment "text message 89"
-2.0.1.9 timeout x comment "text message 9"
-2.0.1.90 timeout x comment "text message 90"
-2.0.1.91 timeout x comment "text message 91"
-2.0.1.92 timeout x comment "text message 92"
-2.0.1.93 timeout x comment "text message 93"
-2.0.1.94 timeout x comment "text message 94"
-2.0.1.95 timeout x comment "text message 95"
-2.0.1.96 timeout x comment "text message 96"
-2.0.1.97 timeout x comment "text message 97"
-2.0.1.98 timeout x comment "text message 98"
-2.0.1.99 timeout x comment "text message 99"
+2.0.0.0 timeout 3 comment "text message 0"
+2.0.0.1 timeout 3 comment "text message 1"
+2.0.0.10 timeout 3 comment "text message 10"
+2.0.0.100 timeout 3 comment "text message 100"
+2.0.0.101 timeout 3 comment "text message 101"
+2.0.0.102 timeout 3 comment "text message 102"
+2.0.0.103 timeout 3 comment "text message 103"
+2.0.0.104 timeout 3 comment "text message 104"
+2.0.0.105 timeout 3 comment "text message 105"
+2.0.0.106 timeout 3 comment "text message 106"
+2.0.0.107 timeout 3 comment "text message 107"
+2.0.0.108 timeout 3 comment "text message 108"
+2.0.0.109 timeout 3 comment "text message 109"
+2.0.0.11 timeout 3 comment "text message 11"
+2.0.0.110 timeout 3 comment "text message 110"
+2.0.0.111 timeout 3 comment "text message 111"
+2.0.0.112 timeout 3 comment "text message 112"
+2.0.0.113 timeout 3 comment "text message 113"
+2.0.0.114 timeout 3 comment "text message 114"
+2.0.0.115 timeout 3 comment "text message 115"
+2.0.0.116 timeout 3 comment "text message 116"
+2.0.0.117 timeout 3 comment "text message 117"
+2.0.0.118 timeout 3 comment "text message 118"
+2.0.0.119 timeout 3 comment "text message 119"
+2.0.0.12 timeout 3 comment "text message 12"
+2.0.0.120 timeout 3 comment "text message 120"
+2.0.0.121 timeout 3 comment "text message 121"
+2.0.0.122 timeout 3 comment "text message 122"
+2.0.0.123 timeout 3 comment "text message 123"
+2.0.0.124 timeout 3 comment "text message 124"
+2.0.0.125 timeout 3 comment "text message 125"
+2.0.0.126 timeout 3 comment "text message 126"
+2.0.0.127 timeout 3 comment "text message 127"
+2.0.0.128 timeout 3 comment "text message 128"
+2.0.0.129 timeout 3 comment "text message 129"
+2.0.0.13 timeout 3 comment "text message 13"
+2.0.0.130 timeout 3 comment "text message 130"
+2.0.0.131 timeout 3 comment "text message 131"
+2.0.0.132 timeout 3 comment "text message 132"
+2.0.0.133 timeout 3 comment "text message 133"
+2.0.0.134 timeout 3 comment "text message 134"
+2.0.0.135 timeout 3 comment "text message 135"
+2.0.0.136 timeout 3 comment "text message 136"
+2.0.0.137 timeout 3 comment "text message 137"
+2.0.0.138 timeout 3 comment "text message 138"
+2.0.0.139 timeout 3 comment "text message 139"
+2.0.0.14 timeout 3 comment "text message 14"
+2.0.0.140 timeout 3 comment "text message 140"
+2.0.0.141 timeout 3 comment "text message 141"
+2.0.0.142 timeout 3 comment "text message 142"
+2.0.0.143 timeout 3 comment "text message 143"
+2.0.0.144 timeout 3 comment "text message 144"
+2.0.0.145 timeout 3 comment "text message 145"
+2.0.0.146 timeout 3 comment "text message 146"
+2.0.0.147 timeout 3 comment "text message 147"
+2.0.0.148 timeout 3 comment "text message 148"
+2.0.0.149 timeout 3 comment "text message 149"
+2.0.0.15 timeout 3 comment "text message 15"
+2.0.0.150 timeout 3 comment "text message 150"
+2.0.0.151 timeout 3 comment "text message 151"
+2.0.0.152 timeout 3 comment "text message 152"
+2.0.0.153 timeout 3 comment "text message 153"
+2.0.0.154 timeout 3 comment "text message 154"
+2.0.0.155 timeout 3 comment "text message 155"
+2.0.0.156 timeout 3 comment "text message 156"
+2.0.0.157 timeout 3 comment "text message 157"
+2.0.0.158 timeout 3 comment "text message 158"
+2.0.0.159 timeout 3 comment "text message 159"
+2.0.0.16 timeout 3 comment "text message 16"
+2.0.0.160 timeout 3 comment "text message 160"
+2.0.0.161 timeout 3 comment "text message 161"
+2.0.0.162 timeout 3 comment "text message 162"
+2.0.0.163 timeout 3 comment "text message 163"
+2.0.0.164 timeout 3 comment "text message 164"
+2.0.0.165 timeout 3 comment "text message 165"
+2.0.0.166 timeout 3 comment "text message 166"
+2.0.0.167 timeout 3 comment "text message 167"
+2.0.0.168 timeout 3 comment "text message 168"
+2.0.0.169 timeout 3 comment "text message 169"
+2.0.0.17 timeout 3 comment "text message 17"
+2.0.0.170 timeout 3 comment "text message 170"
+2.0.0.171 timeout 3 comment "text message 171"
+2.0.0.172 timeout 3 comment "text message 172"
+2.0.0.173 timeout 3 comment "text message 173"
+2.0.0.174 timeout 3 comment "text message 174"
+2.0.0.175 timeout 3 comment "text message 175"
+2.0.0.176 timeout 3 comment "text message 176"
+2.0.0.177 timeout 3 comment "text message 177"
+2.0.0.178 timeout 3 comment "text message 178"
+2.0.0.179 timeout 3 comment "text message 179"
+2.0.0.18 timeout 3 comment "text message 18"
+2.0.0.180 timeout 3 comment "text message 180"
+2.0.0.181 timeout 3 comment "text message 181"
+2.0.0.182 timeout 3 comment "text message 182"
+2.0.0.183 timeout 3 comment "text message 183"
+2.0.0.184 timeout 3 comment "text message 184"
+2.0.0.185 timeout 3 comment "text message 185"
+2.0.0.186 timeout 3 comment "text message 186"
+2.0.0.187 timeout 3 comment "text message 187"
+2.0.0.188 timeout 3 comment "text message 188"
+2.0.0.189 timeout 3 comment "text message 189"
+2.0.0.19 timeout 3 comment "text message 19"
+2.0.0.190 timeout 3 comment "text message 190"
+2.0.0.191 timeout 3 comment "text message 191"
+2.0.0.192 timeout 3 comment "text message 192"
+2.0.0.193 timeout 3 comment "text message 193"
+2.0.0.194 timeout 3 comment "text message 194"
+2.0.0.195 timeout 3 comment "text message 195"
+2.0.0.196 timeout 3 comment "text message 196"
+2.0.0.197 timeout 3 comment "text message 197"
+2.0.0.198 timeout 3 comment "text message 198"
+2.0.0.199 timeout 3 comment "text message 199"
+2.0.0.2 timeout 3 comment "text message 2"
+2.0.0.20 timeout 3 comment "text message 20"
+2.0.0.200 timeout 3 comment "text message 200"
+2.0.0.201 timeout 3 comment "text message 201"
+2.0.0.202 timeout 3 comment "text message 202"
+2.0.0.203 timeout 3 comment "text message 203"
+2.0.0.204 timeout 3 comment "text message 204"
+2.0.0.205 timeout 3 comment "text message 205"
+2.0.0.206 timeout 3 comment "text message 206"
+2.0.0.207 timeout 3 comment "text message 207"
+2.0.0.208 timeout 3 comment "text message 208"
+2.0.0.209 timeout 3 comment "text message 209"
+2.0.0.21 timeout 3 comment "text message 21"
+2.0.0.210 timeout 3 comment "text message 210"
+2.0.0.211 timeout 3 comment "text message 211"
+2.0.0.212 timeout 3 comment "text message 212"
+2.0.0.213 timeout 3 comment "text message 213"
+2.0.0.214 timeout 3 comment "text message 214"
+2.0.0.215 timeout 3 comment "text message 215"
+2.0.0.216 timeout 3 comment "text message 216"
+2.0.0.217 timeout 3 comment "text message 217"
+2.0.0.218 timeout 3 comment "text message 218"
+2.0.0.219 timeout 3 comment "text message 219"
+2.0.0.22 timeout 3 comment "text message 22"
+2.0.0.220 timeout 3 comment "text message 220"
+2.0.0.221 timeout 3 comment "text message 221"
+2.0.0.222 timeout 3 comment "text message 222"
+2.0.0.223 timeout 3 comment "text message 223"
+2.0.0.224 timeout 3 comment "text message 224"
+2.0.0.225 timeout 3 comment "text message 225"
+2.0.0.226 timeout 3 comment "text message 226"
+2.0.0.227 timeout 3 comment "text message 227"
+2.0.0.228 timeout 3 comment "text message 228"
+2.0.0.229 timeout 3 comment "text message 229"
+2.0.0.23 timeout 3 comment "text message 23"
+2.0.0.230 timeout 3 comment "text message 230"
+2.0.0.231 timeout 3 comment "text message 231"
+2.0.0.232 timeout 3 comment "text message 232"
+2.0.0.233 timeout 3 comment "text message 233"
+2.0.0.234 timeout 3 comment "text message 234"
+2.0.0.235 timeout 3 comment "text message 235"
+2.0.0.236 timeout 3 comment "text message 236"
+2.0.0.237 timeout 3 comment "text message 237"
+2.0.0.238 timeout 3 comment "text message 238"
+2.0.0.239 timeout 3 comment "text message 239"
+2.0.0.24 timeout 3 comment "text message 24"
+2.0.0.240 timeout 3 comment "text message 240"
+2.0.0.241 timeout 3 comment "text message 241"
+2.0.0.242 timeout 3 comment "text message 242"
+2.0.0.243 timeout 3 comment "text message 243"
+2.0.0.244 timeout 3 comment "text message 244"
+2.0.0.245 timeout 3 comment "text message 245"
+2.0.0.246 timeout 3 comment "text message 246"
+2.0.0.247 timeout 3 comment "text message 247"
+2.0.0.248 timeout 3 comment "text message 248"
+2.0.0.249 timeout 3 comment "text message 249"
+2.0.0.25 timeout 3 comment "text message 25"
+2.0.0.250 timeout 3 comment "text message 250"
+2.0.0.251 timeout 3 comment "text message 251"
+2.0.0.252 timeout 3 comment "text message 252"
+2.0.0.253 timeout 3 comment "text message 253"
+2.0.0.254 timeout 3 comment "text message 254"
+2.0.0.255 timeout 3 comment "text message 255"
+2.0.0.26 timeout 3 comment "text message 26"
+2.0.0.27 timeout 3 comment "text message 27"
+2.0.0.28 timeout 3 comment "text message 28"
+2.0.0.29 timeout 3 comment "text message 29"
+2.0.0.3 timeout 3 comment "text message 3"
+2.0.0.30 timeout 3 comment "text message 30"
+2.0.0.31 timeout 3 comment "text message 31"
+2.0.0.32 timeout 3 comment "text message 32"
+2.0.0.33 timeout 3 comment "text message 33"
+2.0.0.34 timeout 3 comment "text message 34"
+2.0.0.35 timeout 3 comment "text message 35"
+2.0.0.36 timeout 3 comment "text message 36"
+2.0.0.37 timeout 3 comment "text message 37"
+2.0.0.38 timeout 3 comment "text message 38"
+2.0.0.39 timeout 3 comment "text message 39"
+2.0.0.4 timeout 3 comment "text message 4"
+2.0.0.40 timeout 3 comment "text message 40"
+2.0.0.41 timeout 3 comment "text message 41"
+2.0.0.42 timeout 3 comment "text message 42"
+2.0.0.43 timeout 3 comment "text message 43"
+2.0.0.44 timeout 3 comment "text message 44"
+2.0.0.45 timeout 3 comment "text message 45"
+2.0.0.46 timeout 3 comment "text message 46"
+2.0.0.47 timeout 3 comment "text message 47"
+2.0.0.48 timeout 3 comment "text message 48"
+2.0.0.49 timeout 3 comment "text message 49"
+2.0.0.5 timeout 3 comment "text message 5"
+2.0.0.50 timeout 3 comment "text message 50"
+2.0.0.51 timeout 3 comment "text message 51"
+2.0.0.52 timeout 3 comment "text message 52"
+2.0.0.53 timeout 3 comment "text message 53"
+2.0.0.54 timeout 3 comment "text message 54"
+2.0.0.55 timeout 3 comment "text message 55"
+2.0.0.56 timeout 3 comment "text message 56"
+2.0.0.57 timeout 3 comment "text message 57"
+2.0.0.58 timeout 3 comment "text message 58"
+2.0.0.59 timeout 3 comment "text message 59"
+2.0.0.6 timeout 3 comment "text message 6"
+2.0.0.60 timeout 3 comment "text message 60"
+2.0.0.61 timeout 3 comment "text message 61"
+2.0.0.62 timeout 3 comment "text message 62"
+2.0.0.63 timeout 3 comment "text message 63"
+2.0.0.64 timeout 3 comment "text message 64"
+2.0.0.65 timeout 3 comment "text message 65"
+2.0.0.66 timeout 3 comment "text message 66"
+2.0.0.67 timeout 3 comment "text message 67"
+2.0.0.68 timeout 3 comment "text message 68"
+2.0.0.69 timeout 3 comment "text message 69"
+2.0.0.7 timeout 3 comment "text message 7"
+2.0.0.70 timeout 3 comment "text message 70"
+2.0.0.71 timeout 3 comment "text message 71"
+2.0.0.72 timeout 3 comment "text message 72"
+2.0.0.73 timeout 3 comment "text message 73"
+2.0.0.74 timeout 3 comment "text message 74"
+2.0.0.75 timeout 3 comment "text message 75"
+2.0.0.76 timeout 3 comment "text message 76"
+2.0.0.77 timeout 3 comment "text message 77"
+2.0.0.78 timeout 3 comment "text message 78"
+2.0.0.79 timeout 3 comment "text message 79"
+2.0.0.8 timeout 3 comment "text message 8"
+2.0.0.80 timeout 3 comment "text message 80"
+2.0.0.81 timeout 3 comment "text message 81"
+2.0.0.82 timeout 3 comment "text message 82"
+2.0.0.83 timeout 3 comment "text message 83"
+2.0.0.84 timeout 3 comment "text message 84"
+2.0.0.85 timeout 3 comment "text message 85"
+2.0.0.86 timeout 3 comment "text message 86"
+2.0.0.87 timeout 3 comment "text message 87"
+2.0.0.88 timeout 3 comment "text message 88"
+2.0.0.89 timeout 3 comment "text message 89"
+2.0.0.9 timeout 3 comment "text message 9"
+2.0.0.90 timeout 3 comment "text message 90"
+2.0.0.91 timeout 3 comment "text message 91"
+2.0.0.92 timeout 3 comment "text message 92"
+2.0.0.93 timeout 3 comment "text message 93"
+2.0.0.94 timeout 3 comment "text message 94"
+2.0.0.95 timeout 3 comment "text message 95"
+2.0.0.96 timeout 3 comment "text message 96"
+2.0.0.97 timeout 3 comment "text message 97"
+2.0.0.98 timeout 3 comment "text message 98"
+2.0.0.99 timeout 3 comment "text message 99"
+2.0.1.0 timeout 0 comment "text message 0"
+2.0.1.1 timeout 0 comment "text message 1"
+2.0.1.10 timeout 0 comment "text message 10"
+2.0.1.100 timeout 0 comment "text message 100"
+2.0.1.101 timeout 0 comment "text message 101"
+2.0.1.102 timeout 0 comment "text message 102"
+2.0.1.103 timeout 0 comment "text message 103"
+2.0.1.104 timeout 0 comment "text message 104"
+2.0.1.105 timeout 0 comment "text message 105"
+2.0.1.106 timeout 0 comment "text message 106"
+2.0.1.107 timeout 0 comment "text message 107"
+2.0.1.108 timeout 0 comment "text message 108"
+2.0.1.109 timeout 0 comment "text message 109"
+2.0.1.11 timeout 0 comment "text message 11"
+2.0.1.110 timeout 0 comment "text message 110"
+2.0.1.111 timeout 0 comment "text message 111"
+2.0.1.112 timeout 0 comment "text message 112"
+2.0.1.113 timeout 0 comment "text message 113"
+2.0.1.114 timeout 0 comment "text message 114"
+2.0.1.115 timeout 0 comment "text message 115"
+2.0.1.116 timeout 0 comment "text message 116"
+2.0.1.117 timeout 0 comment "text message 117"
+2.0.1.118 timeout 0 comment "text message 118"
+2.0.1.119 timeout 0 comment "text message 119"
+2.0.1.12 timeout 0 comment "text message 12"
+2.0.1.120 timeout 0 comment "text message 120"
+2.0.1.121 timeout 0 comment "text message 121"
+2.0.1.122 timeout 0 comment "text message 122"
+2.0.1.123 timeout 0 comment "text message 123"
+2.0.1.124 timeout 0 comment "text message 124"
+2.0.1.125 timeout 0 comment "text message 125"
+2.0.1.126 timeout 0 comment "text message 126"
+2.0.1.127 timeout 0 comment "text message 127"
+2.0.1.128 timeout 0 comment "text message 128"
+2.0.1.129 timeout 0 comment "text message 129"
+2.0.1.13 timeout 0 comment "text message 13"
+2.0.1.130 timeout 0 comment "text message 130"
+2.0.1.131 timeout 0 comment "text message 131"
+2.0.1.132 timeout 0 comment "text message 132"
+2.0.1.133 timeout 0 comment "text message 133"
+2.0.1.134 timeout 0 comment "text message 134"
+2.0.1.135 timeout 0 comment "text message 135"
+2.0.1.136 timeout 0 comment "text message 136"
+2.0.1.137 timeout 0 comment "text message 137"
+2.0.1.138 timeout 0 comment "text message 138"
+2.0.1.139 timeout 0 comment "text message 139"
+2.0.1.14 timeout 0 comment "text message 14"
+2.0.1.140 timeout 0 comment "text message 140"
+2.0.1.141 timeout 0 comment "text message 141"
+2.0.1.142 timeout 0 comment "text message 142"
+2.0.1.143 timeout 0 comment "text message 143"
+2.0.1.144 timeout 0 comment "text message 144"
+2.0.1.145 timeout 0 comment "text message 145"
+2.0.1.146 timeout 0 comment "text message 146"
+2.0.1.147 timeout 0 comment "text message 147"
+2.0.1.148 timeout 0 comment "text message 148"
+2.0.1.149 timeout 0 comment "text message 149"
+2.0.1.15 timeout 0 comment "text message 15"
+2.0.1.150 timeout 0 comment "text message 150"
+2.0.1.151 timeout 0 comment "text message 151"
+2.0.1.152 timeout 0 comment "text message 152"
+2.0.1.153 timeout 0 comment "text message 153"
+2.0.1.154 timeout 0 comment "text message 154"
+2.0.1.155 timeout 0 comment "text message 155"
+2.0.1.156 timeout 0 comment "text message 156"
+2.0.1.157 timeout 0 comment "text message 157"
+2.0.1.158 timeout 0 comment "text message 158"
+2.0.1.159 timeout 0 comment "text message 159"
+2.0.1.16 timeout 0 comment "text message 16"
+2.0.1.160 timeout 0 comment "text message 160"
+2.0.1.161 timeout 0 comment "text message 161"
+2.0.1.162 timeout 0 comment "text message 162"
+2.0.1.163 timeout 0 comment "text message 163"
+2.0.1.164 timeout 0 comment "text message 164"
+2.0.1.165 timeout 0 comment "text message 165"
+2.0.1.166 timeout 0 comment "text message 166"
+2.0.1.167 timeout 0 comment "text message 167"
+2.0.1.168 timeout 0 comment "text message 168"
+2.0.1.169 timeout 0 comment "text message 169"
+2.0.1.17 timeout 0 comment "text message 17"
+2.0.1.170 timeout 0 comment "text message 170"
+2.0.1.171 timeout 0 comment "text message 171"
+2.0.1.172 timeout 0 comment "text message 172"
+2.0.1.173 timeout 0 comment "text message 173"
+2.0.1.174 timeout 0 comment "text message 174"
+2.0.1.175 timeout 0 comment "text message 175"
+2.0.1.176 timeout 0 comment "text message 176"
+2.0.1.177 timeout 0 comment "text message 177"
+2.0.1.178 timeout 0 comment "text message 178"
+2.0.1.179 timeout 0 comment "text message 179"
+2.0.1.18 timeout 0 comment "text message 18"
+2.0.1.180 timeout 0 comment "text message 180"
+2.0.1.181 timeout 0 comment "text message 181"
+2.0.1.182 timeout 0 comment "text message 182"
+2.0.1.183 timeout 0 comment "text message 183"
+2.0.1.184 timeout 0 comment "text message 184"
+2.0.1.185 timeout 0 comment "text message 185"
+2.0.1.186 timeout 0 comment "text message 186"
+2.0.1.187 timeout 0 comment "text message 187"
+2.0.1.188 timeout 0 comment "text message 188"
+2.0.1.189 timeout 0 comment "text message 189"
+2.0.1.19 timeout 0 comment "text message 19"
+2.0.1.190 timeout 0 comment "text message 190"
+2.0.1.191 timeout 0 comment "text message 191"
+2.0.1.192 timeout 0 comment "text message 192"
+2.0.1.193 timeout 0 comment "text message 193"
+2.0.1.194 timeout 0 comment "text message 194"
+2.0.1.195 timeout 0 comment "text message 195"
+2.0.1.196 timeout 0 comment "text message 196"
+2.0.1.197 timeout 0 comment "text message 197"
+2.0.1.198 timeout 0 comment "text message 198"
+2.0.1.199 timeout 0 comment "text message 199"
+2.0.1.2 timeout 0 comment "text message 2"
+2.0.1.20 timeout 0 comment "text message 20"
+2.0.1.200 timeout 0 comment "text message 200"
+2.0.1.201 timeout 0 comment "text message 201"
+2.0.1.202 timeout 0 comment "text message 202"
+2.0.1.203 timeout 0 comment "text message 203"
+2.0.1.204 timeout 0 comment "text message 204"
+2.0.1.205 timeout 0 comment "text message 205"
+2.0.1.206 timeout 0 comment "text message 206"
+2.0.1.207 timeout 0 comment "text message 207"
+2.0.1.208 timeout 0 comment "text message 208"
+2.0.1.209 timeout 0 comment "text message 209"
+2.0.1.21 timeout 0 comment "text message 21"
+2.0.1.210 timeout 0 comment "text message 210"
+2.0.1.211 timeout 0 comment "text message 211"
+2.0.1.212 timeout 0 comment "text message 212"
+2.0.1.213 timeout 0 comment "text message 213"
+2.0.1.214 timeout 0 comment "text message 214"
+2.0.1.215 timeout 0 comment "text message 215"
+2.0.1.216 timeout 0 comment "text message 216"
+2.0.1.217 timeout 0 comment "text message 217"
+2.0.1.218 timeout 0 comment "text message 218"
+2.0.1.219 timeout 0 comment "text message 219"
+2.0.1.22 timeout 0 comment "text message 22"
+2.0.1.220 timeout 0 comment "text message 220"
+2.0.1.221 timeout 0 comment "text message 221"
+2.0.1.222 timeout 0 comment "text message 222"
+2.0.1.223 timeout 0 comment "text message 223"
+2.0.1.224 timeout 0 comment "text message 224"
+2.0.1.225 timeout 0 comment "text message 225"
+2.0.1.226 timeout 0 comment "text message 226"
+2.0.1.227 timeout 0 comment "text message 227"
+2.0.1.228 timeout 0 comment "text message 228"
+2.0.1.229 timeout 0 comment "text message 229"
+2.0.1.23 timeout 0 comment "text message 23"
+2.0.1.230 timeout 0 comment "text message 230"
+2.0.1.231 timeout 0 comment "text message 231"
+2.0.1.232 timeout 0 comment "text message 232"
+2.0.1.233 timeout 0 comment "text message 233"
+2.0.1.234 timeout 0 comment "text message 234"
+2.0.1.235 timeout 0 comment "text message 235"
+2.0.1.236 timeout 0 comment "text message 236"
+2.0.1.237 timeout 0 comment "text message 237"
+2.0.1.238 timeout 0 comment "text message 238"
+2.0.1.239 timeout 0 comment "text message 239"
+2.0.1.24 timeout 0 comment "text message 24"
+2.0.1.240 timeout 0 comment "text message 240"
+2.0.1.241 timeout 0 comment "text message 241"
+2.0.1.242 timeout 0 comment "text message 242"
+2.0.1.243 timeout 0 comment "text message 243"
+2.0.1.244 timeout 0 comment "text message 244"
+2.0.1.245 timeout 0 comment "text message 245"
+2.0.1.246 timeout 0 comment "text message 246"
+2.0.1.247 timeout 0 comment "text message 247"
+2.0.1.248 timeout 0 comment "text message 248"
+2.0.1.249 timeout 0 comment "text message 249"
+2.0.1.25 timeout 0 comment "text message 25"
+2.0.1.250 timeout 0 comment "text message 250"
+2.0.1.251 timeout 0 comment "text message 251"
+2.0.1.252 timeout 0 comment "text message 252"
+2.0.1.253 timeout 0 comment "text message 253"
+2.0.1.254 timeout 0 comment "text message 254"
+2.0.1.255 timeout 0 comment "text message 255"
+2.0.1.26 timeout 0 comment "text message 26"
+2.0.1.27 timeout 0 comment "text message 27"
+2.0.1.28 timeout 0 comment "text message 28"
+2.0.1.29 timeout 0 comment "text message 29"
+2.0.1.3 timeout 0 comment "text message 3"
+2.0.1.30 timeout 0 comment "text message 30"
+2.0.1.31 timeout 0 comment "text message 31"
+2.0.1.32 timeout 0 comment "text message 32"
+2.0.1.33 timeout 0 comment "text message 33"
+2.0.1.34 timeout 0 comment "text message 34"
+2.0.1.35 timeout 0 comment "text message 35"
+2.0.1.36 timeout 0 comment "text message 36"
+2.0.1.37 timeout 0 comment "text message 37"
+2.0.1.38 timeout 0 comment "text message 38"
+2.0.1.39 timeout 0 comment "text message 39"
+2.0.1.4 timeout 0 comment "text message 4"
+2.0.1.40 timeout 0 comment "text message 40"
+2.0.1.41 timeout 0 comment "text message 41"
+2.0.1.42 timeout 0 comment "text message 42"
+2.0.1.43 timeout 0 comment "text message 43"
+2.0.1.44 timeout 0 comment "text message 44"
+2.0.1.45 timeout 0 comment "text message 45"
+2.0.1.46 timeout 0 comment "text message 46"
+2.0.1.47 timeout 0 comment "text message 47"
+2.0.1.48 timeout 0 comment "text message 48"
+2.0.1.49 timeout 0 comment "text message 49"
+2.0.1.5 timeout 0 comment "text message 5"
+2.0.1.50 timeout 0 comment "text message 50"
+2.0.1.51 timeout 0 comment "text message 51"
+2.0.1.52 timeout 0 comment "text message 52"
+2.0.1.53 timeout 0 comment "text message 53"
+2.0.1.54 timeout 0 comment "text message 54"
+2.0.1.55 timeout 0 comment "text message 55"
+2.0.1.56 timeout 0 comment "text message 56"
+2.0.1.57 timeout 0 comment "text message 57"
+2.0.1.58 timeout 0 comment "text message 58"
+2.0.1.59 timeout 0 comment "text message 59"
+2.0.1.6 timeout 0 comment "text message 6"
+2.0.1.60 timeout 0 comment "text message 60"
+2.0.1.61 timeout 0 comment "text message 61"
+2.0.1.62 timeout 0 comment "text message 62"
+2.0.1.63 timeout 0 comment "text message 63"
+2.0.1.64 timeout 0 comment "text message 64"
+2.0.1.65 timeout 0 comment "text message 65"
+2.0.1.66 timeout 0 comment "text message 66"
+2.0.1.67 timeout 0 comment "text message 67"
+2.0.1.68 timeout 0 comment "text message 68"
+2.0.1.69 timeout 0 comment "text message 69"
+2.0.1.7 timeout 0 comment "text message 7"
+2.0.1.70 timeout 0 comment "text message 70"
+2.0.1.71 timeout 0 comment "text message 71"
+2.0.1.72 timeout 0 comment "text message 72"
+2.0.1.73 timeout 0 comment "text message 73"
+2.0.1.74 timeout 0 comment "text message 74"
+2.0.1.75 timeout 0 comment "text message 75"
+2.0.1.76 timeout 0 comment "text message 76"
+2.0.1.77 timeout 0 comment "text message 77"
+2.0.1.78 timeout 0 comment "text message 78"
+2.0.1.79 timeout 0 comment "text message 79"
+2.0.1.8 timeout 0 comment "text message 8"
+2.0.1.80 timeout 0 comment "text message 80"
+2.0.1.81 timeout 0 comment "text message 81"
+2.0.1.82 timeout 0 comment "text message 82"
+2.0.1.83 timeout 0 comment "text message 83"
+2.0.1.84 timeout 0 comment "text message 84"
+2.0.1.85 timeout 0 comment "text message 85"
+2.0.1.86 timeout 0 comment "text message 86"
+2.0.1.87 timeout 0 comment "text message 87"
+2.0.1.88 timeout 0 comment "text message 88"
+2.0.1.89 timeout 0 comment "text message 89"
+2.0.1.9 timeout 0 comment "text message 9"
+2.0.1.90 timeout 0 comment "text message 90"
+2.0.1.91 timeout 0 comment "text message 91"
+2.0.1.92 timeout 0 comment "text message 92"
+2.0.1.93 timeout 0 comment "text message 93"
+2.0.1.94 timeout 0 comment "text message 94"
+2.0.1.95 timeout 0 comment "text message 95"
+2.0.1.96 timeout 0 comment "text message 96"
+2.0.1.97 timeout 0 comment "text message 97"
+2.0.1.98 timeout 0 comment "text message 98"
+2.0.1.99 timeout 0 comment "text message 99"
diff --git a/tests/comment.t.list22 b/tests/comment.t.list22
index 9215b0d..4cfdabe 100644
--- a/tests/comment.t.list22
+++ b/tests/comment.t.list22
@@ -1,263 +1,264 @@
Name: test
Type: hash:ip
-Header: family inet hashsize 1024 maxelem 65536 timeout x comment
-Size in memory: 57634
+Revision: 5
+Header: family inet hashsize 1024 maxelem 65536 timeout 4 comment bucketsize 12 initval 0x8e7fb9de
+Size in memory: 40834
References: 0
Number of entries: 256
Members:
-2.0.1.0 timeout x comment "text message 0"
-2.0.1.1 timeout x comment "text message 1"
-2.0.1.10 timeout x comment "text message 10"
-2.0.1.100 timeout x comment "text message 100"
-2.0.1.101 timeout x comment "text message 101"
-2.0.1.102 timeout x comment "text message 102"
-2.0.1.103 timeout x comment "text message 103"
-2.0.1.104 timeout x comment "text message 104"
-2.0.1.105 timeout x comment "text message 105"
-2.0.1.106 timeout x comment "text message 106"
-2.0.1.107 timeout x comment "text message 107"
-2.0.1.108 timeout x comment "text message 108"
-2.0.1.109 timeout x comment "text message 109"
-2.0.1.11 timeout x comment "text message 11"
-2.0.1.110 timeout x comment "text message 110"
-2.0.1.111 timeout x comment "text message 111"
-2.0.1.112 timeout x comment "text message 112"
-2.0.1.113 timeout x comment "text message 113"
-2.0.1.114 timeout x comment "text message 114"
-2.0.1.115 timeout x comment "text message 115"
-2.0.1.116 timeout x comment "text message 116"
-2.0.1.117 timeout x comment "text message 117"
-2.0.1.118 timeout x comment "text message 118"
-2.0.1.119 timeout x comment "text message 119"
-2.0.1.12 timeout x comment "text message 12"
-2.0.1.120 timeout x comment "text message 120"
-2.0.1.121 timeout x comment "text message 121"
-2.0.1.122 timeout x comment "text message 122"
-2.0.1.123 timeout x comment "text message 123"
-2.0.1.124 timeout x comment "text message 124"
-2.0.1.125 timeout x comment "text message 125"
-2.0.1.126 timeout x comment "text message 126"
-2.0.1.127 timeout x comment "text message 127"
-2.0.1.128 timeout x comment "text message 128"
-2.0.1.129 timeout x comment "text message 129"
-2.0.1.13 timeout x comment "text message 13"
-2.0.1.130 timeout x comment "text message 130"
-2.0.1.131 timeout x comment "text message 131"
-2.0.1.132 timeout x comment "text message 132"
-2.0.1.133 timeout x comment "text message 133"
-2.0.1.134 timeout x comment "text message 134"
-2.0.1.135 timeout x comment "text message 135"
-2.0.1.136 timeout x comment "text message 136"
-2.0.1.137 timeout x comment "text message 137"
-2.0.1.138 timeout x comment "text message 138"
-2.0.1.139 timeout x comment "text message 139"
-2.0.1.14 timeout x comment "text message 14"
-2.0.1.140 timeout x comment "text message 140"
-2.0.1.141 timeout x comment "text message 141"
-2.0.1.142 timeout x comment "text message 142"
-2.0.1.143 timeout x comment "text message 143"
-2.0.1.144 timeout x comment "text message 144"
-2.0.1.145 timeout x comment "text message 145"
-2.0.1.146 timeout x comment "text message 146"
-2.0.1.147 timeout x comment "text message 147"
-2.0.1.148 timeout x comment "text message 148"
-2.0.1.149 timeout x comment "text message 149"
-2.0.1.15 timeout x comment "text message 15"
-2.0.1.150 timeout x comment "text message 150"
-2.0.1.151 timeout x comment "text message 151"
-2.0.1.152 timeout x comment "text message 152"
-2.0.1.153 timeout x comment "text message 153"
-2.0.1.154 timeout x comment "text message 154"
-2.0.1.155 timeout x comment "text message 155"
-2.0.1.156 timeout x comment "text message 156"
-2.0.1.157 timeout x comment "text message 157"
-2.0.1.158 timeout x comment "text message 158"
-2.0.1.159 timeout x comment "text message 159"
-2.0.1.16 timeout x comment "text message 16"
-2.0.1.160 timeout x comment "text message 160"
-2.0.1.161 timeout x comment "text message 161"
-2.0.1.162 timeout x comment "text message 162"
-2.0.1.163 timeout x comment "text message 163"
-2.0.1.164 timeout x comment "text message 164"
-2.0.1.165 timeout x comment "text message 165"
-2.0.1.166 timeout x comment "text message 166"
-2.0.1.167 timeout x comment "text message 167"
-2.0.1.168 timeout x comment "text message 168"
-2.0.1.169 timeout x comment "text message 169"
-2.0.1.17 timeout x comment "text message 17"
-2.0.1.170 timeout x comment "text message 170"
-2.0.1.171 timeout x comment "text message 171"
-2.0.1.172 timeout x comment "text message 172"
-2.0.1.173 timeout x comment "text message 173"
-2.0.1.174 timeout x comment "text message 174"
-2.0.1.175 timeout x comment "text message 175"
-2.0.1.176 timeout x comment "text message 176"
-2.0.1.177 timeout x comment "text message 177"
-2.0.1.178 timeout x comment "text message 178"
-2.0.1.179 timeout x comment "text message 179"
-2.0.1.18 timeout x comment "text message 18"
-2.0.1.180 timeout x comment "text message 180"
-2.0.1.181 timeout x comment "text message 181"
-2.0.1.182 timeout x comment "text message 182"
-2.0.1.183 timeout x comment "text message 183"
-2.0.1.184 timeout x comment "text message 184"
-2.0.1.185 timeout x comment "text message 185"
-2.0.1.186 timeout x comment "text message 186"
-2.0.1.187 timeout x comment "text message 187"
-2.0.1.188 timeout x comment "text message 188"
-2.0.1.189 timeout x comment "text message 189"
-2.0.1.19 timeout x comment "text message 19"
-2.0.1.190 timeout x comment "text message 190"
-2.0.1.191 timeout x comment "text message 191"
-2.0.1.192 timeout x comment "text message 192"
-2.0.1.193 timeout x comment "text message 193"
-2.0.1.194 timeout x comment "text message 194"
-2.0.1.195 timeout x comment "text message 195"
-2.0.1.196 timeout x comment "text message 196"
-2.0.1.197 timeout x comment "text message 197"
-2.0.1.198 timeout x comment "text message 198"
-2.0.1.199 timeout x comment "text message 199"
-2.0.1.2 timeout x comment "text message 2"
-2.0.1.20 timeout x comment "text message 20"
-2.0.1.200 timeout x comment "text message 200"
-2.0.1.201 timeout x comment "text message 201"
-2.0.1.202 timeout x comment "text message 202"
-2.0.1.203 timeout x comment "text message 203"
-2.0.1.204 timeout x comment "text message 204"
-2.0.1.205 timeout x comment "text message 205"
-2.0.1.206 timeout x comment "text message 206"
-2.0.1.207 timeout x comment "text message 207"
-2.0.1.208 timeout x comment "text message 208"
-2.0.1.209 timeout x comment "text message 209"
-2.0.1.21 timeout x comment "text message 21"
-2.0.1.210 timeout x comment "text message 210"
-2.0.1.211 timeout x comment "text message 211"
-2.0.1.212 timeout x comment "text message 212"
-2.0.1.213 timeout x comment "text message 213"
-2.0.1.214 timeout x comment "text message 214"
-2.0.1.215 timeout x comment "text message 215"
-2.0.1.216 timeout x comment "text message 216"
-2.0.1.217 timeout x comment "text message 217"
-2.0.1.218 timeout x comment "text message 218"
-2.0.1.219 timeout x comment "text message 219"
-2.0.1.22 timeout x comment "text message 22"
-2.0.1.220 timeout x comment "text message 220"
-2.0.1.221 timeout x comment "text message 221"
-2.0.1.222 timeout x comment "text message 222"
-2.0.1.223 timeout x comment "text message 223"
-2.0.1.224 timeout x comment "text message 224"
-2.0.1.225 timeout x comment "text message 225"
-2.0.1.226 timeout x comment "text message 226"
-2.0.1.227 timeout x comment "text message 227"
-2.0.1.228 timeout x comment "text message 228"
-2.0.1.229 timeout x comment "text message 229"
-2.0.1.23 timeout x comment "text message 23"
-2.0.1.230 timeout x comment "text message 230"
-2.0.1.231 timeout x comment "text message 231"
-2.0.1.232 timeout x comment "text message 232"
-2.0.1.233 timeout x comment "text message 233"
-2.0.1.234 timeout x comment "text message 234"
-2.0.1.235 timeout x comment "text message 235"
-2.0.1.236 timeout x comment "text message 236"
-2.0.1.237 timeout x comment "text message 237"
-2.0.1.238 timeout x comment "text message 238"
-2.0.1.239 timeout x comment "text message 239"
-2.0.1.24 timeout x comment "text message 24"
-2.0.1.240 timeout x comment "text message 240"
-2.0.1.241 timeout x comment "text message 241"
-2.0.1.242 timeout x comment "text message 242"
-2.0.1.243 timeout x comment "text message 243"
-2.0.1.244 timeout x comment "text message 244"
-2.0.1.245 timeout x comment "text message 245"
-2.0.1.246 timeout x comment "text message 246"
-2.0.1.247 timeout x comment "text message 247"
-2.0.1.248 timeout x comment "text message 248"
-2.0.1.249 timeout x comment "text message 249"
-2.0.1.25 timeout x comment "text message 25"
-2.0.1.250 timeout x comment "text message 250"
-2.0.1.251 timeout x comment "text message 251"
-2.0.1.252 timeout x comment "text message 252"
-2.0.1.253 timeout x comment "text message 253"
-2.0.1.254 timeout x comment "text message 254"
-2.0.1.255 timeout x comment "text message 255"
-2.0.1.26 timeout x comment "text message 26"
-2.0.1.27 timeout x comment "text message 27"
-2.0.1.28 timeout x comment "text message 28"
-2.0.1.29 timeout x comment "text message 29"
-2.0.1.3 timeout x comment "text message 3"
-2.0.1.30 timeout x comment "text message 30"
-2.0.1.31 timeout x comment "text message 31"
-2.0.1.32 timeout x comment "text message 32"
-2.0.1.33 timeout x comment "text message 33"
-2.0.1.34 timeout x comment "text message 34"
-2.0.1.35 timeout x comment "text message 35"
-2.0.1.36 timeout x comment "text message 36"
-2.0.1.37 timeout x comment "text message 37"
-2.0.1.38 timeout x comment "text message 38"
-2.0.1.39 timeout x comment "text message 39"
-2.0.1.4 timeout x comment "text message 4"
-2.0.1.40 timeout x comment "text message 40"
-2.0.1.41 timeout x comment "text message 41"
-2.0.1.42 timeout x comment "text message 42"
-2.0.1.43 timeout x comment "text message 43"
-2.0.1.44 timeout x comment "text message 44"
-2.0.1.45 timeout x comment "text message 45"
-2.0.1.46 timeout x comment "text message 46"
-2.0.1.47 timeout x comment "text message 47"
-2.0.1.48 timeout x comment "text message 48"
-2.0.1.49 timeout x comment "text message 49"
-2.0.1.5 timeout x comment "text message 5"
-2.0.1.50 timeout x comment "text message 50"
-2.0.1.51 timeout x comment "text message 51"
-2.0.1.52 timeout x comment "text message 52"
-2.0.1.53 timeout x comment "text message 53"
-2.0.1.54 timeout x comment "text message 54"
-2.0.1.55 timeout x comment "text message 55"
-2.0.1.56 timeout x comment "text message 56"
-2.0.1.57 timeout x comment "text message 57"
-2.0.1.58 timeout x comment "text message 58"
-2.0.1.59 timeout x comment "text message 59"
-2.0.1.6 timeout x comment "text message 6"
-2.0.1.60 timeout x comment "text message 60"
-2.0.1.61 timeout x comment "text message 61"
-2.0.1.62 timeout x comment "text message 62"
-2.0.1.63 timeout x comment "text message 63"
-2.0.1.64 timeout x comment "text message 64"
-2.0.1.65 timeout x comment "text message 65"
-2.0.1.66 timeout x comment "text message 66"
-2.0.1.67 timeout x comment "text message 67"
-2.0.1.68 timeout x comment "text message 68"
-2.0.1.69 timeout x comment "text message 69"
-2.0.1.7 timeout x comment "text message 7"
-2.0.1.70 timeout x comment "text message 70"
-2.0.1.71 timeout x comment "text message 71"
-2.0.1.72 timeout x comment "text message 72"
-2.0.1.73 timeout x comment "text message 73"
-2.0.1.74 timeout x comment "text message 74"
-2.0.1.75 timeout x comment "text message 75"
-2.0.1.76 timeout x comment "text message 76"
-2.0.1.77 timeout x comment "text message 77"
-2.0.1.78 timeout x comment "text message 78"
-2.0.1.79 timeout x comment "text message 79"
-2.0.1.8 timeout x comment "text message 8"
-2.0.1.80 timeout x comment "text message 80"
-2.0.1.81 timeout x comment "text message 81"
-2.0.1.82 timeout x comment "text message 82"
-2.0.1.83 timeout x comment "text message 83"
-2.0.1.84 timeout x comment "text message 84"
-2.0.1.85 timeout x comment "text message 85"
-2.0.1.86 timeout x comment "text message 86"
-2.0.1.87 timeout x comment "text message 87"
-2.0.1.88 timeout x comment "text message 88"
-2.0.1.89 timeout x comment "text message 89"
-2.0.1.9 timeout x comment "text message 9"
-2.0.1.90 timeout x comment "text message 90"
-2.0.1.91 timeout x comment "text message 91"
-2.0.1.92 timeout x comment "text message 92"
-2.0.1.93 timeout x comment "text message 93"
-2.0.1.94 timeout x comment "text message 94"
-2.0.1.95 timeout x comment "text message 95"
-2.0.1.96 timeout x comment "text message 96"
-2.0.1.97 timeout x comment "text message 97"
-2.0.1.98 timeout x comment "text message 98"
-2.0.1.99 timeout x comment "text message 99"
+2.0.1.0 timeout 0 comment "text message 0"
+2.0.1.1 timeout 0 comment "text message 1"
+2.0.1.10 timeout 0 comment "text message 10"
+2.0.1.100 timeout 0 comment "text message 100"
+2.0.1.101 timeout 0 comment "text message 101"
+2.0.1.102 timeout 0 comment "text message 102"
+2.0.1.103 timeout 0 comment "text message 103"
+2.0.1.104 timeout 0 comment "text message 104"
+2.0.1.105 timeout 0 comment "text message 105"
+2.0.1.106 timeout 0 comment "text message 106"
+2.0.1.107 timeout 0 comment "text message 107"
+2.0.1.108 timeout 0 comment "text message 108"
+2.0.1.109 timeout 0 comment "text message 109"
+2.0.1.11 timeout 0 comment "text message 11"
+2.0.1.110 timeout 0 comment "text message 110"
+2.0.1.111 timeout 0 comment "text message 111"
+2.0.1.112 timeout 0 comment "text message 112"
+2.0.1.113 timeout 0 comment "text message 113"
+2.0.1.114 timeout 0 comment "text message 114"
+2.0.1.115 timeout 0 comment "text message 115"
+2.0.1.116 timeout 0 comment "text message 116"
+2.0.1.117 timeout 0 comment "text message 117"
+2.0.1.118 timeout 0 comment "text message 118"
+2.0.1.119 timeout 0 comment "text message 119"
+2.0.1.12 timeout 0 comment "text message 12"
+2.0.1.120 timeout 0 comment "text message 120"
+2.0.1.121 timeout 0 comment "text message 121"
+2.0.1.122 timeout 0 comment "text message 122"
+2.0.1.123 timeout 0 comment "text message 123"
+2.0.1.124 timeout 0 comment "text message 124"
+2.0.1.125 timeout 0 comment "text message 125"
+2.0.1.126 timeout 0 comment "text message 126"
+2.0.1.127 timeout 0 comment "text message 127"
+2.0.1.128 timeout 0 comment "text message 128"
+2.0.1.129 timeout 0 comment "text message 129"
+2.0.1.13 timeout 0 comment "text message 13"
+2.0.1.130 timeout 0 comment "text message 130"
+2.0.1.131 timeout 0 comment "text message 131"
+2.0.1.132 timeout 0 comment "text message 132"
+2.0.1.133 timeout 0 comment "text message 133"
+2.0.1.134 timeout 0 comment "text message 134"
+2.0.1.135 timeout 0 comment "text message 135"
+2.0.1.136 timeout 0 comment "text message 136"
+2.0.1.137 timeout 0 comment "text message 137"
+2.0.1.138 timeout 0 comment "text message 138"
+2.0.1.139 timeout 0 comment "text message 139"
+2.0.1.14 timeout 0 comment "text message 14"
+2.0.1.140 timeout 0 comment "text message 140"
+2.0.1.141 timeout 0 comment "text message 141"
+2.0.1.142 timeout 0 comment "text message 142"
+2.0.1.143 timeout 0 comment "text message 143"
+2.0.1.144 timeout 0 comment "text message 144"
+2.0.1.145 timeout 0 comment "text message 145"
+2.0.1.146 timeout 0 comment "text message 146"
+2.0.1.147 timeout 0 comment "text message 147"
+2.0.1.148 timeout 0 comment "text message 148"
+2.0.1.149 timeout 0 comment "text message 149"
+2.0.1.15 timeout 0 comment "text message 15"
+2.0.1.150 timeout 0 comment "text message 150"
+2.0.1.151 timeout 0 comment "text message 151"
+2.0.1.152 timeout 0 comment "text message 152"
+2.0.1.153 timeout 0 comment "text message 153"
+2.0.1.154 timeout 0 comment "text message 154"
+2.0.1.155 timeout 0 comment "text message 155"
+2.0.1.156 timeout 0 comment "text message 156"
+2.0.1.157 timeout 0 comment "text message 157"
+2.0.1.158 timeout 0 comment "text message 158"
+2.0.1.159 timeout 0 comment "text message 159"
+2.0.1.16 timeout 0 comment "text message 16"
+2.0.1.160 timeout 0 comment "text message 160"
+2.0.1.161 timeout 0 comment "text message 161"
+2.0.1.162 timeout 0 comment "text message 162"
+2.0.1.163 timeout 0 comment "text message 163"
+2.0.1.164 timeout 0 comment "text message 164"
+2.0.1.165 timeout 0 comment "text message 165"
+2.0.1.166 timeout 0 comment "text message 166"
+2.0.1.167 timeout 0 comment "text message 167"
+2.0.1.168 timeout 0 comment "text message 168"
+2.0.1.169 timeout 0 comment "text message 169"
+2.0.1.17 timeout 0 comment "text message 17"
+2.0.1.170 timeout 0 comment "text message 170"
+2.0.1.171 timeout 0 comment "text message 171"
+2.0.1.172 timeout 0 comment "text message 172"
+2.0.1.173 timeout 0 comment "text message 173"
+2.0.1.174 timeout 0 comment "text message 174"
+2.0.1.175 timeout 0 comment "text message 175"
+2.0.1.176 timeout 0 comment "text message 176"
+2.0.1.177 timeout 0 comment "text message 177"
+2.0.1.178 timeout 0 comment "text message 178"
+2.0.1.179 timeout 0 comment "text message 179"
+2.0.1.18 timeout 0 comment "text message 18"
+2.0.1.180 timeout 0 comment "text message 180"
+2.0.1.181 timeout 0 comment "text message 181"
+2.0.1.182 timeout 0 comment "text message 182"
+2.0.1.183 timeout 0 comment "text message 183"
+2.0.1.184 timeout 0 comment "text message 184"
+2.0.1.185 timeout 0 comment "text message 185"
+2.0.1.186 timeout 0 comment "text message 186"
+2.0.1.187 timeout 0 comment "text message 187"
+2.0.1.188 timeout 0 comment "text message 188"
+2.0.1.189 timeout 0 comment "text message 189"
+2.0.1.19 timeout 0 comment "text message 19"
+2.0.1.190 timeout 0 comment "text message 190"
+2.0.1.191 timeout 0 comment "text message 191"
+2.0.1.192 timeout 0 comment "text message 192"
+2.0.1.193 timeout 0 comment "text message 193"
+2.0.1.194 timeout 0 comment "text message 194"
+2.0.1.195 timeout 0 comment "text message 195"
+2.0.1.196 timeout 0 comment "text message 196"
+2.0.1.197 timeout 0 comment "text message 197"
+2.0.1.198 timeout 0 comment "text message 198"
+2.0.1.199 timeout 0 comment "text message 199"
+2.0.1.2 timeout 0 comment "text message 2"
+2.0.1.20 timeout 0 comment "text message 20"
+2.0.1.200 timeout 0 comment "text message 200"
+2.0.1.201 timeout 0 comment "text message 201"
+2.0.1.202 timeout 0 comment "text message 202"
+2.0.1.203 timeout 0 comment "text message 203"
+2.0.1.204 timeout 0 comment "text message 204"
+2.0.1.205 timeout 0 comment "text message 205"
+2.0.1.206 timeout 0 comment "text message 206"
+2.0.1.207 timeout 0 comment "text message 207"
+2.0.1.208 timeout 0 comment "text message 208"
+2.0.1.209 timeout 0 comment "text message 209"
+2.0.1.21 timeout 0 comment "text message 21"
+2.0.1.210 timeout 0 comment "text message 210"
+2.0.1.211 timeout 0 comment "text message 211"
+2.0.1.212 timeout 0 comment "text message 212"
+2.0.1.213 timeout 0 comment "text message 213"
+2.0.1.214 timeout 0 comment "text message 214"
+2.0.1.215 timeout 0 comment "text message 215"
+2.0.1.216 timeout 0 comment "text message 216"
+2.0.1.217 timeout 0 comment "text message 217"
+2.0.1.218 timeout 0 comment "text message 218"
+2.0.1.219 timeout 0 comment "text message 219"
+2.0.1.22 timeout 0 comment "text message 22"
+2.0.1.220 timeout 0 comment "text message 220"
+2.0.1.221 timeout 0 comment "text message 221"
+2.0.1.222 timeout 0 comment "text message 222"
+2.0.1.223 timeout 0 comment "text message 223"
+2.0.1.224 timeout 0 comment "text message 224"
+2.0.1.225 timeout 0 comment "text message 225"
+2.0.1.226 timeout 0 comment "text message 226"
+2.0.1.227 timeout 0 comment "text message 227"
+2.0.1.228 timeout 0 comment "text message 228"
+2.0.1.229 timeout 0 comment "text message 229"
+2.0.1.23 timeout 0 comment "text message 23"
+2.0.1.230 timeout 0 comment "text message 230"
+2.0.1.231 timeout 0 comment "text message 231"
+2.0.1.232 timeout 0 comment "text message 232"
+2.0.1.233 timeout 0 comment "text message 233"
+2.0.1.234 timeout 0 comment "text message 234"
+2.0.1.235 timeout 0 comment "text message 235"
+2.0.1.236 timeout 0 comment "text message 236"
+2.0.1.237 timeout 0 comment "text message 237"
+2.0.1.238 timeout 0 comment "text message 238"
+2.0.1.239 timeout 0 comment "text message 239"
+2.0.1.24 timeout 0 comment "text message 24"
+2.0.1.240 timeout 0 comment "text message 240"
+2.0.1.241 timeout 0 comment "text message 241"
+2.0.1.242 timeout 0 comment "text message 242"
+2.0.1.243 timeout 0 comment "text message 243"
+2.0.1.244 timeout 0 comment "text message 244"
+2.0.1.245 timeout 0 comment "text message 245"
+2.0.1.246 timeout 0 comment "text message 246"
+2.0.1.247 timeout 0 comment "text message 247"
+2.0.1.248 timeout 0 comment "text message 248"
+2.0.1.249 timeout 0 comment "text message 249"
+2.0.1.25 timeout 0 comment "text message 25"
+2.0.1.250 timeout 0 comment "text message 250"
+2.0.1.251 timeout 0 comment "text message 251"
+2.0.1.252 timeout 0 comment "text message 252"
+2.0.1.253 timeout 0 comment "text message 253"
+2.0.1.254 timeout 0 comment "text message 254"
+2.0.1.255 timeout 0 comment "text message 255"
+2.0.1.26 timeout 0 comment "text message 26"
+2.0.1.27 timeout 0 comment "text message 27"
+2.0.1.28 timeout 0 comment "text message 28"
+2.0.1.29 timeout 0 comment "text message 29"
+2.0.1.3 timeout 0 comment "text message 3"
+2.0.1.30 timeout 0 comment "text message 30"
+2.0.1.31 timeout 0 comment "text message 31"
+2.0.1.32 timeout 0 comment "text message 32"
+2.0.1.33 timeout 0 comment "text message 33"
+2.0.1.34 timeout 0 comment "text message 34"
+2.0.1.35 timeout 0 comment "text message 35"
+2.0.1.36 timeout 0 comment "text message 36"
+2.0.1.37 timeout 0 comment "text message 37"
+2.0.1.38 timeout 0 comment "text message 38"
+2.0.1.39 timeout 0 comment "text message 39"
+2.0.1.4 timeout 0 comment "text message 4"
+2.0.1.40 timeout 0 comment "text message 40"
+2.0.1.41 timeout 0 comment "text message 41"
+2.0.1.42 timeout 0 comment "text message 42"
+2.0.1.43 timeout 0 comment "text message 43"
+2.0.1.44 timeout 0 comment "text message 44"
+2.0.1.45 timeout 0 comment "text message 45"
+2.0.1.46 timeout 0 comment "text message 46"
+2.0.1.47 timeout 0 comment "text message 47"
+2.0.1.48 timeout 0 comment "text message 48"
+2.0.1.49 timeout 0 comment "text message 49"
+2.0.1.5 timeout 0 comment "text message 5"
+2.0.1.50 timeout 0 comment "text message 50"
+2.0.1.51 timeout 0 comment "text message 51"
+2.0.1.52 timeout 0 comment "text message 52"
+2.0.1.53 timeout 0 comment "text message 53"
+2.0.1.54 timeout 0 comment "text message 54"
+2.0.1.55 timeout 0 comment "text message 55"
+2.0.1.56 timeout 0 comment "text message 56"
+2.0.1.57 timeout 0 comment "text message 57"
+2.0.1.58 timeout 0 comment "text message 58"
+2.0.1.59 timeout 0 comment "text message 59"
+2.0.1.6 timeout 0 comment "text message 6"
+2.0.1.60 timeout 0 comment "text message 60"
+2.0.1.61 timeout 0 comment "text message 61"
+2.0.1.62 timeout 0 comment "text message 62"
+2.0.1.63 timeout 0 comment "text message 63"
+2.0.1.64 timeout 0 comment "text message 64"
+2.0.1.65 timeout 0 comment "text message 65"
+2.0.1.66 timeout 0 comment "text message 66"
+2.0.1.67 timeout 0 comment "text message 67"
+2.0.1.68 timeout 0 comment "text message 68"
+2.0.1.69 timeout 0 comment "text message 69"
+2.0.1.7 timeout 0 comment "text message 7"
+2.0.1.70 timeout 0 comment "text message 70"
+2.0.1.71 timeout 0 comment "text message 71"
+2.0.1.72 timeout 0 comment "text message 72"
+2.0.1.73 timeout 0 comment "text message 73"
+2.0.1.74 timeout 0 comment "text message 74"
+2.0.1.75 timeout 0 comment "text message 75"
+2.0.1.76 timeout 0 comment "text message 76"
+2.0.1.77 timeout 0 comment "text message 77"
+2.0.1.78 timeout 0 comment "text message 78"
+2.0.1.79 timeout 0 comment "text message 79"
+2.0.1.8 timeout 0 comment "text message 8"
+2.0.1.80 timeout 0 comment "text message 80"
+2.0.1.81 timeout 0 comment "text message 81"
+2.0.1.82 timeout 0 comment "text message 82"
+2.0.1.83 timeout 0 comment "text message 83"
+2.0.1.84 timeout 0 comment "text message 84"
+2.0.1.85 timeout 0 comment "text message 85"
+2.0.1.86 timeout 0 comment "text message 86"
+2.0.1.87 timeout 0 comment "text message 87"
+2.0.1.88 timeout 0 comment "text message 88"
+2.0.1.89 timeout 0 comment "text message 89"
+2.0.1.9 timeout 0 comment "text message 9"
+2.0.1.90 timeout 0 comment "text message 90"
+2.0.1.91 timeout 0 comment "text message 91"
+2.0.1.92 timeout 0 comment "text message 92"
+2.0.1.93 timeout 0 comment "text message 93"
+2.0.1.94 timeout 0 comment "text message 94"
+2.0.1.95 timeout 0 comment "text message 95"
+2.0.1.96 timeout 0 comment "text message 96"
+2.0.1.97 timeout 0 comment "text message 97"
+2.0.1.98 timeout 0 comment "text message 98"
+2.0.1.99 timeout 0 comment "text message 99"
diff --git a/tests/comment.t.list3 b/tests/comment.t.list3
index 673678a..b6eab32 100644
--- a/tests/comment.t.list3
+++ b/tests/comment.t.list3
@@ -1,31 +1,35 @@
Name: a
Type: hash:ip
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 152
+Revision: 5
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xe2558329
+Size in memory: 336
References: 1
Number of entries: 0
Members:
Name: b
Type: hash:ip
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 152
+Revision: 5
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x0dfa7d5d
+Size in memory: 336
References: 1
Number of entries: 0
Members:
Name: c
Type: hash:ip
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 152
+Revision: 5
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x8fada201
+Size in memory: 336
References: 1
Number of entries: 0
Members:
Name: test
Type: list:set
+Revision: 3
Header: size 8 comment
-Size in memory: 288
+Size in memory: 378
References: 0
Number of entries: 3
Members:
diff --git a/tests/diff.sh b/tests/diff.sh
new file mode 100755
index 0000000..a364a28
--- /dev/null
+++ b/tests/diff.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+diff -u -I 'Revision: .*' -I 'Size in memory.*' \
+ <(sed -e 's/timeout [0-9]*/timeout x/' -e 's/initval 0x[0-9a-fA-F]\{8\}/initval 0x00000000/' $1) \
+ <(sed -e 's/timeout [0-9]*/timeout x/' -e 's/initval 0x[0-9a-fA-F]\{8\}/initval 0x00000000/' $2)
+
+
diff --git a/tests/hash:ip,mark.t b/tests/hash:ip,mark.t
index 9c51201..ce94efc 100644
--- a/tests/hash:ip,mark.t
+++ b/tests/hash:ip,mark.t
@@ -27,15 +27,15 @@
# Try to add value after second random value
0 ipset add test 2.1.0.1,0x80
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip,mark.t.list0
+0 ./diff.sh .foo hash:ip,mark.t.list0
# Sleep 5s so that elements can time out
0 sleep 5
# List set
-0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip,mark.t.list1
+0 ./diff.sh .foo hash:ip,mark.t.list1
# Flush test set
0 ipset flush test
# Add multiple elements in one step
diff --git a/tests/hash:ip,mark.t.list0 b/tests/hash:ip,mark.t.list0
index 3866bf5..1df024f 100644
--- a/tests/hash:ip,mark.t.list0
+++ b/tests/hash:ip,mark.t.list0
@@ -1,11 +1,12 @@
Name: test
Type: hash:ip,mark
-Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 timeout x
-Size in memory: 640
+Revision: 3
+Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x30edb64c
+Size in memory: 592
References: 0
Number of entries: 4
Members:
-2.0.0.0,0x00000005 timeout x
-2.0.0.1,0x00000005 timeout x
-2.1.0.0,0x00000080 timeout x
-2.1.0.1,0x00000080 timeout x
+2.0.0.0,0x00000005 timeout 3
+2.0.0.1,0x00000005 timeout 3
+2.1.0.0,0x00000080 timeout 3
+2.1.0.1,0x00000080 timeout 3
diff --git a/tests/hash:ip,mark.t.list1 b/tests/hash:ip,mark.t.list1
index c959e4c..34fafcc 100644
--- a/tests/hash:ip,mark.t.list1
+++ b/tests/hash:ip,mark.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,mark
-Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4
-Size in memory: 536
+Revision: 3
+Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x139cd632
+Size in memory: 592
References: 0
Number of entries: 0
Members:
diff --git a/tests/hash:ip,port,ip.t b/tests/hash:ip,port,ip.t
index 8a6954e..fcd6985 100644
--- a/tests/hash:ip,port,ip.t
+++ b/tests/hash:ip,port,ip.t
@@ -35,15 +35,15 @@
# Try to add value after second random value
0 ipset add test 2.1.0.1,128,2.2.2.2
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip,port,ip.t.list0
+0 ./diff.sh .foo hash:ip,port,ip.t.list0
# Sleep 5s so that elements can time out
0 sleep 5
# List set
-0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip,port,ip.t.list1
+0 ./diff.sh .foo hash:ip,port,ip.t.list1
# Flush test set
0 ipset flush test
# Add multiple elements in one step
diff --git a/tests/hash:ip,port,ip.t.list0 b/tests/hash:ip,port,ip.t.list0
index 57adef1..f34c24a 100644
--- a/tests/hash:ip,port,ip.t.list0
+++ b/tests/hash:ip,port,ip.t.list0
@@ -1,11 +1,12 @@
Name: test
Type: hash:ip,port,ip
-Header: family inet hashsize 1024 maxelem 65536 timeout x
-Size in memory: 840
+Revision: 6
+Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x7713f039
+Size in memory: 664
References: 0
Number of entries: 4
Members:
-2.0.0.0,tcp:5,1.1.1.1 timeout x
-2.0.0.1,tcp:5,1.1.1.1 timeout x
-2.1.0.0,tcp:128,2.2.2.2 timeout x
-2.1.0.1,tcp:128,2.2.2.2 timeout x
+2.0.0.0,tcp:5,1.1.1.1 timeout 3
+2.0.0.1,tcp:5,1.1.1.1 timeout 3
+2.1.0.0,tcp:128,2.2.2.2 timeout 3
+2.1.0.1,tcp:128,2.2.2.2 timeout 3
diff --git a/tests/hash:ip,port,ip.t.list1 b/tests/hash:ip,port,ip.t.list1
index 7c7d560..e81e0ec 100644
--- a/tests/hash:ip,port,ip.t.list1
+++ b/tests/hash:ip,port,ip.t.list1
@@ -1,6 +1,7 @@
Name: test
Type: hash:ip,port,ip
-Header: family inet hashsize 1024 maxelem 65536 timeout 4
+Revision: 6
+Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x87fc0d22
Size in memory: 664
References: 0
Number of entries: 0
diff --git a/tests/hash:ip,port,net.t b/tests/hash:ip,port,net.t
index 487f563..67d20b0 100644
--- a/tests/hash:ip,port,net.t
+++ b/tests/hash:ip,port,net.t
@@ -27,9 +27,9 @@
# Try to add value after second random value
0 ipset add test 2.1.0.1,128,10.0.0.0/17
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip,port,net.t.list0
+0 ./diff.sh .foo hash:ip,port,net.t.list0
# Sleep 5s so that elements can time out
0 sleep 5
# List set
diff --git a/tests/hash:ip,port,net.t.list0 b/tests/hash:ip,port,net.t.list0
index 44c53c5..45ab21c 100644
--- a/tests/hash:ip,port,net.t.list0
+++ b/tests/hash:ip,port,net.t.list0
@@ -1,11 +1,12 @@
Name: test
Type: hash:ip,port,net
-Header: family inet hashsize 1024 maxelem 65536 timeout x
-Size in memory: 1096
+Revision: 8
+Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x882e1e10
+Size in memory: 920
References: 0
Number of entries: 4
Members:
-2.0.0.0,tcp:5,192.168.0.0/25 timeout x
-2.0.0.1,tcp:5,192.168.0.0/24 timeout x
-2.1.0.0,tcp:128,10.0.0.0/16 timeout x
-2.1.0.1,tcp:128,10.0.0.0/17 timeout x
+2.0.0.0,tcp:5,192.168.0.0/25 timeout 3
+2.0.0.1,tcp:5,192.168.0.0/24 timeout 3
+2.1.0.0,tcp:128,10.0.0.0/16 timeout 3
+2.1.0.1,tcp:128,10.0.0.0/17 timeout 3
diff --git a/tests/hash:ip,port.t b/tests/hash:ip,port.t
index aba8fdc..f65fb59 100644
--- a/tests/hash:ip,port.t
+++ b/tests/hash:ip,port.t
@@ -31,15 +31,15 @@
# Delete port by number
0 ipset del test 2.1.0.3,25
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip,port.t.list0
+0 ./diff.sh .foo hash:ip,port.t.list0
# Sleep 5s so that elements can time out
0 sleep 5
# List set
-0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip,port.t.list1
+0 ./diff.sh .foo hash:ip,port.t.list1
# Flush test set
0 ipset flush test
# Add multiple elements in one step
@@ -62,10 +62,10 @@
0 ipset test test 2.0.0.1,tcp:80
# Test element with UDP protocol
0 ipset test test 2.0.0.1,udp:80
-# Add element with vrrp
-0 ipset add test 2.0.0.1,vrrp:0
-# Test element with vrrp
-0 ipset test test 2.0.0.1,vrrp:0
+# Add element with GRE
+0 ipset add test 2.0.0.1,gre:0
+# Test element with GRE
+0 ipset test test 2.0.0.1,gre:0
# Add element with sctp
0 ipset add test 2.0.0.1,sctp:80
# Test element with sctp
@@ -73,9 +73,9 @@
# Delete element with sctp
0 ipset del test 2.0.0.1,sctp:80
# List set
-0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip,port.t.list2
+0 ./diff.sh .foo hash:ip,port.t.list2
# Delete set
0 ipset destroy test
# Create set to add a range
@@ -170,4 +170,122 @@
0 ./check_extensions test 2.0.0.20 700 13 12479
# Counters and timeout: destroy set
0 ipset x test
+# Network: Create a set with timeout and netmask
+0 ipset -N test hash:ip,port --hashsize 128 --netmask 24 timeout 4
+# Network: Add zero valued element
+1 ipset -A test 0.0.0.0,80
+# Network: Test zero valued element
+1 ipset -T test 0.0.0.0,80
+# Network: Delete zero valued element
+1 ipset -D test 0.0.0.0,80
+# Network: Add first random network
+0 ipset -A test 2.0.0.1,8080
+# Network: Add second random network
+0 ipset -A test 192.168.68.69,22
+# Network: Test first random value
+0 ipset -T test 2.0.0.255,8080
+# Network: Test second random value
+0 ipset -T test 192.168.68.95,22
+# Network: Test value not added to the set
+1 ipset -T test 2.0.1.0,8080
+# Network: Add third element
+0 ipset -A test 200.100.10.1,22 timeout 0
+# Network: Add third random network
+0 ipset -A test 200.100.0.12,22
+# Network: Delete the same network
+0 ipset -D test 200.100.0.12,22
+# Network: List set
+0 ipset -L test > .foo0 && ./sort.sh .foo0
+# Network: Check listing
+0 ./diff.sh .foo hash:ip,port.t.list3
+# Sleep 5s so that elements can time out
+0 sleep 5
+# Network: List set
+0 ipset -L test > .foo
+# Network: Check listing
+0 ./diff.sh .foo hash:ip,port.t.list4
+# Network: Flush test set
+0 ipset -F test
+# Network: add element with 1s timeout
+0 ipset add test 200.100.0.12,80 timeout 1
+# Network: readd element with 3s timeout
+0 ipset add test 200.100.0.12,80 timeout 3 -exist
+# Network: sleep 2s
+0 sleep 2s
+# Network: check readded element
+0 ipset test test 200.100.0.12,80
+# Network: Delete test set
+0 ipset -X test
+# Network: Create a set with timeout and bitmask
+0 ipset -N test hash:ip,port --hashsize 128 --bitmask 255.255.255.0 timeout 4
+# Network: Add zero valued element
+1 ipset -A test 0.0.0.0,80
+# Network: Test zero valued element
+1 ipset -T test 0.0.0.0,80
+# Network: Delete zero valued element
+1 ipset -D test 0.0.0.0,80
+# Network: Add first random network
+0 ipset -A test 2.0.0.1,8080
+# Network: Add second random network
+0 ipset -A test 192.168.68.69,22
+# Network: Test first random value
+0 ipset -T test 2.0.0.255,8080
+# Network: Test second random value
+0 ipset -T test 192.168.68.95,22
+# Network: Test value not added to the set
+1 ipset -T test 2.0.1.0,8080
+# Network: Add third element
+0 ipset -A test 200.100.10.1,22 timeout 0
+# Network: Add third random network
+0 ipset -A test 200.100.0.12,22
+# Network: Delete the same network
+0 ipset -D test 200.100.0.12,22
+# Network: List set
+0 ipset -L test > .foo0 && ./sort.sh .foo0
+# Network: Check listing
+0 ./diff.sh .foo hash:ip,port.t.list5
+# Sleep 5s so that elements can time out
+0 sleep 5
+# Network: List set
+0 ipset -L test > .foo
+# Network: Check listing
+0 ./diff.sh .foo hash:ip,port.t.list6
+# Network: Flush test set
+0 ipset -F test
+# Network: add element with 1s timeout
+0 ipset add test 200.100.0.12,80 timeout 1
+# Network: readd element with 3s timeout
+0 ipset add test 200.100.0.12,80 timeout 3 -exist
+# Network: sleep 2s
+0 sleep 2s
+# Network: check readded element
+0 ipset test test 200.100.0.12,80
+# Network: Delete test set
+0 ipset -X test
+# Network: Create a set with bitmask which is not a valid netmask
+0 ipset -N test hash:ip,port --hashsize 128 --bitmask 255.255.0.255
+# Network: Add zero valued element
+1 ipset -A test 0.0.0.0
+# Network: Test zero valued element
+1 ipset -T test 0.0.0.0
+# Network: Delete zero valued element
+1 ipset -D test 0.0.0.0
+# Network: Add first random network
+0 ipset -A test 1.2.3.4,22
+# Network: Add second random network
+0 ipset -A test 1.168.122.124,22
+# Network: Test first random value
+0 ipset -T test 1.2.9.4,22
+# Network: Test second random value
+0 ipset -T test 1.168.68.124,22
+# Network: Test value not added to the set
+1 ipset -T test 2.0.1.0,23
+# Network: Test delete value
+0 ipset -D test 1.168.0.124,22
+# Network: List set
+0 ipset -L test > .foo
+# Network: Check listing
+0 ./diff.sh .foo hash:ip,port.t.list7
+# Network: Delete test set
+0 ipset -X test
# eof
diff --git a/tests/hash:ip,port.t.list0 b/tests/hash:ip,port.t.list0
index 49e3033..b1541f5 100644
--- a/tests/hash:ip,port.t.list0
+++ b/tests/hash:ip,port.t.list0
@@ -1,11 +1,12 @@
Name: test
Type: hash:ip,port
-Header: family inet hashsize 1024 maxelem 65536 timeout x
-Size in memory: 640
+Revision: 6
+Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0xf8e65168
+Size in memory: 592
References: 0
Number of entries: 4
Members:
-2.0.0.0,tcp:5 timeout x
-2.0.0.1,tcp:5 timeout x
-2.1.0.0,tcp:128 timeout x
-2.1.0.1,tcp:128 timeout x
+2.0.0.0,tcp:5 timeout 3
+2.0.0.1,tcp:5 timeout 3
+2.1.0.0,tcp:128 timeout 3
+2.1.0.1,tcp:128 timeout 3
diff --git a/tests/hash:ip,port.t.list1 b/tests/hash:ip,port.t.list1
index 4b79124..4471ce6 100644
--- a/tests/hash:ip,port.t.list1
+++ b/tests/hash:ip,port.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,port
-Header: family inet hashsize 1024 maxelem 65536 timeout 4
-Size in memory: 528
+Revision: 6
+Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x881c5fa0
+Size in memory: 592
References: 0
Number of entries: 0
Members:
diff --git a/tests/hash:ip,port.t.list2 b/tests/hash:ip,port.t.list2
index 624d050..2550422 100644
--- a/tests/hash:ip,port.t.list2
+++ b/tests/hash:ip,port.t.list2
@@ -1,10 +1,11 @@
Name: test
Type: hash:ip,port
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 320
+Revision: 6
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x819addf6
+Size in memory: 480
References: 0
Number of entries: 3
Members:
+2.0.0.1,gre:0
2.0.0.1,tcp:80
2.0.0.1,udp:80
-2.0.0.1,vrrp:0
diff --git a/tests/hash:ip,port.t.list3 b/tests/hash:ip,port.t.list3
new file mode 100644
index 0000000..b2cdc28
--- /dev/null
+++ b/tests/hash:ip,port.t.list3
@@ -0,0 +1,11 @@
+Name: test
+Type: hash:ip,port
+Revision: 7
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xf49ba001 netmask 24
+Size in memory: 408
+References: 0
+Number of entries: 3
+Members:
+192.168.68.0,tcp:22 timeout 3
+2.0.0.0,tcp:8080 timeout 3
+200.100.10.0,tcp:22 timeout 0
diff --git a/tests/hash:ip,port.t.list4 b/tests/hash:ip,port.t.list4
new file mode 100644
index 0000000..c28987a
--- /dev/null
+++ b/tests/hash:ip,port.t.list4
@@ -0,0 +1,9 @@
+Name: test
+Type: hash:ip,port
+Revision: 7
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x18b2277a netmask 24
+Size in memory: 408
+References: 0
+Number of entries: 1
+Members:
+200.100.10.0,tcp:22 timeout 0
diff --git a/tests/hash:ip,port.t.list5 b/tests/hash:ip,port.t.list5
new file mode 100644
index 0000000..b5fa817
--- /dev/null
+++ b/tests/hash:ip,port.t.list5
@@ -0,0 +1,11 @@
+Name: test
+Type: hash:ip,port
+Revision: 7
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x6a0e903a bitmask 255.255.255.0
+Size in memory: 408
+References: 0
+Number of entries: 3
+Members:
+192.168.68.0,tcp:22 timeout 3
+2.0.0.0,tcp:8080 timeout 3
+200.100.10.0,tcp:22 timeout 0
diff --git a/tests/hash:ip,port.t.list6 b/tests/hash:ip,port.t.list6
new file mode 100644
index 0000000..33969cf
--- /dev/null
+++ b/tests/hash:ip,port.t.list6
@@ -0,0 +1,9 @@
+Name: test
+Type: hash:ip,port
+Revision: 7
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x2fcffdca bitmask 255.255.255.0
+Size in memory: 408
+References: 0
+Number of entries: 1
+Members:
+200.100.10.0,tcp:22 timeout 0
diff --git a/tests/hash:ip,port.t.list7 b/tests/hash:ip,port.t.list7
new file mode 100644
index 0000000..f223657
--- /dev/null
+++ b/tests/hash:ip,port.t.list7
@@ -0,0 +1,9 @@
+Name: test
+Type: hash:ip,port
+Revision: 7
+Header: family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x98bdfa72 bitmask 255.255.0.255
+Size in memory: 312
+References: 0
+Number of entries: 1
+Members:
+1.2.0.4,tcp:22
diff --git a/tests/hash:ip.t b/tests/hash:ip.t
index 36b82f9..3771437 100644
--- a/tests/hash:ip.t
+++ b/tests/hash:ip.t
@@ -19,15 +19,15 @@
# IP: Delete the same value
0 ipset -D test 200.100.0.12
# IP: List set
-0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# IP: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip.t.list2
+0 ./diff.sh .foo hash:ip.t.list2
# Sleep 5s so that element can time out
0 sleep 5
# IP: List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# IP: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip.t.list0
+0 ./diff.sh .foo hash:ip.t.list0
# IP: Flush test set
0 ipset -F test
# IP: Add multiple elements in one step
@@ -72,7 +72,7 @@
0 n=`ipset list test|grep '^10.0'|wc -l` && test $n -eq 1024
# IP: Destroy sets
0 ipset -X
-# Network: Create a set with timeout
+# Network: Create a set with timeout and netmask
0 ipset -N test iphash --hashsize 128 --netmask 24 timeout 4
# Network: Add zero valued element
1 ipset -A test 0.0.0.0
@@ -97,15 +97,15 @@
# Network: Delete the same network
0 ipset -D test 200.100.0.12
# Network: List set
-0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Network: Check listing
-0 diff -u -I 'Size in memory.*' -I 'Size in memory.*' .foo hash:ip.t.list3
+0 ./diff.sh .foo hash:ip.t.list3
# Sleep 5s so that elements can time out
0 sleep 5
# Network: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Network: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip.t.list1
+0 ./diff.sh .foo hash:ip.t.list1
# Network: Flush test set
0 ipset -F test
# Network: add element with 1s timeout
@@ -136,6 +136,12 @@
0 ipset del test 10.0.0.1-10.0.0.10
# Range: Check number of elements
0 n=`ipset save test|wc -l` && test $n -eq 1
+# Range: Flush set
+0 ipset flush test
+# Range: Add elements in multiple internal batches
+0 ipset add test 10.1.0.0-10.1.64.255
+# Range: Check number of elements
+0 n=`ipset save test|grep '^add test 10.1' | wc -l` && test $n -eq 16640
# Range: Delete test set
0 ipset destroy test
# Timeout: Check that resizing keeps timeout values
@@ -210,4 +216,78 @@ skip which sendip
0 ./check_extensions test 10.255.255.64 600 6 $((6*40))
# Counters and timeout: destroy set
0 ipset x test
+# Network: Create a set with timeout and bitmask
+0 ipset -N test iphash --hashsize 128 --bitmask 255.255.255.0 timeout 4
+# Network: Add zero valued element
+1 ipset -A test 0.0.0.0
+# Network: Test zero valued element
+1 ipset -T test 0.0.0.0
+# Network: Delete zero valued element
+1 ipset -D test 0.0.0.0
+# Network: Add first random network
+0 ipset -A test 2.0.0.1
+# Network: Add second random network
+0 ipset -A test 192.168.68.69
+# Network: Test first random value
+0 ipset -T test 2.0.0.255
+# Network: Test second random value
+0 ipset -T test 192.168.68.95
+# Network: Test value not added to the set
+1 ipset -T test 2.0.1.0
+# Network: Add third element
+0 ipset -A test 200.100.10.1 timeout 0
+# Network: Add third random network
+0 ipset -A test 200.100.0.12
+# Network: Delete the same network
+0 ipset -D test 200.100.0.12
+# Network: List set
+0 ipset -L test > .foo0 && ./sort.sh .foo0
+# Network: Check listing
+0 ./diff.sh .foo hash:ip.t.list4
+# Sleep 5s so that elements can time out
+0 sleep 5
+# Network: List set
+0 ipset -L test > .foo
+# Network: Check listing
+0 ./diff.sh .foo hash:ip.t.list5
+# Network: Flush test set
+0 ipset -F test
+# Network: add element with 1s timeout
+0 ipset add test 200.100.0.12 timeout 1
+# Network: readd element with 3s timeout
+0 ipset add test 200.100.0.12 timeout 3 -exist
+# Network: sleep 2s
+0 sleep 2s
+# Network: check readded element
+0 ipset test test 200.100.0.12
+# Network: Delete test set
+0 ipset -X test
+# Network: Create a set with both bitmask and netmask
+1 ipset -N test iphash --hashsize 128 --bitmask 255.255.0.255 --netmask 24
+# Network: Create a set with bitmask which is not a valid netmask
+0 ipset -N test iphash --hashsize 128 --bitmask 255.255.0.255
+# Network: Add zero valued element
+1 ipset -A test 0.0.0.0
+# Network: Test zero valued element
+1 ipset -T test 0.0.0.0
+# Network: Delete zero valued element
+1 ipset -D test 0.0.0.0
+# Network: Add first random network
+0 ipset -A test 1.2.3.4
+# Network: Add second random network
+0 ipset -A test 1.2.4.5
+# Network: Test first random value
+0 ipset -T test 1.2.9.4
+# Network: Test second random value
+0 ipset -T test 1.2.9.5
+# Network: Test value not added to the set
+1 ipset -T test 2.0.1.0
+# Network: Test delete value
+0 ipset -D test 1.2.0.5
+# Network: List set
+0 ipset -L test > .foo
+# Network: Check listing
+0 ./diff.sh .foo hash:ip.t.list6
+# Network: Delete test set
+0 ipset -X test
# eof
diff --git a/tests/hash:ip.t.list0 b/tests/hash:ip.t.list0
index 1859015..efa642f 100644
--- a/tests/hash:ip.t.list0
+++ b/tests/hash:ip.t.list0
@@ -1,7 +1,7 @@
Name: test
Type: hash:ip
-Header: family inet hashsize 128 maxelem 65536 timeout 4
-Size in memory: 336
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x00000000
+Size in memory: 464
References: 0
Number of entries: 1
Members:
diff --git a/tests/hash:ip.t.list1 b/tests/hash:ip.t.list1
index 0977324..5b832d9 100644
--- a/tests/hash:ip.t.list1
+++ b/tests/hash:ip.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip
-Header: family inet hashsize 128 maxelem 65536 netmask 24 timeout 4
-Size in memory: 432
+Revision: 5
+Header: family inet hashsize 128 maxelem 65536 netmask 24 timeout 4 bucketsize 12 initval 0xbc66e38a
+Size in memory: 528
References: 0
Number of entries: 1
Members:
diff --git a/tests/hash:ip.t.list2 b/tests/hash:ip.t.list2
index 6cd2bf4..3198a72 100644
--- a/tests/hash:ip.t.list2
+++ b/tests/hash:ip.t.list2
@@ -1,9 +1,10 @@
Name: test
Type: hash:ip
-Header: family inet hashsize 128 maxelem 65536 timeout x
-Size in memory: 352
+Revision: 5
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x3723bb8f
+Size in memory: 464
References: 0
Number of entries: 2
Members:
-192.168.68.69 timeout x
-2.0.0.1 timeout x
+192.168.68.69 timeout 0
+2.0.0.1 timeout 3
diff --git a/tests/hash:ip.t.list3 b/tests/hash:ip.t.list3
index 500abbc..a68b731 100644
--- a/tests/hash:ip.t.list3
+++ b/tests/hash:ip.t.list3
@@ -1,10 +1,11 @@
Name: test
Type: hash:ip
-Header: family inet hashsize 128 maxelem 65536 netmask 24 timeout x
-Size in memory: 464
+Revision: 5
+Header: family inet hashsize 128 maxelem 65536 netmask 24 timeout 4 bucketsize 12 initval 0xfe970e91
+Size in memory: 528
References: 0
Number of entries: 3
Members:
-192.168.68.0 timeout x
-2.0.0.0 timeout x
-200.100.10.0 timeout x
+192.168.68.0 timeout 3
+2.0.0.0 timeout 3
+200.100.10.0 timeout 0
diff --git a/tests/hash:ip.t.list4 b/tests/hash:ip.t.list4
new file mode 100644
index 0000000..5f92afa
--- /dev/null
+++ b/tests/hash:ip.t.list4
@@ -0,0 +1,11 @@
+Name: test
+Type: hash:ip
+Revision: 5
+Header: family inet hashsize 128 maxelem 65536 bitmask 255.255.255.0 timeout 4 bucketsize 12 initval 0xfe970e91
+Size in memory: 528
+References: 0
+Number of entries: 3
+Members:
+192.168.68.0 timeout 3
+2.0.0.0 timeout 3
+200.100.10.0 timeout 0
diff --git a/tests/hash:ip.t.list5 b/tests/hash:ip.t.list5
new file mode 100644
index 0000000..9a29e75
--- /dev/null
+++ b/tests/hash:ip.t.list5
@@ -0,0 +1,9 @@
+Name: test
+Type: hash:ip
+Revision: 5
+Header: family inet hashsize 128 maxelem 65536 bitmask 255.255.255.0 timeout 4 bucketsize 12 initval 0xbc66e38a
+Size in memory: 528
+References: 0
+Number of entries: 1
+Members:
+200.100.10.0 timeout 0
diff --git a/tests/hash:ip.t.list6 b/tests/hash:ip.t.list6
new file mode 100644
index 0000000..44c5a49
--- /dev/null
+++ b/tests/hash:ip.t.list6
@@ -0,0 +1,9 @@
+Name: test
+Type: hash:ip
+Revision: 6
+Header: family inet hashsize 128 maxelem 65536 bitmask 255.255.0.255 bucketsize 12 initval 0xd7d821e1
+Size in memory: 296
+References: 0
+Number of entries: 1
+Members:
+1.2.0.4
diff --git a/tests/hash:ip6,mark.t b/tests/hash:ip6,mark.t
index 8f50acf..af46d97 100644
--- a/tests/hash:ip6,mark.t
+++ b/tests/hash:ip6,mark.t
@@ -27,15 +27,15 @@
# Try to add value after second random value
0 ipset add test 2:1:0::1,0x80
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6,mark.t.list0
+0 ./diff.sh .foo hash:ip6,mark.t.list0
# Sleep 5s so that elements can time out
0 sleep 5
# List set
-0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6,mark.t.list1
+0 ./diff.sh .foo hash:ip6,mark.t.list1
# Delete test set
0 ipset destroy test
# Create set to add a range
diff --git a/tests/hash:ip6,mark.t.list0 b/tests/hash:ip6,mark.t.list0
index be7c069..39a48f6 100644
--- a/tests/hash:ip6,mark.t.list0
+++ b/tests/hash:ip6,mark.t.list0
@@ -1,11 +1,12 @@
Name: test
Type: hash:ip,mark
-Header: family inet6 markmask 0xffffffff hashsize 1024 maxelem 65536 timeout x
-Size in memory: 1088
+Revision: 3
+Header: family inet6 markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x861e4c6a
+Size in memory: 736
References: 0
Number of entries: 4
Members:
-2:1::,0x00000080 timeout x
-2:1::1,0x00000080 timeout x
-2::,0x00000005 timeout x
-2::1,0x00000005 timeout x
+2:1::,0x00000080 timeout 3
+2:1::1,0x00000080 timeout 3
+2::,0x00000005 timeout 3
+2::1,0x00000005 timeout 3
diff --git a/tests/hash:ip6,mark.t.list1 b/tests/hash:ip6,mark.t.list1
index 5c7b730..b2c4dd2 100644
--- a/tests/hash:ip6,mark.t.list1
+++ b/tests/hash:ip6,mark.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,mark
-Header: family inet6 markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4
-Size in memory: 800
+Revision: 3
+Header: family inet6 markmask 0xffffffff hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x8e5240e7
+Size in memory: 736
References: 0
Number of entries: 0
Members:
diff --git a/tests/hash:ip6,port,ip6.t b/tests/hash:ip6,port,ip6.t
index e8a75f0..aaf6530 100644
--- a/tests/hash:ip6,port,ip6.t
+++ b/tests/hash:ip6,port,ip6.t
@@ -35,15 +35,15 @@
# Try to add value after second random value
0 ipset add test 2:1:0::1,128,2:2:2::2
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6,port,ip6.t.list0
+0 ./diff.sh .foo hash:ip6,port,ip6.t.list0
# Sleep 5s so that elements can time out
0 sleep 5
# List set
-0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6,port,ip6.t.list1
+0 ./diff.sh .foo hash:ip6,port,ip6.t.list1
# Flush test set
0 ipset flush test
# Add multiple elements in one step
diff --git a/tests/hash:ip6,port,ip6.t.list0 b/tests/hash:ip6,port,ip6.t.list0
index 6fc6771..a7aaced 100644
--- a/tests/hash:ip6,port,ip6.t.list0
+++ b/tests/hash:ip6,port,ip6.t.list0
@@ -1,12 +1,12 @@
Name: test
Type: hash:ip,port,ip
-Header: family inet6 hashsize 1024 maxelem 65536 timeout x
-Size in memory: 1608
+Revision: 6
+Header: family inet6 hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0xae2818a9
+Size in memory: 880
References: 0
-Size in memory: 9104
Number of entries: 4
Members:
-2:1::,tcp:128,2:2:2::2 timeout x
-2:1::1,tcp:128,2:2:2::2 timeout x
-2::,tcp:5,1:1:1::1 timeout x
-2::1,tcp:5,1:1:1::1 timeout x
+2:1::,tcp:128,2:2:2::2 timeout 3
+2:1::1,tcp:128,2:2:2::2 timeout 3
+2::,tcp:5,1:1:1::1 timeout 3
+2::1,tcp:5,1:1:1::1 timeout 3
diff --git a/tests/hash:ip6,port,ip6.t.list1 b/tests/hash:ip6,port,ip6.t.list1
index d3b61b7..1e735c1 100644
--- a/tests/hash:ip6,port,ip6.t.list1
+++ b/tests/hash:ip6,port,ip6.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,port,ip
-Header: family inet6 hashsize 1024 maxelem 65536 timeout 4
-Size in memory: 1072
+Revision: 6
+Header: family inet6 hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0xb9a9f4a5
+Size in memory: 880
References: 0
Number of entries: 0
Members:
diff --git a/tests/hash:ip6,port,net6.t b/tests/hash:ip6,port,net6.t
index 23a5da0..71dfa61 100644
--- a/tests/hash:ip6,port,net6.t
+++ b/tests/hash:ip6,port,net6.t
@@ -35,9 +35,9 @@
# Range: Try to add value after second random value
0 ipset -A test 2:1:0::1,128,2:2:2::2/12
# Range: List set
-0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Range: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6,port,net6.t.list0
+0 ./diff.sh .foo hash:ip6,port,net6.t.list0
# Range: Flush test set
0 ipset -F test
# Range: Delete test set
diff --git a/tests/hash:ip6,port,net6.t.list0 b/tests/hash:ip6,port,net6.t.list0
index ad8ea8f..3e92bee 100644
--- a/tests/hash:ip6,port,net6.t.list0
+++ b/tests/hash:ip6,port,net6.t.list0
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,port,net
-Header: family inet6 hashsize 1024 maxelem 65536
-Size in memory: 1864
+Revision: 8
+Header: family inet6 hashsize 1024 maxelem 65536 bucketsize 12 initval 0xa5d3d0fa
+Size in memory: 1808
References: 0
Number of entries: 4
Members:
diff --git a/tests/hash:ip6,port.t b/tests/hash:ip6,port.t
index a47ca6e..e56e39c 100644
--- a/tests/hash:ip6,port.t
+++ b/tests/hash:ip6,port.t
@@ -27,15 +27,15 @@
# Try to add value after second random value
0 ipset add test 2:1:0::1,128
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6,port.t.list0
+0 ./diff.sh .foo hash:ip6,port.t.list0
# Sleep 5s so that elements can time out
0 sleep 5
# List set
-0 ipset list test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6,port.t.list1
+0 ./diff.sh .foo hash:ip6,port.t.list1
# Flush test set
0 ipset flush test
# Add multiple elements in one step
diff --git a/tests/hash:ip6,port.t.list0 b/tests/hash:ip6,port.t.list0
index 926c4ec..9fca34a 100644
--- a/tests/hash:ip6,port.t.list0
+++ b/tests/hash:ip6,port.t.list0
@@ -1,11 +1,12 @@
Name: test
Type: hash:ip,port
-Header: family inet6 hashsize 1024 maxelem 65536 timeout x
-Size in memory: 1088
+Revision: 6
+Header: family inet6 hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x013bd339
+Size in memory: 736
References: 0
Number of entries: 4
Members:
-2:1::,tcp:128 timeout x
-2:1::1,tcp:128 timeout x
-2::,tcp:5 timeout x
-2::1,tcp:5 timeout x
+2:1::,tcp:128 timeout 3
+2:1::1,tcp:128 timeout 3
+2::,tcp:5 timeout 3
+2::1,tcp:5 timeout 3
diff --git a/tests/hash:ip6,port.t.list1 b/tests/hash:ip6,port.t.list1
index d707af5..46fdea2 100644
--- a/tests/hash:ip6,port.t.list1
+++ b/tests/hash:ip6,port.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,port
-Header: family inet6 hashsize 1024 maxelem 65536 timeout 4
-Size in memory: 800
+Revision: 6
+Header: family inet6 hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0x9f983aa9
+Size in memory: 736
References: 0
Number of entries: 0
Members:
diff --git a/tests/hash:ip6.t b/tests/hash:ip6.t
index 5edc267..52175a5 100644
--- a/tests/hash:ip6.t
+++ b/tests/hash:ip6.t
@@ -21,25 +21,25 @@
# IP: Delete the same value
0 ipset -D test 200:100:0::12
# IP: List set
-0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# IP: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6.t.list2
+0 ./diff.sh .foo hash:ip6.t.list2
# IP: Save set
0 ipset save test > hash:ip6.t.restore
# Sleep 5s so that element can time out
0 sleep 5
# IP: List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# IP: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6.t.list0
+0 ./diff.sh .foo hash:ip6.t.list0
# IP: Destroy set
0 ipset x test
# IP: Restore saved set
0 ipset restore < hash:ip6.t.restore && rm hash:ip6.t.restore
# IP: List set
-0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# IP: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6.t.list2
+0 ./diff.sh .foo hash:ip6.t.list2
# IP: Flush test set
0 ipset -F test
# IP: Try to add multiple elements in one step
@@ -73,15 +73,15 @@
# Network: Test the deleted network
1 ipset -T test 200:101:0::12
# Network: List set
-0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Network: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6.t.list3
+0 ./diff.sh .foo hash:ip6.t.list3
# Sleep 5s so that elements can time out
0 sleep 5
# Network: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Network: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:ip6.t.list1
+0 ./diff.sh .foo hash:ip6.t.list1
# Network: Flush test set
0 ipset -F test
# Network: Delete test set
@@ -89,13 +89,13 @@
# Check more complex restore commands
0 ipset restore < restore.t.restore
# List restored set a
-0 ipset l a | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset l a > .foo0 && ./sort.sh .foo0
# Check listing of set a
-0 diff -u -I 'Size in memory.*' .foo restore.t.list0
+0 ./diff.sh .foo restore.t.list0
# List restored set b
-0 ipset l b | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset l b > .foo0 && ./sort.sh .foo0
# Check listing of set b
-0 diff -u -I 'Size in memory.*' .foo restore.t.list1
+0 ./diff.sh .foo restore.t.list1
# Destroy by restore
0 ipset restore < restore.t.destroy
# Timeout: Check that resizing keeps timeout values
diff --git a/tests/hash:ip6.t.list0 b/tests/hash:ip6.t.list0
index 44b6fb4..7dbe3dd 100644
--- a/tests/hash:ip6.t.list0
+++ b/tests/hash:ip6.t.list0
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip
-Header: family inet6 hashsize 128 maxelem 65536 timeout 4
-Size in memory: 416
+Revision: 5
+Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xb377cb25
+Size in memory: 504
References: 0
Number of entries: 1
Members:
diff --git a/tests/hash:ip6.t.list1 b/tests/hash:ip6.t.list1
index 838fa77..c839bea 100644
--- a/tests/hash:ip6.t.list1
+++ b/tests/hash:ip6.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip
-Header: family inet6 hashsize 128 maxelem 65536 netmask 64 timeout 4
-Size in memory: 544
+Revision: 5
+Header: family inet6 hashsize 128 maxelem 65536 netmask 64 timeout 4 bucketsize 12 initval 0xc4b28af2
+Size in memory: 584
References: 0
Number of entries: 1
Members:
diff --git a/tests/hash:ip6.t.list2 b/tests/hash:ip6.t.list2
index 46a92f7..d3045ea 100644
--- a/tests/hash:ip6.t.list2
+++ b/tests/hash:ip6.t.list2
@@ -1,9 +1,10 @@
Name: test
Type: hash:ip
-Header: family inet6 hashsize 128 maxelem 65536 timeout x
-Size in memory: 512
+Revision: 5
+Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x4f3db7cd
+Size in memory: 504
References: 0
Number of entries: 2
Members:
-192:168:68::69 timeout x
-2::1 timeout x
+192:168:68::69 timeout 0
+2::1 timeout 3
diff --git a/tests/hash:ip6.t.list3 b/tests/hash:ip6.t.list3
index c6e2990..9becbe5 100644
--- a/tests/hash:ip6.t.list3
+++ b/tests/hash:ip6.t.list3
@@ -1,10 +1,11 @@
Name: test
Type: hash:ip
-Header: family inet6 hashsize 128 maxelem 65536 netmask 64 timeout x
-Size in memory: 704
+Revision: 5
+Header: family inet6 hashsize 128 maxelem 65536 netmask 64 timeout 4 bucketsize 12 initval 0xcc03ae18
+Size in memory: 504
References: 0
Number of entries: 3
Members:
-192:168:68:: timeout x
-200:100:10:: timeout x
-2:: timeout x
+192:168:68:: timeout 3
+200:100:10:: timeout 0
+2:: timeout 3
diff --git a/tests/hash:mac.t b/tests/hash:mac.t
index 361bf58..9192af0 100644
--- a/tests/hash:mac.t
+++ b/tests/hash:mac.t
@@ -19,15 +19,15 @@
# MAC: Delete the same value
0 ipset -D test 1:2:3:4:a:b
# MAC: List set
-0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# MAC: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:mac.t.list2
+0 ./diff.sh .foo hash:mac.t.list2
# Sleep 5s so that element can time out
0 sleep 5
# MAC: List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# MAC: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:mac.t.list0
+0 ./diff.sh .foo hash:mac.t.list0
# MAC: Destroy test set
0 ipset -X test
# MAC: Create a set with skbinfo extension
@@ -45,9 +45,9 @@
# MAC: Add element with mark, skbprio and skbqueue
0 ipset a test 1:2:3:4:5:11 skbmark 0x11223344/0xffff0000 skbprio 2:1 skbqueue 8
# MAC: List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# MAC: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:mac.t.list1
+0 ./diff.sh .foo hash:mac.t.list1
# MAC: Destroy test set
0 ipset -X test
# MAC: Create a set with small maxelem parameter
@@ -63,9 +63,9 @@
# MAC: Add second element with another extension value
0 ipset -! a test 1:2:3:4:5:7 skbprio 1:12 skbqueue 8
# MAC: List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# MAC: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:mac.t.list3
+0 ./diff.sh .foo hash:mac.t.list3
# MAC: Destroy test set
0 ipset x test
# eof
diff --git a/tests/hash:mac.t.list0 b/tests/hash:mac.t.list0
index 232b932..2c381ff 100644
--- a/tests/hash:mac.t.list0
+++ b/tests/hash:mac.t.list0
@@ -1,7 +1,8 @@
Name: test
Type: hash:mac
-Header: hashsize 128 maxelem 65536 timeout 4
-Size in memory: 336
+Revision: 1
+Header: hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x851b9eb1
+Size in memory: 464
References: 0
Number of entries: 1
Members:
diff --git a/tests/hash:mac.t.list1 b/tests/hash:mac.t.list1
index 0c971ff..d464f74 100644
--- a/tests/hash:mac.t.list1
+++ b/tests/hash:mac.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:mac
-Header: hashsize 1024 maxelem 65536 skbinfo
-Size in memory: 1088
+Revision: 1
+Header: hashsize 1024 maxelem 65536 skbinfo bucketsize 12 initval 0x5698af00
+Size in memory: 816
References: 0
Number of entries: 6
Members:
diff --git a/tests/hash:mac.t.list2 b/tests/hash:mac.t.list2
index 166f266..bc7ecb0 100644
--- a/tests/hash:mac.t.list2
+++ b/tests/hash:mac.t.list2
@@ -1,9 +1,10 @@
Name: test
Type: hash:mac
-Header: hashsize 128 maxelem 65536 timeout x
-Size in memory: 384
+Revision: 1
+Header: hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x60a630a7
+Size in memory: 464
References: 0
Number of entries: 2
Members:
-00:00:00:00:02:00 timeout x
-00:0A:00:00:00:00 timeout x
+00:00:00:00:02:00 timeout 3
+00:0A:00:00:00:00 timeout 0
diff --git a/tests/hash:mac.t.list3 b/tests/hash:mac.t.list3
index 4154342..cc02314 100644
--- a/tests/hash:mac.t.list3
+++ b/tests/hash:mac.t.list3
@@ -1,7 +1,8 @@
Name: test
Type: hash:mac
-Header: hashsize 1024 maxelem 2 skbinfo
-Size in memory: 448
+Revision: 1
+Header: hashsize 1024 maxelem 2 skbinfo bucketsize 12 initval 0x7c818884
+Size in memory: 496
References: 0
Number of entries: 2
Members:
diff --git a/tests/hash:net,iface.t b/tests/hash:net,iface.t
index a847357..444f230 100644
--- a/tests/hash:net,iface.t
+++ b/tests/hash:net,iface.t
@@ -41,9 +41,9 @@
# Try to add IP address
0 ipset add test 2.0.0.1,eth0
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net,iface.t.list0
+0 ./diff.sh .foo hash:net,iface.t.list0
# Flush test set
0 ipset flush test
# Delete test set
@@ -53,9 +53,9 @@
# Add networks in range notation
0 ipset add test 10.2.0.0-10.2.1.12,eth0
# List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net,iface.t.list2
+0 ./diff.sh .foo hash:net,iface.t.list2
# Flush test set
0 ipset flush test
# Add 0/0,eth0
@@ -117,9 +117,9 @@
# Add overlapping networks from /4 to /30
0 (set -e; for x in `seq 4 30`; do ipset add test 192.0.0.0/$x,eth$x; done)
# List test set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net,iface.t.list1
+0 ./diff.sh .foo hash:net,iface.t.list1
# Test matching elements in all added networks from /30 to /24
0 (set -e; y=2; for x in `seq 24 30 | tac`; do ipset test test 192.0.0.$y,eth$x; y=$((y*2)); done)
# Test non-matching elements in all added networks from /30 to /24
@@ -132,6 +132,10 @@
0 (set -e; for x in `seq 0 63`; do ipset add test 10.0.0.0/16,eth$x; done)
# Check listing
0 n=`ipset list test | grep -v Revision: | wc -l` && test $n -eq 71
+# Flush test set
+0 ipset flush test
+# Try to add more than 64 clashing entries
+1 (set -e; for x in `seq 0 64`; do ipset add test 10.0.0.0/16,eth$x; done)
# Delete test set
0 ipset destroy test
# Check all possible CIDR values
diff --git a/tests/hash:net,iface.t.list0 b/tests/hash:net,iface.t.list0
index e29a7d6..aeb3c52 100644
--- a/tests/hash:net,iface.t.list0
+++ b/tests/hash:net,iface.t.list0
@@ -1,7 +1,8 @@
Name: test
Type: hash:net,iface
-Header: family inet hashsize 128 maxelem 65536
-Size in memory: 928
+Revision: 8
+Header: family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x9b9671af
+Size in memory: 976
References: 0
Number of entries: 4
Members:
diff --git a/tests/hash:net,iface.t.list1 b/tests/hash:net,iface.t.list1
index 00f7d80..bf07a73 100644
--- a/tests/hash:net,iface.t.list1
+++ b/tests/hash:net,iface.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:net,iface
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 3872
+Revision: 8
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x79761aac
+Size in memory: 3000
References: 0
Number of entries: 27
Members:
diff --git a/tests/hash:net,iface.t.list2 b/tests/hash:net,iface.t.list2
index 4f5cc90..5dc128a 100644
--- a/tests/hash:net,iface.t.list2
+++ b/tests/hash:net,iface.t.list2
@@ -1,7 +1,8 @@
Name: test
Type: hash:net,iface
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 928
+Revision: 8
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb61bc401
+Size in memory: 976
References: 0
Number of entries: 4
Members:
diff --git a/tests/hash:net,net.t b/tests/hash:net,net.t
index 13f1198..41189b7 100644
--- a/tests/hash:net,net.t
+++ b/tests/hash:net,net.t
@@ -33,15 +33,15 @@
# Try to add IP address
0 ipset add test 2.0.0.1,2.0.0.2
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net,net.t.list0
+0 ./diff.sh .foo hash:net,net.t.list0
# Sleep 5s so that element can time out
0 sleep 5
# List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net,net.t.list1
+0 ./diff.sh .foo hash:net,net.t.list1
# Flush test set
0 ipset flush test
# Delete test set
@@ -51,9 +51,9 @@
# Add networks in range notation
0 ipset add test 10.2.0.0-10.2.1.12,10.3.0.0-10.3.1.12
# List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net,net.t.list2
+0 ./diff.sh .foo hash:net,net.t.list2
# Delete test set
0 ipset destroy test
# Stress test with range notation
@@ -166,4 +166,110 @@
0 ./check_extensions test 2.0.0.0/25,2.0.0.0/25 700 13 12479
# Counters and timeout: destroy set
0 ipset x test
+# Network: Create a set with timeout and netmask
+0 ipset -N test hash:net,net --hashsize 128 --netmask 24 timeout 4
+# Network: Add first random network
+0 ipset -A test 2.0.10.1,2.10.10.254
+# Network: Add second random network
+0 ipset -A test 192.168.68.1,192.168.68.254
+# Network: Test first random value
+0 ipset -T test 2.0.10.11,2.10.10.25
+# Network: Test second random value
+0 ipset -T test 192.168.68.11,192.168.68.5
+# Network: Test value not added to the set
+1 ipset -T test 2.10.1.0,21.0.1.0
+# Network: Add third element
+0 ipset -A test 200.100.10.1,200.100.10.100 timeout 0
+# Network: Add third random network
+0 ipset -A test 200.100.0.12,200.100.0.13
+# Network: Delete the same network
+0 ipset -D test 200.100.0.12,200.100.0.13
+# Network: List set
+0 ipset -L test > .foo0 && ./sort.sh .foo0
+# Network: Check listing
+0 ./diff.sh .foo hash:net,net.t.list3
+# Sleep 5s so that elements can time out
+0 sleep 5
+# Network: List set
+0 ipset -L test > .foo
+# Network: Check listing
+0 ./diff.sh .foo hash:net,net.t.list4
+# Network: Flush test set
+0 ipset -F test
+# Network: add element with 1s timeout
+0 ipset add test 200.100.0.12,80.20.0.12 timeout 1
+# Network: readd element with 3s timeout
+0 ipset add test 200.100.0.12,80.20.0.12 timeout 3 -exist
+# Network: sleep 2s
+0 sleep 2s
+# Network: check readded element
+0 ipset test test 200.100.0.12,80.20.0.12
+# Network: Delete test set
+0 ipset -X test
+# Network: Create a set with timeout and bitmask
+0 ipset -N test hash:net,net --hashsize 128 --bitmask 255.255.255.0 timeout 4
+# Network: Add first random network
+0 ipset -A test 2.0.10.1,2.10.10.254
+# Network: Add second random network
+0 ipset -A test 192.168.68.1,192.168.68.254
+# Network: Test first random value
+0 ipset -T test 2.0.10.11,2.10.10.25
+# Network: Test second random value
+0 ipset -T test 192.168.68.11,192.168.68.5
+# Network: Test value not added to the set
+1 ipset -T test 2.10.1.0,21.0.1.0
+# Network: Add third element
+0 ipset -A test 200.100.10.1,200.100.10.100 timeout 0
+# Network: Add third random network
+0 ipset -A test 200.100.0.12,200.100.0.13
+# Network: Delete the same network
+0 ipset -D test 200.100.0.12,200.100.0.13
+# Network: List set
+0 ipset -L test > .foo0 && ./sort.sh .foo0
+# Network: Check listing
+0 ./diff.sh .foo hash:net,net.t.list5
+# Sleep 5s so that elements can time out
+0 sleep 5
+# Network: List set
+0 ipset -L test > .foo
+# Network: Check listing
+0 ./diff.sh .foo hash:net,net.t.list6
+# Network: Flush test set
+0 ipset -F test
+# Network: add element with 1s timeout
+0 ipset add test 200.100.0.12,80.20.0.12 timeout 1
+# Network: readd element with 3s timeout
+0 ipset add test 200.100.0.12,80.20.0.12 timeout 3 -exist
+# Network: sleep 2s
+0 sleep 2s
+# Network: check readded element
+0 ipset test test 200.100.0.12,80.20.0.12
+# Network: Delete test set
+0 ipset -X test
+# Network: Create a set with bitmask which is not a valid netmask
+0 ipset -N test hash:net,net --hashsize 128 --bitmask 255.255.0.255
+# Network: Add zero valued element
+1 ipset -A test 0.0.0.0
+# Network: Test zero valued element
+1 ipset -T test 0.0.0.0
+# Network: Delete zero valued element
+1 ipset -D test 0.0.0.0
+# Network: Add first random network
+0 ipset -A test 1.2.3.4,22.23.24.25
+# Network: Add second random network
+0 ipset -A test 1.168.122.124,122.23.45.50
+# Network: Test first random value
+0 ipset -T test 1.2.43.4,22.23.2.25
+# Network: Test second random value
+0 ipset -T test 1.168.12.124,122.23.4.50
+# Network: Test value not added to the set
+1 ipset -T test 2.168.122.124,22.23.45.50
+# Network: Test delete value
+0 ipset -D test 1.168.12.124,122.23.0.50
+# Network: List set
+0 ipset -L test > .foo
+# Network: Check listing
+0 ./diff.sh .foo hash:net,net.t.list7
+# Network: Delete test set
+0 ipset -X test
# eof
diff --git a/tests/hash:net,net.t.list0 b/tests/hash:net,net.t.list0
index 4b806ea..14be3c2 100644
--- a/tests/hash:net,net.t.list0
+++ b/tests/hash:net,net.t.list0
@@ -1,11 +1,12 @@
Name: test
Type: hash:net,net
-Header: family inet hashsize 128 maxelem 65536 timeout x
-Size in memory: 1288
+Revision: 3
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x24629b16
+Size in memory: 1048
References: 0
Number of entries: 4
Members:
-1.1.1.1,1.1.1.2 timeout x
-192.168.68.64/27,192.168.129.64/27 timeout x
-2.0.0.0/24,2.0.1.0/24 timeout x
-2.0.0.1,2.0.0.2 timeout x
+1.1.1.1,1.1.1.2 timeout 3
+192.168.68.64/27,192.168.129.64/27 timeout 3
+2.0.0.0/24,2.0.1.0/24 timeout 3
+2.0.0.1,2.0.0.2 timeout 3
diff --git a/tests/hash:net,net.t.list1 b/tests/hash:net,net.t.list1
index 99e62c1..7f1a1b6 100644
--- a/tests/hash:net,net.t.list1
+++ b/tests/hash:net,net.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:net,net
-Header: family inet hashsize 128 maxelem 65536 timeout 4
-Size in memory: 920
+Revision: 3
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xff0645fb
+Size in memory: 1048
References: 0
Number of entries: 0
Members:
diff --git a/tests/hash:net,net.t.list2 b/tests/hash:net,net.t.list2
index 139b3e2..bb8d663 100644
--- a/tests/hash:net,net.t.list2
+++ b/tests/hash:net,net.t.list2
@@ -1,7 +1,8 @@
Name: test
Type: hash:net,net
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 2056
+Revision: 3
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x957a74a3
+Size in memory: 1752
References: 0
Number of entries: 16
Members:
diff --git a/tests/hash:net,net.t.list3 b/tests/hash:net,net.t.list3
new file mode 100644
index 0000000..fc5b97a
--- /dev/null
+++ b/tests/hash:net,net.t.list3
@@ -0,0 +1,11 @@
+Name: test
+Type: hash:net,net
+Revision: 4
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xe17e4732 netmask 24
+Size in memory: 848
+References: 0
+Number of entries: 3
+Members:
+192.168.68.0,192.168.68.0 timeout 3
+2.0.10.0,2.10.10.0 timeout 3
+200.100.10.0,200.100.10.0 timeout 0
diff --git a/tests/hash:net,net.t.list4 b/tests/hash:net,net.t.list4
new file mode 100644
index 0000000..908cab6
--- /dev/null
+++ b/tests/hash:net,net.t.list4
@@ -0,0 +1,9 @@
+Name: test
+Type: hash:net,net
+Revision: 4
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xb69e293e netmask 24
+Size in memory: 848
+References: 0
+Number of entries: 1
+Members:
+200.100.10.0,200.100.10.0 timeout 0
diff --git a/tests/hash:net,net.t.list5 b/tests/hash:net,net.t.list5
new file mode 100644
index 0000000..0ff37fb
--- /dev/null
+++ b/tests/hash:net,net.t.list5
@@ -0,0 +1,11 @@
+Name: test
+Type: hash:net,net
+Revision: 4
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xe17e4732 bitmask 255.255.255.0
+Size in memory: 848
+References: 0
+Number of entries: 3
+Members:
+192.168.68.0,192.168.68.0 timeout 3
+2.0.10.0,2.10.10.0 timeout 3
+200.100.10.0,200.100.10.0 timeout 0
diff --git a/tests/hash:net,net.t.list6 b/tests/hash:net,net.t.list6
new file mode 100644
index 0000000..84beb5b
--- /dev/null
+++ b/tests/hash:net,net.t.list6
@@ -0,0 +1,9 @@
+Name: test
+Type: hash:net,net
+Revision: 4
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xb69e293e bitmask 255.255.255.0
+Size in memory: 848
+References: 0
+Number of entries: 1
+Members:
+200.100.10.0,200.100.10.0 timeout 0
diff --git a/tests/hash:net,net.t.list7 b/tests/hash:net,net.t.list7
new file mode 100644
index 0000000..6601795
--- /dev/null
+++ b/tests/hash:net,net.t.list7
@@ -0,0 +1,9 @@
+Name: test
+Type: hash:net,net
+Revision: 4
+Header: family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x6223fef7 bitmask 255.255.0.255
+Size in memory: 736
+References: 0
+Number of entries: 1
+Members:
+1.2.0.4,22.23.0.25
diff --git a/tests/hash:net,port,net.t b/tests/hash:net,port,net.t
index 0e92f5b..2c9516b 100644
--- a/tests/hash:net,port,net.t
+++ b/tests/hash:net,port,net.t
@@ -27,9 +27,9 @@
# Try to add value after second random value
0 ipset add test 2.1.0.1,128,10.0.0.0/17
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net,port,net.t.list0
+0 ./diff.sh .foo hash:net,port,net.t.list0
# Sleep 5s so that elements can time out
0 sleep 5
# List set
@@ -52,6 +52,12 @@
0 ipset add test 10.0.0.0-10.0.3.255,tcp:80-82,192.168.0.0-192.168.2.255
# Check that correct number of elements are added
0 n=`ipset list test|grep '^10.0'|wc -l` && test $n -eq 6
+# Flush set
+0 ipset flush test
+# Add 0/0 networks
+0 ipset add test 0.0.0.0/0,tcp:1-2,192.168.230.128/25
+# Check that correct number of elements are added
+0 n=`ipset list test|grep '^0'|wc -l` && test $n -eq 2
# Destroy set
0 ipset -X test
# Create test set with timeout support
diff --git a/tests/hash:net,port,net.t.list0 b/tests/hash:net,port,net.t.list0
index 9f20e7d..166b602 100644
--- a/tests/hash:net,port,net.t.list0
+++ b/tests/hash:net,port,net.t.list0
@@ -1,11 +1,12 @@
Name: test
Type: hash:net,port,net
-Header: family inet hashsize 1024 maxelem 65536 timeout x
-Size in memory: 1288
+Revision: 3
+Header: family inet hashsize 1024 maxelem 65536 timeout 4 bucketsize 12 initval 0xf441dd10
+Size in memory: 1048
References: 0
Number of entries: 4
Members:
-2.0.0.0/24,tcp:5,192.168.0.0/24 timeout x
-2.0.0.0/24,tcp:5,192.168.0.0/25 timeout x
-2.1.0.0/24,tcp:128,10.0.0.0/16 timeout x
-2.1.0.1,tcp:128,10.0.0.0/17 timeout x
+2.0.0.0/24,tcp:5,192.168.0.0/24 timeout 3
+2.0.0.0/24,tcp:5,192.168.0.0/25 timeout 3
+2.1.0.0/24,tcp:128,10.0.0.0/16 timeout 3
+2.1.0.1,tcp:128,10.0.0.0/17 timeout 3
diff --git a/tests/hash:net,port.t b/tests/hash:net,port.t
index 5424ff7..5a850e6 100644
--- a/tests/hash:net,port.t
+++ b/tests/hash:net,port.t
@@ -41,15 +41,15 @@
# Test ICMP by name
0 ipset test test 2.0.0.255,icmp:host-prohibited
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net,port.t.list0
+0 ./diff.sh .foo hash:net,port.t.list0
# Sleep 5s so that element can time out
0 sleep 5
# IP: List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# IP: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net,port.t.list1
+0 ./diff.sh .foo hash:net,port.t.list1
# Flush test set
0 ipset flush test
# Add multiple elements in one step
diff --git a/tests/hash:net,port.t.list0 b/tests/hash:net,port.t.list0
index fbfab7f..afb7215 100644
--- a/tests/hash:net,port.t.list0
+++ b/tests/hash:net,port.t.list0
@@ -1,12 +1,13 @@
Name: test
Type: hash:net,port
-Header: family inet hashsize 128 maxelem 65536 timeout x
-Size in memory: 1024
+Revision: 8
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x34b03146
+Size in memory: 912
References: 0
Number of entries: 5
Members:
-1.1.1.1,tcp:5 timeout x
-192.168.68.64/27,tcp:8 timeout x
-2.0.0.0/24,icmp:echo-request timeout x
-2.0.0.1,icmp:echo-request timeout x
-2.0.0.255,icmp:host-prohibited timeout x
+1.1.1.1,tcp:5 timeout 3
+192.168.68.64/27,tcp:8 timeout 3
+2.0.0.0/24,icmp:echo-request timeout 3
+2.0.0.1,icmp:echo-request timeout 2
+2.0.0.255,icmp:host-prohibited timeout 3
diff --git a/tests/hash:net,port.t.list1 b/tests/hash:net,port.t.list1
index 66f0955..4ee3e5b 100644
--- a/tests/hash:net,port.t.list1
+++ b/tests/hash:net,port.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:net,port
-Header: family inet hashsize 128 maxelem 65536 timeout 4
-Size in memory: 880
+Revision: 8
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xad2d00b2
+Size in memory: 784
References: 0
Number of entries: 0
Members:
diff --git a/tests/hash:net.t b/tests/hash:net.t
index 501f63e..c74ace1 100644
--- a/tests/hash:net.t
+++ b/tests/hash:net.t
@@ -33,15 +33,15 @@
# Try to add IP address
0 ipset add test 2.0.0.1
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net.t.list0
+0 ./diff.sh .foo hash:net.t.list0
# Sleep 5s so that element can time out
0 sleep 5
# List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net.t.list1
+0 ./diff.sh .foo hash:net.t.list1
# Flush test set
0 ipset flush test
# Delete test set
@@ -51,9 +51,9 @@
# Add networks in range notation
0 ipset add test 10.2.0.0-10.2.1.12
# List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net.t.list2
+0 ./diff.sh .foo hash:net.t.list2
# Delete test set
0 ipset destroy test
# Stress test with range notation
@@ -127,9 +127,9 @@
# Add more than 2^31 elements in a range
0 ipset a test 0.0.0.0-128.0.0.1
# List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net.t.list3
+0 ./diff.sh .foo hash:net.t.list3
# Delete test set
0 ipset destroy test
# Counters: create set
diff --git a/tests/hash:net.t.list0 b/tests/hash:net.t.list0
index e22f183..fbab961 100644
--- a/tests/hash:net.t.list0
+++ b/tests/hash:net.t.list0
@@ -1,11 +1,12 @@
Name: test
Type: hash:net
-Header: family inet hashsize 128 maxelem 65536 timeout x
-Size in memory: 896
+Revision: 7
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xb6f1b3fa
+Size in memory: 848
References: 0
Number of entries: 4
Members:
-1.1.1.1 timeout x
-192.168.68.64/27 timeout x
-2.0.0.0/24 timeout x
-2.0.0.1 timeout x
+1.1.1.1 timeout 3
+192.168.68.64/27 timeout 3
+2.0.0.0/24 timeout 3
+2.0.0.1 timeout 3
diff --git a/tests/hash:net.t.list1 b/tests/hash:net.t.list1
index 6e74a1d..afa8f0e 100644
--- a/tests/hash:net.t.list1
+++ b/tests/hash:net.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:net
-Header: family inet hashsize 128 maxelem 65536 timeout 4
-Size in memory: 784
+Revision: 7
+Header: family inet hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x9d02405f
+Size in memory: 848
References: 0
Number of entries: 0
Members:
diff --git a/tests/hash:net.t.list2 b/tests/hash:net.t.list2
index 893ac9d..94bb184 100644
--- a/tests/hash:net.t.list2
+++ b/tests/hash:net.t.list2
@@ -1,7 +1,8 @@
Name: test
Type: hash:net
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 640
+Revision: 7
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xadbf55c3
+Size in memory: 784
References: 0
Number of entries: 4
Members:
diff --git a/tests/hash:net.t.list3 b/tests/hash:net.t.list3
index 265fcbd..7b21185 100644
--- a/tests/hash:net.t.list3
+++ b/tests/hash:net.t.list3
@@ -1,7 +1,8 @@
Name: test
Type: hash:net
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 504
+Revision: 7
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5f93250
+Size in memory: 688
References: 0
Number of entries: 2
Members:
diff --git a/tests/hash:net6,net6.t b/tests/hash:net6,net6.t
index 57f8b2a..257d142 100644
--- a/tests/hash:net6,net6.t
+++ b/tests/hash:net6,net6.t
@@ -33,15 +33,15 @@
# Try to add IP address
0 ipset add test 3:0:0::1,8:0:0::1
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net6,net6.t.list0
+0 ./diff.sh .foo hash:net6,net6.t.list0
# Sleep 5s so that element can time out
0 sleep 5
# IP: List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# IP: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net6,net6.t.list1
+0 ./diff.sh .foo hash:net6,net6.t.list1
# Flush test set
0 ipset flush test
# Add matching IP address entry
diff --git a/tests/hash:net6,net6.t.list0 b/tests/hash:net6,net6.t.list0
index 1f021e5..93d3aeb 100644
--- a/tests/hash:net6,net6.t.list0
+++ b/tests/hash:net6,net6.t.list0
@@ -1,11 +1,12 @@
Name: test
Type: hash:net,net
-Header: family inet6 hashsize 128 maxelem 65536 timeout x
-Size in memory: 3144
+Revision: 3
+Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x4f7b512c
+Size in memory: 2416
References: 0
Number of entries: 4
Members:
-192:160::/27,172:16:68::/48 timeout x
-1:1:1::1,2:2:2::2 timeout x
-2::/24,4::/32 timeout x
-3::1,8::1 timeout x
+192:160::/27,172:16:68::/48 timeout 3
+1:1:1::1,2:2:2::2 timeout 3
+2::/24,4::/32 timeout 3
+3::1,8::1 timeout 3
diff --git a/tests/hash:net6,net6.t.list1 b/tests/hash:net6,net6.t.list1
index 2ccfd51..3aad97e 100644
--- a/tests/hash:net6,net6.t.list1
+++ b/tests/hash:net6,net6.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:net,net
-Header: family inet6 hashsize 128 maxelem 65536 timeout 4
-Size in memory: 2608
+Revision: 3
+Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x3ab35d63
+Size in memory: 2416
References: 0
Number of entries: 0
Members:
diff --git a/tests/hash:net6,port,net6.t b/tests/hash:net6,port,net6.t
index 5793b2d..7ec737e 100644
--- a/tests/hash:net6,port,net6.t
+++ b/tests/hash:net6,port,net6.t
@@ -41,9 +41,9 @@
# Range: Try to add value after second random value
0 ipset -A test 2:1:0::1,128,2:2:2::2/12
# Range: List set
-0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Range: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net6,port,net6.t.list0
+0 ./diff.sh .foo hash:net6,port,net6.t.list0
# Range: Flush test set
0 ipset -F test
# Range: Delete test set
diff --git a/tests/hash:net6,port,net6.t.list0 b/tests/hash:net6,port,net6.t.list0
index 4b9f8f8..3777d54 100644
--- a/tests/hash:net6,port,net6.t.list0
+++ b/tests/hash:net6,port,net6.t.list0
@@ -1,7 +1,8 @@
Name: test
Type: hash:net,port,net
-Header: family inet6 hashsize 1024 maxelem 65536
-Size in memory: 2440
+Revision: 3
+Header: family inet6 hashsize 1024 maxelem 65536 bucketsize 12 initval 0x5b5fdcc8
+Size in memory: 2352
References: 0
Number of entries: 4
Members:
diff --git a/tests/hash:net6,port.t b/tests/hash:net6,port.t
index e3e6584..a9a0f90 100644
--- a/tests/hash:net6,port.t
+++ b/tests/hash:net6,port.t
@@ -41,25 +41,25 @@
# Test ICMPv6 by name
0 ipset test test 192:168:68::95,icmpv6:port-unreachable
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Save set
0 ipset save test > hash:net6,port.t.restore
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net6,port.t.list0
+0 ./diff.sh .foo hash:net6,port.t.list0
# Sleep 5s so that element can time out
0 sleep 5
# IP: List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# IP: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net6,port.t.list1
+0 ./diff.sh .foo hash:net6,port.t.list1
# Destroy set
0 ipset x test
# Restore set
0 ipset restore < hash:net6,port.t.restore && rm hash:net6,port.t.restore
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net6,port.t.list0
+0 ./diff.sh .foo hash:net6,port.t.list0
# Flush test set
0 ipset flush test
# Add multiple elements in one step
diff --git a/tests/hash:net6,port.t.list0 b/tests/hash:net6,port.t.list0
index 2d3596c..ec3dae6 100644
--- a/tests/hash:net6,port.t.list0
+++ b/tests/hash:net6,port.t.list0
@@ -1,12 +1,13 @@
Name: test
Type: hash:net,port
-Header: family inet6 hashsize 128 maxelem 65536 timeout x
-Size in memory: 2352
+Revision: 8
+Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xf2b7e0da
+Size in memory: 1856
References: 0
Number of entries: 5
Members:
-192:160::/27,ipv6-icmp:echo-request timeout x
-192:168:68::95,ipv6-icmp:port-unreachable timeout x
-1:1:1::1,tcp:8 timeout x
-2::/24,tcp:8 timeout x
-3::1,tcp:8 timeout x
+192:160::/27,ipv6-icmp:echo-request timeout 3
+192:168:68::95,ipv6-icmp:port-unreachable timeout 3
+1:1:1::1,tcp:8 timeout 0
+2::/24,tcp:8 timeout 3
+3::1,tcp:8 timeout 3
diff --git a/tests/hash:net6,port.t.list1 b/tests/hash:net6,port.t.list1
index 788358b..b3a8c00 100644
--- a/tests/hash:net6,port.t.list1
+++ b/tests/hash:net6,port.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:net,port
-Header: family inet6 hashsize 128 maxelem 65536 timeout 4
-Size in memory: 1984
+Revision: 8
+Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x799a2fc6
+Size in memory: 1856
References: 0
Number of entries: 1
Members:
diff --git a/tests/hash:net6.t b/tests/hash:net6.t
index 7a47655..67ef33e 100644
--- a/tests/hash:net6.t
+++ b/tests/hash:net6.t
@@ -33,15 +33,15 @@
# Try to add IP address
0 ipset add test 3:0:0::1
# List set
-0 ipset list test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
+0 ipset list test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net6.t.list0
+0 ./diff.sh .foo hash:net6.t.list0
# Sleep 5s so that element can time out
0 sleep 5
# IP: List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# IP: Check listing
-0 diff -u -I 'Size in memory.*' .foo hash:net6.t.list1
+0 ./diff.sh .foo hash:net6.t.list1
# Flush test set
0 ipset flush test
# Delete test set
diff --git a/tests/hash:net6.t.list0 b/tests/hash:net6.t.list0
index ad7133a..c78fb3a 100644
--- a/tests/hash:net6.t.list0
+++ b/tests/hash:net6.t.list0
@@ -1,11 +1,12 @@
Name: test
Type: hash:net
-Header: family inet6 hashsize 128 maxelem 65536 timeout x
-Size in memory: 2112
+Revision: 7
+Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0xd3799c51
+Size in memory: 1760
References: 0
Number of entries: 4
Members:
-192:160::/27 timeout x
-1:1:1::1 timeout x
-2::/24 timeout x
-3::1 timeout x
+192:160::/27 timeout 3
+1:1:1::1 timeout 3
+2::/24 timeout 3
+3::1 timeout 3
diff --git a/tests/hash:net6.t.list1 b/tests/hash:net6.t.list1
index bf7dd88..e0a08ec 100644
--- a/tests/hash:net6.t.list1
+++ b/tests/hash:net6.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:net
-Header: family inet6 hashsize 128 maxelem 65536 timeout 4
-Size in memory: 1824
+Revision: 7
+Header: family inet6 hashsize 128 maxelem 65536 timeout 4 bucketsize 12 initval 0x1fb859e4
+Size in memory: 1760
References: 0
Number of entries: 0
Members:
diff --git a/tests/ignore.sh b/tests/ignore.sh
new file mode 100755
index 0000000..9d458e3
--- /dev/null
+++ b/tests/ignore.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+grep -v Revision: $1 | sed 's/initval 0x[0-9a-fA-F]\{8\}/initval 0x00000000/' > .foo
+rm $1
diff --git a/tests/iphash.t b/tests/iphash.t
index 0393295..4d65113 100644
--- a/tests/iphash.t
+++ b/tests/iphash.t
@@ -23,9 +23,9 @@
# IP: Delete element not added to the set, ignoring error
0 ipset -! -D test 200.100.0.12
# IP: List set
-0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# IP: Check listing
-0 diff -u -I 'Size in memory.*' .foo iphash.t.list0
+0 ./diff.sh .foo iphash.t.list0
# IP: Flush test set
0 ipset -F test
# IP: Delete test set
@@ -53,9 +53,9 @@
# IP: Add more entries to the second set
0 tail -n +2 iphash.t.restore | sed -e 's/test/test2/' -e 's/ 10/ 30/' | ipset r
# IP: Save sets
-0 ipset -s -f .foo.1 save
+0 ipset -s -f .foo0 save && ./ignore.sh .foo0
# IP: Compare sorted save and restore
-0 cmp .foo.1 iphash.t.restore.sorted
+0 cmp .foo iphash.t.restore.sorted
# IP: Delete test set
0 ipset x test
# IP: Delete test2 set
@@ -63,9 +63,9 @@
# IP: Restore, which requires multiple messages
0 ipset restore < iphash.t.large
# IP: Save the restored set
-0 ipset save test | sort > .foo.1
+0 (ipset save test | sort > .foo.1) && ./ignore.sh .foo.1
# IP: Compare save and restore
-0 (sort iphash.t.large > .foo.2) && (cmp .foo.1 .foo.2)
+0 (sort iphash.t.large > .foo.2) && (cmp .foo .foo.2)
# IP: Delete all elements, one by one
0 ipset list test | sed '1,/Members/d' | xargs -n1 ipset del test
# IP: Delete test set
@@ -95,9 +95,9 @@
# Network: Delete element not added to the set
1 ipset -D test 200.100.0.12
# Network: List set
-0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Network: Check listing
-0 diff -u -I 'Size in memory.*' .foo iphash.t.list1
+0 ./diff.sh .foo iphash.t.list1
# Network: Flush test set
0 ipset -F test
# Network: Delete test set
diff --git a/tests/iphash.t.large b/tests/iphash.t.large
index 24cc125..dc36b2f 100644
--- a/tests/iphash.t.large
+++ b/tests/iphash.t.large
@@ -1,4 +1,4 @@
-create test hash:ip family inet hashsize 1024 maxelem 65536
+create test hash:ip family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x00000000
add test 10.10.0.0
add test 10.10.0.1
add test 10.10.0.2
diff --git a/tests/iphash.t.list0 b/tests/iphash.t.list0
index 4d75711..3403b82 100644
--- a/tests/iphash.t.list0
+++ b/tests/iphash.t.list0
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip
-Header: family inet hashsize 128 maxelem 65536
-Size in memory: 224
+Revision: 5
+Header: family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x9806dfda
+Size in memory: 416
References: 0
Number of entries: 2
Members:
diff --git a/tests/iphash.t.list1 b/tests/iphash.t.list1
index 18ec027..4ff0d69 100644
--- a/tests/iphash.t.list1
+++ b/tests/iphash.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip
-Header: family inet hashsize 128 maxelem 65536 netmask 24
-Size in memory: 224
+Revision: 5
+Header: family inet hashsize 128 maxelem 65536 netmask 24 bucketsize 12 initval 0x3bfba4f0
+Size in memory: 416
References: 0
Number of entries: 2
Members:
diff --git a/tests/iphash.t.restore.sorted b/tests/iphash.t.restore.sorted
index e944061..2cdd991 100644
--- a/tests/iphash.t.restore.sorted
+++ b/tests/iphash.t.restore.sorted
@@ -1,4 +1,4 @@
-create test hash:ip family inet hashsize 128 maxelem 65536
+create test hash:ip family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x00000000
add test 10.0.0.0
add test 10.0.0.1
add test 10.0.0.2
@@ -128,7 +128,7 @@ add test 10.0.0.125
add test 10.0.0.126
add test 10.0.0.127
add test 10.0.0.128
-create test2 hash:ip family inet hashsize 128 maxelem 65536
+create test2 hash:ip family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0x00000000
add test2 20.0.0.0
add test2 20.0.0.1
add test2 20.0.0.2
diff --git a/tests/ipmap.t b/tests/ipmap.t
index 7ae141c..8e90dc2 100644
--- a/tests/ipmap.t
+++ b/tests/ipmap.t
@@ -49,15 +49,15 @@
# Range: Restore set
0 ipset -R < ipmap.t.restore && rm ipmap.t.restore
# Range: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Range: Check listing
-0 diff -u -I 'Size in memory.*' .foo ipmap.t.list0
+0 ./diff.sh .foo ipmap.t.list0
# Range: Delete a range of elements
0 ipset -! -D test 2.0.0.128-2.0.0.132
# Range: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Range: Check listing
-0 diff -u -I 'Size in memory.*' .foo ipmap.t.list1
+0 ./diff.sh .foo ipmap.t.list1
# Range: Flush test set
0 ipset -F test
# Range: Delete test set
@@ -91,9 +91,9 @@
# Network: Delete the same element
0 ipset -D test 2.0.0.128
# Network: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Network: Check listing
-0 diff -u -I 'Size in memory.*' .foo ipmap.t.list2
+0 ./diff.sh .foo ipmap.t.list2
# Network: Flush test set
0 ipset -F test
# Network: Delete test set
@@ -127,9 +127,9 @@
# Subnets: Add a subnet of subnets
0 ipset -A test 10.8.0.0/16
# Subnets: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Subnets: Check listing
-0 diff -u -I 'Size in memory.*' .foo ipmap.t.list3
+0 ./diff.sh .foo ipmap.t.list3
# Subnets: FLush test set
0 ipset -F test
# Subnets: Delete test set
@@ -153,9 +153,9 @@
# Full: Delete same element
0 ipset -D test 0.1.0.0
# Full: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Full: Check listing
-0 diff -u -I 'Size in memory.*' .foo ipmap.t.list4
+0 ./diff.sh .foo ipmap.t.list4
# Full: Delete test set
0 ipset -X test
# eof
diff --git a/tests/ipmap.t.list0 b/tests/ipmap.t.list0
index d3b99a8..d2a7681 100644
--- a/tests/ipmap.t.list0
+++ b/tests/ipmap.t.list0
@@ -1,7 +1,8 @@
Name: test
Type: bitmap:ip
+Revision: 3
Header: range 2.0.0.1-2.1.0.0
-Size in memory: 8352
+Size in memory: 8320
References: 0
Number of entries: 6
Members:
diff --git a/tests/ipmap.t.list1 b/tests/ipmap.t.list1
index f9b311d..6a97b10 100644
--- a/tests/ipmap.t.list1
+++ b/tests/ipmap.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: bitmap:ip
+Revision: 3
Header: range 2.0.0.1-2.1.0.0
-Size in memory: 8352
+Size in memory: 8320
References: 0
Number of entries: 2
Members:
diff --git a/tests/ipmap.t.list2 b/tests/ipmap.t.list2
index c2c5691..6fc78b5 100644
--- a/tests/ipmap.t.list2
+++ b/tests/ipmap.t.list2
@@ -1,7 +1,8 @@
Name: test
Type: bitmap:ip
+Revision: 3
Header: range 2.0.0.0-2.0.255.255
-Size in memory: 8352
+Size in memory: 8320
References: 0
Number of entries: 2
Members:
diff --git a/tests/ipmap.t.list3 b/tests/ipmap.t.list3
index 3586211..f162e14 100644
--- a/tests/ipmap.t.list3
+++ b/tests/ipmap.t.list3
@@ -1,7 +1,8 @@
Name: test
Type: bitmap:ip
+Revision: 3
Header: range 10.0.0.0-10.255.255.255 netmask 24
-Size in memory: 8352
+Size in memory: 8320
References: 0
Number of entries: 258
Members:
diff --git a/tests/ipmap.t.list4 b/tests/ipmap.t.list4
index 2042ee6..478382d 100644
--- a/tests/ipmap.t.list4
+++ b/tests/ipmap.t.list4
@@ -1,7 +1,8 @@
Name: test
Type: bitmap:ip
+Revision: 3
Header: range 0.0.0.0-255.255.255.255 netmask 16
-Size in memory: 8352
+Size in memory: 8320
References: 0
Number of entries: 2
Members:
diff --git a/tests/ipmarkhash.t b/tests/ipmarkhash.t
index e96bbfa..1276f72 100644
--- a/tests/ipmarkhash.t
+++ b/tests/ipmarkhash.t
@@ -31,9 +31,9 @@
# Try to add value after second random value
0 ipset -A test 2.1.0.1,0x80
# List set
-0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo ipmarkhash.t.list0
+0 ./diff.sh .foo ipmarkhash.t.list0
# Flush test set
0 ipset -F test
# Delete test set
@@ -61,9 +61,9 @@
# Try to add value after second random value
0 ipset -A test 2.1.0.0,0x80
# List set
-0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo ipmarkhash.t.list1
+0 ./diff.sh .foo ipmarkhash.t.list1
# Flush test set
0 ipset -F test
# Delete test set
diff --git a/tests/ipmarkhash.t.list0 b/tests/ipmarkhash.t.list0
index 9ebf116..7042bc6 100644
--- a/tests/ipmarkhash.t.list0
+++ b/tests/ipmarkhash.t.list0
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,mark
-Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536
-Size in memory: 384
+Revision: 3
+Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 bucketsize 12 initval 0x3ad108b0
+Size in memory: 528
References: 0
Number of entries: 4
Members:
diff --git a/tests/ipmarkhash.t.list1 b/tests/ipmarkhash.t.list1
index af39998..30324c7 100644
--- a/tests/ipmarkhash.t.list1
+++ b/tests/ipmarkhash.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,mark
-Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536
-Size in memory: 384
+Revision: 3
+Header: family inet markmask 0xffffffff hashsize 1024 maxelem 65536 bucketsize 12 initval 0xd0130277
+Size in memory: 528
References: 0
Number of entries: 4
Members:
diff --git a/tests/ipporthash.t b/tests/ipporthash.t
index 866c720..b8f3606 100644
--- a/tests/ipporthash.t
+++ b/tests/ipporthash.t
@@ -31,9 +31,9 @@
# Try to add value after second random value
0 ipset -A test 2.1.0.1,128
# List set
-0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo ipporthash.t.list0
+0 ./diff.sh .foo ipporthash.t.list0
# Flush test set
0 ipset -F test
# Delete test set
@@ -61,9 +61,9 @@
# Try to add value after second random value
0 ipset -A test 2.1.0.0,128
# List set
-0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo ipporthash.t.list1
+0 ./diff.sh .foo ipporthash.t.list1
# Flush test set
0 ipset -F test
# Delete test set
diff --git a/tests/ipporthash.t.list0 b/tests/ipporthash.t.list0
index 902160f..c87147e 100644
--- a/tests/ipporthash.t.list0
+++ b/tests/ipporthash.t.list0
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,port
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 384
+Revision: 6
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x7888c8ef
+Size in memory: 528
References: 0
Number of entries: 4
Members:
diff --git a/tests/ipporthash.t.list1 b/tests/ipporthash.t.list1
index d298cc0..5dac9fc 100644
--- a/tests/ipporthash.t.list1
+++ b/tests/ipporthash.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,port
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 384
+Revision: 6
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xcb19e607
+Size in memory: 528
References: 0
Number of entries: 4
Members:
diff --git a/tests/ipportiphash.t b/tests/ipportiphash.t
index 5632433..32f22d1 100644
--- a/tests/ipportiphash.t
+++ b/tests/ipportiphash.t
@@ -39,9 +39,9 @@
# Try to add value after second random value
0 ipset -A test 2.1.0.1,128,2.2.2.2
# List set
-0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo ipportiphash.t.list0
+0 ./diff.sh .foo ipportiphash.t.list0
# Flush test set
0 ipset -F test
# Delete test set
@@ -71,9 +71,9 @@
# Try to del value before first random value
0 ipset -D test 1.255.255.255,5,1.1.1.1
# List set
-0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo ipportiphash.t.list1
+0 ./diff.sh .foo ipportiphash.t.list1
# Flush test set
0 ipset -F test
# Delete test set
diff --git a/tests/ipportiphash.t.list0 b/tests/ipportiphash.t.list0
index bde5356..f031796 100644
--- a/tests/ipportiphash.t.list0
+++ b/tests/ipportiphash.t.list0
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,port,ip
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 456
+Revision: 6
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xf6f43069
+Size in memory: 568
References: 0
Number of entries: 4
Members:
diff --git a/tests/ipportiphash.t.list1 b/tests/ipportiphash.t.list1
index d5cc29e..17877b8 100644
--- a/tests/ipportiphash.t.list1
+++ b/tests/ipportiphash.t.list1
@@ -1,7 +1,8 @@
Name: test
Type: hash:ip,port,ip
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 296
+Revision: 6
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xcd2e539b
+Size in memory: 456
References: 0
Number of entries: 2
Members:
diff --git a/tests/iptables.sh b/tests/iptables.sh
index bca3253..f101ab4 100755
--- a/tests/iptables.sh
+++ b/tests/iptables.sh
@@ -125,11 +125,21 @@ counter)
./sendip.sh -p ipv4 -id 10.255.255.254 -is 10.255.255.64 -p udp -ud 80 -us 1025 10.255.255.254 >/dev/null 2>&1
./sendip.sh -p ipv4 -id 10.255.255.254 -is 10.255.255.64 -p udp -ud 80 -us 1025 10.255.255.254 >/dev/null 2>&1
;;
+resize)
+ $ipset n test hash:ip hashsize 4096 maxelem 655360 2>/dev/null
+ $cmd -t raw -A OUTPUT -j SET --add-set test src
+ $cmd -t raw -A OUTPUT -s 10.255.0.0/16 -j DROP
+ $cmd -t raw -A OUTPUT -s 10.254.0.0/16 -j DROP
+ ./resize_sendip.sh &
+ $ipset restore < resize_target.set
+ ;;
stop)
$cmd -F
$cmd -X
$cmd -F -t mangle
$cmd -X -t mangle
+ $cmd -F -t raw
+ $cmd -X -t raw
$ipset -F 2>/dev/null
$ipset -X 2>/dev/null
;;
diff --git a/tests/macipmap.t b/tests/macipmap.t
index 45783d6..074e067 100644
--- a/tests/macipmap.t
+++ b/tests/macipmap.t
@@ -39,9 +39,9 @@
# Range: Delete the same element
0 ipset -D test 2.0.200.214
# Range: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Range: Check listing
-0 diff -u -I 'Size in memory.*' .foo macipmap.t.list0
+0 ./diff.sh .foo macipmap.t.list0
# Range: Flush test set
0 ipset -F test
# Range: Catch invalid (too long) MAC
@@ -87,9 +87,9 @@
# Network: Add MAC to already added element
0 ipset -A test 2.0.255.255,00:11:22:33:44:56
# Network: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Network: Check listing
-0 diff -u -I 'Size in memory.*' .foo macipmap.t.list1
+0 ./diff.sh .foo macipmap.t.list1
# Network: Flush test set
0 ipset -F test
# Network: Delete test set
@@ -127,15 +127,15 @@
# Range: Delete the same element
0 ipset -D test 2.0.200.214
# Range: List set
-0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo
+0 ipset -L test > .foo
# Range: Check listing
-0 diff -u -I 'Size in memory.*' .foo macipmap.t.list3
+0 ./diff.sh .foo macipmap.t.list3
# Range: sleep 5s so that elements can timeout
0 sleep 5
# Range: List set
-0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo
+0 ipset -L test > .foo
# Range: Check listing
-0 diff -u -I 'Size in memory.*' .foo macipmap.t.list2
+0 ./diff.sh .foo macipmap.t.list2
# Range: Flush test set
0 ipset -F test
# Range: add element with 1s timeout
diff --git a/tests/macipmap.t.list2 b/tests/macipmap.t.list2
index f6a78c7..eaa01ae 100644
--- a/tests/macipmap.t.list2
+++ b/tests/macipmap.t.list2
@@ -1,8 +1,9 @@
Name: test
Type: bitmap:ip,mac
-Header: range 2.0.0.1-2.1.0.0 timeout x
-Size in memory: 1056920
+Revision: 3
+Header: range 2.0.0.1-2.1.0.0 timeout 5
+Size in memory: 1056888
References: 0
Number of entries: 1
Members:
-2.1.0.0 timeout x
+2.1.0.0 timeout 3
diff --git a/tests/macipmap.t.list3 b/tests/macipmap.t.list3
index 78c78d3..3262e64 100644
--- a/tests/macipmap.t.list3
+++ b/tests/macipmap.t.list3
@@ -1,10 +1,11 @@
Name: test
Type: bitmap:ip,mac
-Header: range 2.0.0.1-2.1.0.0 timeout x
-Size in memory: 1056920
+Revision: 3
+Header: range 2.0.0.1-2.1.0.0 timeout 5
+Size in memory: 1056888
References: 0
Number of entries: 3
Members:
-2.0.0.1,00:11:22:33:44:56 timeout x
-2.0.0.2,00:11:22:33:44:55 timeout x
-2.1.0.0 timeout x
+2.0.0.1,00:11:22:33:44:56 timeout 3
+2.0.0.2,00:11:22:33:44:55 timeout 3
+2.1.0.0 timeout 3
diff --git a/tests/nethash.t b/tests/nethash.t
index 05e64c3..8f98ffa 100644
--- a/tests/nethash.t
+++ b/tests/nethash.t
@@ -33,9 +33,9 @@
# Try to add IP address
0 ipset -A test 2.0.0.1
# List set
-0 ipset -L test | grep -v Revision: > .foo0 && ./sort.sh .foo0
+0 ipset -L test > .foo0 && ./sort.sh .foo0
# Check listing
-0 diff -u -I 'Size in memory.*' .foo nethash.t.list0
+0 ./diff.sh .foo nethash.t.list0
# Flush test set
0 ipset -F test
# Add a non-matching IP address entry
diff --git a/tests/nethash.t.list0 b/tests/nethash.t.list0
index 0aeb852..dad3dee 100644
--- a/tests/nethash.t.list0
+++ b/tests/nethash.t.list0
@@ -1,7 +1,8 @@
Name: test
Type: hash:net
-Header: family inet hashsize 128 maxelem 65536
-Size in memory: 640
+Revision: 7
+Header: family inet hashsize 128 maxelem 65536 bucketsize 12 initval 0xdc096f08
+Size in memory: 784
References: 0
Number of entries: 4
Members:
diff --git a/tests/netnetgen.sh b/tests/netnetgen.sh
index f2a31cc..32aac18 100755
--- a/tests/netnetgen.sh
+++ b/tests/netnetgen.sh
@@ -6,7 +6,7 @@ while [ -n "$1" ]; do
comment=" comment"
;;
timeout)
- timeout=" timeout 5"
+ timeout=" timeout 60"
;;
*)
;;
diff --git a/tests/portmap.t b/tests/portmap.t
index 5eeaaff..819a59b 100644
--- a/tests/portmap.t
+++ b/tests/portmap.t
@@ -25,9 +25,9 @@
# Range: Delete the same element
0 ipset -D test 567
# Range: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Range: Check listing
-0 diff -u -I 'Size in memory.*' .foo portmap.t.list0
+0 ./diff.sh .foo portmap.t.list0
# Range: Flush test set
0 ipset -F test
# Range: Delete test set
@@ -45,9 +45,9 @@
# Full: Test value not added to the set
1 ipset -T test 1
# Full: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Full: Check listing
-0 diff -u -I 'Size in memory.*' .foo portmap.t.list1
+0 ./diff.sh .foo portmap.t.list1
# Full: Flush test set
0 ipset -F test
# Full: Delete test set
@@ -69,15 +69,15 @@
# Full: Delete the same element
0 ipset -D test 567
# Full: List set
-0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo
+0 ipset -L test > .foo
# Full: Check listing
-0 diff -u -I 'Size in memory.*' .foo portmap.t.list3
+0 ./diff.sh .foo portmap.t.list3
# Full: sleep 5s so that elements can timeout
0 sleep 5
# Full: List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Full: Check listing
-# 0 diff -u -I 'Size in memory.*' .foo portmap.t.list2
+# 0 ./diff.sh .foo portmap.t.list2
# Full: Flush test set
0 ipset -F test
# Full: add element with 1s timeout
diff --git a/tests/portmap.t.list3 b/tests/portmap.t.list3
index d5756e6..cd3f831 100644
--- a/tests/portmap.t.list3
+++ b/tests/portmap.t.list3
@@ -1,9 +1,10 @@
Name: test
Type: bitmap:port
-Header: range 0-65535 timeout x
-Size in memory: 532628
+Revision: 3
+Header: range 0-65535 timeout 5
+Size in memory: 532592
References: 0
Number of entries: 2
Members:
-0 timeout x
-65535 timeout x
+0 timeout 4
+65535 timeout 0
diff --git a/tests/restore.t b/tests/restore.t
index ffde2d1..dda143f 100644
--- a/tests/restore.t
+++ b/tests/restore.t
@@ -6,4 +6,28 @@
0 ipset x
# Check auto-increasing maximal number of sets
0 ./setlist_resize.sh
+# Create bitmap set with timeout
+0 ipset create test1 bitmap:ip range 2.0.0.1-2.1.0.0 timeout 5
+# Add element to bitmap set
+0 ipset add test1 2.0.0.2 timeout 30
+# Create hash set with timeout
+0 ipset -N test2 iphash --hashsize 128 timeout 4
+# Add element to hash set
+0 ipset add test2 2.0.0.3 timeout 30
+# Create list set with timeout
+0 ipset -N test3 list:set timeout 3
+# Add bitmap set to list set
+0 ipset a test3 test1 timeout 30
+# Add hash set to list set
+0 ipset a test3 test2 timeout 30
+# Flush list set
+0 ipset f test3
+# Destroy all sets
+0 ipset x
+# Remove the ip_set_list_set kernel module
+0 rmmod ip_set_list_set
+# Remove the ip_set_bitmap_ip kernel module
+0 rmmod ip_set_bitmap_ip
+# Remove the ip_set_hash_ip kernel module
+0 rmmod ip_set_hash_ip
# eof
diff --git a/tests/restore.t.list0 b/tests/restore.t.list0
index 3c73ab3..022a0b5 100644
--- a/tests/restore.t.list0
+++ b/tests/restore.t.list0
@@ -1,7 +1,8 @@
Name: a
Type: hash:ip
-Header: family inet6 hashsize 1024 maxelem 65536
-Size in memory: 416
+Revision: 5
+Header: family inet6 hashsize 1024 maxelem 65536 bucketsize 12 initval 0xf366ace6
+Size in memory: 536
References: 0
Number of entries: 3
Members:
diff --git a/tests/restore.t.list1 b/tests/restore.t.list1
index e2c1f8e..e270e52 100644
--- a/tests/restore.t.list1
+++ b/tests/restore.t.list1
@@ -1,7 +1,8 @@
Name: b
Type: hash:ip
-Header: family inet6 hashsize 1024 maxelem 65536
-Size in memory: 416
+Revision: 5
+Header: family inet6 hashsize 1024 maxelem 65536 bucketsize 12 initval 0xdcbd231e
+Size in memory: 536
References: 0
Number of entries: 3
Members:
diff --git a/tests/setlist.t b/tests/setlist.t
index 7d14ec8..316daf8 100644
--- a/tests/setlist.t
+++ b/tests/setlist.t
@@ -45,9 +45,9 @@
# Restore saved sets
0 ipset -R < setlist.t.r
# List set
-0 ipset -L test | grep -v Revision: > .foo
+0 ipset -L test > .foo
# Check listing
-0 diff -u -I 'Size in memory.*' .foo setlist.t.list0
+0 ./diff.sh .foo setlist.t.list0
# Flush all sets
0 ipset -F
# Delete all sets
@@ -61,9 +61,9 @@
# Add set a before b
0 ipset add test a before b
# List test set
-0 ipset list test | grep -v Revision: > .foo
+0 ipset list test > .foo
# Check listing
-0 diff -u -I 'Size in memory.*' .foo setlist.t.list1
+0 ./diff.sh .foo setlist.t.list1
# Test a set before b
0 ipset test test a before b
# Test c set after b
@@ -71,19 +71,19 @@
# Delete b set before c
0 ipset del test b before c
# List test set
-0 ipset list test | grep -v Revision: > .foo
+0 ipset list test > .foo
# Check listing
-0 diff -u -I 'Size in memory.*' .foo setlist.t.list2
+0 ./diff.sh .foo setlist.t.list2
# Delete c set after a
0 ipset del test c after a
# List test set
-0 ipset list test | grep -v Revision: > .foo
+0 ipset list test > .foo
# Check listing
-0 diff -u -I 'Size in memory.*' .foo setlist.t.list3
+0 ./diff.sh .foo setlist.t.list3
# List all sets
-0 sleep .1s; ipset list | grep -v Revision: > .foo
+0 sleep .1s; ipset list > .foo
# Check listing
-0 diff -u -I 'Size in memory.*' .foo setlist.t.list4
+0 ./diff.sh .foo setlist.t.list4
# Flush sets
0 ipset flush
# Destroy sets
diff --git a/tests/setlist.t.list4 b/tests/setlist.t.list4
index 6b115d9..46c6a8c 100644
--- a/tests/setlist.t.list4
+++ b/tests/setlist.t.list4
@@ -1,39 +1,44 @@
Name: a
Type: hash:ip
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 152
+Revision: 5
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x042092ea
+Size in memory: 336
References: 1
Number of entries: 0
Members:
Name: b
Type: hash:ip
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 152
+Revision: 5
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x05db211b
+Size in memory: 336
References: 0
Number of entries: 0
Members:
Name: c
Type: hash:ip
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 152
+Revision: 5
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xf3109e51
+Size in memory: 336
References: 0
Number of entries: 0
Members:
Name: d
Type: hash:ip
-Header: family inet hashsize 1024 maxelem 65536
-Size in memory: 152
+Revision: 5
+Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x6c851a66
+Size in memory: 336
References: 0
Number of entries: 0
Members:
Name: test
Type: list:set
+Revision: 3
Header: size 8
-Size in memory: 184
+Size in memory: 168
References: 0
Number of entries: 1
Members:
diff --git a/tests/setlist_resize.sh b/tests/setlist_resize.sh
index 3255656..848f1d1 100755
--- a/tests/setlist_resize.sh
+++ b/tests/setlist_resize.sh
@@ -12,7 +12,7 @@ for x in ip_set_list_set ip_set_hash_netiface ip_set_hash_ipportnet \
ip_set_hash_netportnet ip_set_hash_ipmark ip_set_hash_mac \
ip_set_bitmap_port ip_set_bitmap_ipmac \
ip_set_bitmap_ip xt_set ip_set; do
- rmmod $x
+ rmmod $x >/dev/null 2>&1
done
create() {
@@ -31,6 +31,6 @@ for x in `seq 1 $loop`; do
test `$ipset l -n | wc -l` -eq 1024 || exit 1
$ipset x
test `lsmod|grep -w ^ip_set_hash_ip | awk '{print $3}'` -eq 0 || exit 1
- rmmod ip_set_hash_ip
- rmmod ip_set
+ rmmod ip_set_hash_ip >/dev/null 2>&1
+ rmmod ip_set >/dev/null 2>&1
done
diff --git a/tests/sort.sh b/tests/sort.sh
index c5edad1..904b216 100755
--- a/tests/sort.sh
+++ b/tests/sort.sh
@@ -1,5 +1,5 @@
#!/bin/sh
-head -n 7 $1 > .foo
-tail -n +8 $1 | grep '[[:alnum:]]' | sort >> .foo
-rm $1
+sed '/Members:/q' $1 > .foo
+awk '/Members:/,EOF' $1 | grep -v 'Members:' | sort >> .foo
+rm -f $1
diff --git a/tests/xlate/ipset-translate b/tests/xlate/ipset-translate
new file mode 120000
index 0000000..91980c1
--- /dev/null
+++ b/tests/xlate/ipset-translate
@@ -0,0 +1 @@
+../../src/ipset \ No newline at end of file
diff --git a/tests/xlate/runtest.sh b/tests/xlate/runtest.sh
new file mode 100755
index 0000000..8b42f0b
--- /dev/null
+++ b/tests/xlate/runtest.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+DIFF=$(which diff)
+if [ ! -x "$DIFF" ] ; then
+ echo "ERROR: missing diff"
+ exit 1
+fi
+
+ipset=${IPSET_BIN:-../../src/ipset}
+ipset_xlate=${IPSET_XLATE_BIN:-$(dirname $0)/ipset-translate}
+
+$ipset restore < xlate.t
+rc=$?
+$ipset destroy
+if [ $rc -ne 0 ]
+then
+ echo -e "[\033[0;31mERROR\033[0m] invalid test input"
+ exit 1
+fi
+
+TMP=$(mktemp)
+$ipset_xlate restore < xlate.t &> $TMP
+if [ $? -ne 0 ]
+then
+ cat $TMP
+ echo -e "[\033[0;31mERROR\033[0m] failed to run ipset-translate"
+ exit 1
+fi
+${DIFF} -u xlate.t.nft $TMP
+if [ $? -eq 0 ]
+then
+ echo -e "[\033[0;32mOK\033[0m] tests are fine!"
+else
+ echo -e "[\033[0;31mERROR\033[0m] unexpected ipset to nftables translation"
+fi
diff --git a/tests/xlate/xlate.t b/tests/xlate/xlate.t
new file mode 100644
index 0000000..38cbc78
--- /dev/null
+++ b/tests/xlate/xlate.t
@@ -0,0 +1,57 @@
+create hip1 hash:ip
+add hip1 192.168.10.2
+add hip1 192.168.10.3
+create hip2 hash:ip hashsize 128 bucketsize 255 timeout 4
+add hip2 192.168.10.3
+add hip2 192.168.10.4 timeout 10
+create hip3 hash:ip counters
+add hip3 192.168.10.3 packets 5 bytes 3456
+create hip4 hash:ip netmask 24
+add hip4 192.168.10.0
+create hip5 hash:ip maxelem 24
+add hip5 192.168.10.0
+create hip6 hash:ip comment
+add hip6 192.168.10.1
+add hip6 192.168.10.2 comment "this is a comment"
+create ipp1 hash:ip,port
+add ipp1 192.168.10.1,0
+add ipp1 192.168.10.2,5
+create ipp2 hash:ip,port timeout 4
+add ipp2 192.168.10.1,0 timeout 12
+add ipp2 192.168.10.2,5
+create ipp3 hash:ip,port counters
+add ipp3 192.168.10.3,20 packets 5 bytes 3456
+create ipp4 hash:ip,port timeout 4 counters
+add ipp4 192.168.10.3,20 packets 5 bytes 3456
+create bip1 bitmap:ip range 2.0.0.1-2.0.1.1 timeout 5
+create bip2 bitmap:ip range 10.0.0.0/8 netmask 24 timeout 5
+add bip2 10.10.10.0
+add bip2 10.10.20.0 timeout 12
+create net1 hash:net
+add net1 192.168.10.0/24
+create net2 hash:net,net
+add net2 192.168.10.0/24,192.168.20.0/24
+create hm1 hash:mac
+add hm1 aa:bb:cc:dd:ee:ff
+create him1 hash:ip,mac
+add him1 1.1.1.1,aa:bb:cc:dd:ee:ff
+create ni1 hash:net,iface
+add ni1 1.1.1.0/24,eth0
+create nip1 hash:net,port
+add nip1 1.1.1.0/24,22
+create npn1 hash:net,port,net
+add npn1 1.1.1.0/24,22,2.2.2.0/24
+create nn1 hash:net,net
+add nn1 1.1.1.0/24,2.2.2.0/24
+create ipn1 hash:ip,port,net
+add ipn1 1.1.1.1,22,2.2.2.0/24
+create ipi1 hash:ip,port,ip
+add ipi1 1.1.1.1,22,2.2.2.2
+create im1 hash:ip,mark
+add im1 1.1.1.1,0x123456
+create bp1 bitmap:port range 1-1024
+add bp1 22
+create bim1 bitmap:ip,mac range 1.1.1.0/24
+add bim1 1.1.1.1,aa:bb:cc:dd:ee:ff
+create hn6 hash:net family inet6
+add hn6 fe80::/64
diff --git a/tests/xlate/xlate.t.nft b/tests/xlate/xlate.t.nft
new file mode 100644
index 0000000..8fb2a29
--- /dev/null
+++ b/tests/xlate/xlate.t.nft
@@ -0,0 +1,58 @@
+add table inet global
+add set inet global hip1 { type ipv4_addr; }
+add element inet global hip1 { 192.168.10.2 }
+add element inet global hip1 { 192.168.10.3 }
+add set inet global hip2 { type ipv4_addr; timeout 4s; }
+add element inet global hip2 { 192.168.10.3 }
+add element inet global hip2 { 192.168.10.4 timeout 10s }
+add set inet global hip3 { type ipv4_addr; counter; }
+add element inet global hip3 { 192.168.10.3 counter packets 5 bytes 3456 }
+add set inet global hip4 { type ipv4_addr; flags interval; }
+add element inet global hip4 { 192.168.10.0/24 }
+add set inet global hip5 { type ipv4_addr; size 24; }
+add element inet global hip5 { 192.168.10.0 }
+add set inet global hip6 { type ipv4_addr; }
+add element inet global hip6 { 192.168.10.1 }
+add element inet global hip6 { 192.168.10.2 comment "this is a comment" }
+add set inet global ipp1 { type ipv4_addr . inet_proto . inet_service; }
+add element inet global ipp1 { 192.168.10.1 . tcp . 0 }
+add element inet global ipp1 { 192.168.10.2 . tcp . 5 }
+add set inet global ipp2 { type ipv4_addr . inet_proto . inet_service; timeout 4s; }
+add element inet global ipp2 { 192.168.10.1 . tcp . 0 timeout 12s }
+add element inet global ipp2 { 192.168.10.2 . tcp . 5 }
+add set inet global ipp3 { type ipv4_addr . inet_proto . inet_service; counter; }
+add element inet global ipp3 { 192.168.10.3 . tcp . 20 counter packets 5 bytes 3456 }
+add set inet global ipp4 { type ipv4_addr . inet_proto . inet_service; counter; timeout 4s; }
+add element inet global ipp4 { 192.168.10.3 . tcp . 20 counter packets 5 bytes 3456 }
+add set inet global bip1 { type ipv4_addr; timeout 5s; }
+add set inet global bip2 { type ipv4_addr; timeout 5s; flags interval; }
+add element inet global bip2 { 10.10.10.0/24 }
+add element inet global bip2 { 10.10.20.0/24 timeout 12s }
+add set inet global net1 { type ipv4_addr; flags interval; }
+add element inet global net1 { 192.168.10.0/24 }
+add set inet global net2 { type ipv4_addr . ipv4_addr; flags interval; }
+add element inet global net2 { 192.168.10.0/24 . 192.168.20.0/24 }
+add set inet global hm1 { type ether_addr; }
+add element inet global hm1 { aa:bb:cc:dd:ee:ff }
+add set inet global him1 { type ipv4_addr . ether_addr; }
+add element inet global him1 { 1.1.1.1 . aa:bb:cc:dd:ee:ff }
+add set inet global ni1 { type ipv4_addr . ifname; flags interval; }
+add element inet global ni1 { 1.1.1.0/24 . eth0 }
+add set inet global nip1 { type ipv4_addr . inet_proto . inet_service; flags interval; }
+add element inet global nip1 { 1.1.1.0/24 . tcp . 22 }
+add set inet global npn1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; flags interval; }
+add element inet global npn1 { 1.1.1.0/24 . tcp . 22 . 2.2.2.0/24 }
+add set inet global nn1 { type ipv4_addr . ipv4_addr; flags interval; }
+add element inet global nn1 { 1.1.1.0/24 . 2.2.2.0/24 }
+add set inet global ipn1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; flags interval; }
+add element inet global ipn1 { 1.1.1.1 . tcp . 22 . 2.2.2.0/24 }
+add set inet global ipi1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; }
+add element inet global ipi1 { 1.1.1.1 . tcp . 22 . 2.2.2.2 }
+add set inet global im1 { type ipv4_addr . mark; }
+add element inet global im1 { 1.1.1.1 . 0x00123456 }
+add set inet global bp1 { type inet_service; }
+add element inet global bp1 { 22 }
+add set inet global bim1 { type ipv4_addr . ether_addr; }
+add element inet global bim1 { 1.1.1.1 . aa:bb:cc:dd:ee:ff }
+add set inet global hn6 { type ipv6_addr; flags interval; }
+add element inet global hn6 { fe80::/64 }
diff --git a/utils/ipset_bash_completion/README.md b/utils/ipset_bash_completion/README.md
index ce5c47e..ecfd6b9 100644
--- a/utils/ipset_bash_completion/README.md
+++ b/utils/ipset_bash_completion/README.md
@@ -33,14 +33,57 @@ icmp[6] types and interface names when adding, deleting or testing elements.
- Complete on filenames if the current option requires it.
- Complete variable names and command substitution.
- Do not complete if an invalid combination of options is used.
-- Do not complete if an invalid value of an option argument is detected.
+- Optionally do not complete if an invalid value of an option argument is detected.
- Environment variables allow to modify completion behaviour.
Installation
============
-Put it into ~/.bash_completion or /etc/bash_completion.d/.
+Quote from bash-completion README:
+
+ Install it in one of the directories pointed to by
+ bash-completion's pkgconfig file variables. There are two
+ alternatives: the recommended one is 'completionsdir' (get it with
+ "pkg-config --variable=completionsdir bash-completion") from which
+ completions are loaded on demand based on invoked commands' names,
+ so be sure to name your completion file accordingly, and to include
+ for example symbolic links in case the file provides completions
+ for more than one command. The other one which is present for
+ backwards compatibility reasons is 'compatdir' (get it with
+ "pkg-config --variable=compatdir bash-completion") from which files
+ are loaded when bash_completion is loaded.
+
+ For packages using GNU autotools the installation can be handled
+ for example like this in configure.ac:
+
+ PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], ,
+ bashcompdir="${sysconfdir}/bash_completion.d")
+ AC_SUBST(bashcompdir)
+
+ ...accompanied by this in Makefile.am:
+
+ bashcompdir = @bashcompdir@
+ dist_bashcomp_DATA = # completion files go here
+
+ For cmake we ship the bash-completion-config.cmake and
+ bash-completion-config-version.cmake files. Example usage:
+
+ find_package(bash-completion)
+ if(BASH_COMPLETION_FOUND)
+ message(STATUS
+ "Using bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}")
+ else()
+ set (BASH_COMPLETION_COMPLETIONSDIR "/etc/bash_completion.d")
+ message (STATUS
+ "Using fallback bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}")
+ endif()
+
+ install(FILES your-completion-file DESTINATION
+ ${BASH_COMPLETION_COMPLETIONSDIR})
+
+For backwards compatibility it is still possible
+to put it into ~/.bash_completion or /etc/bash_completion.d/.
Tip:
To make tab completion more handsome put the following into either
@@ -113,6 +156,7 @@ which will be used for hostname completion.
For all *net* type of sets and the hash:ip,mark set type, if hostname completion is attempted,
if the environment variable **_IPSET_COMP_NETWORKS** is set to a non-empty value,
networks are retrieved from /etc/networks.
+Means these two commands disable it: `_IPSET_COMP_NETWORKS=` or `_IPSET_COMP_NETWORKS=""`
Also a list of ip addresses can be supplied using the environment variable
**_IPSET_IPLIST_FILE**. Which should point to a file containing an ip address per line.
@@ -139,13 +183,15 @@ the list of possible completions (this is the default).
---
-When adding elements to a **bitmap:ip,mac** type of set,
-the environment variable **_IPSET_MACLIST_FILE** will be queried
+When completing on MAC addresses (bitmap:ip,mac, hash:mac type of set),
+the environment variable **_IPSET_MAC_COMPL_MODE** is queried to decide how to complete.
+If set to 'file' the variable **_IPSET_MACLIST_FILE** will be queried
for a file containing a list of mac addresses.
The file should contain one mac address per line.
Empty lines and comments (also after the address) are supported.
-If the variable is unset mac addresses are fetched from arp cache,
-/etc/ethers and the output of `ip link show`.
+If the variable **_IPSET_MAC_COMPL_MODE** is set to 'system' mac addresses are fetched
+from arp cache, /etc/ethers and the output of `ip link show`.
+If the variable is unset or set to 'both' (default) both methods are used).
---
@@ -168,8 +214,8 @@ In that case it is recommended to disable input validation (see below).
---
-If the environment variable **_IPSET_VALIDATE_INPUT** is set to a non empty value
-validation of users input is disabled.
+If the environment variable **_IPSET_VALIDATE_INPUT** is defined and set to a non empty value
+validation of users input is enabled.
---
@@ -183,7 +229,7 @@ Compatibility
Compatible with ipset versions 6+.
-Tested with ipset v6.20.1.
+Tested with ipset v6.24, v6.27.
bash v4+ is required.
diff --git a/utils/ipset_bash_completion/ipset b/utils/ipset_bash_completion/ipset
index b6d94c2..d258be2 100644
--- a/utils/ipset_bash_completion/ipset
+++ b/utils/ipset_bash_completion/ipset
@@ -7,7 +7,7 @@
# https://sourceforge.net/projects/ipset-bashcompl
# -----------------------------------------------------------------
-# Copyright (C) 2013-2014 AllKind (AllKind@fastest.cc)
+# Copyright (C) 2013-2016 Mart Frauenlob aka AllKind (AllKind@fastest.cc)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
# -----------------------------------------------------------------
# Compatible with ipset versions: 6+
# Tested with ipset versions:
-# 6.22
+# 6.24, 6.27
# -----------------------------------------------------------------
# Requirements:
#
@@ -33,6 +33,7 @@
#
# The bash completion package version 2.0 or greater is recommended.
# http://bash-completion.alioth.debian.org/
+# Older version are not supported.
#
# If the package is not available, things might not be so reliable.
# Also the colon (if there) is removed from COMP_WORDBREAKS.
@@ -40,13 +41,54 @@
# if they don't take care of it themselves.
#
# -----------------------------------------------------------------
-# Installation:
+# Installation (quote from bash-completion README):
#
-# Put it into ~/.bash_completion or /etc/bash_completion.d/
+# Install it in one of the directories pointed to by
+# bash-completion's pkgconfig file variables. There are two
+# alternatives: the recommended one is 'completionsdir' (get it with
+# "pkg-config --variable=completionsdir bash-completion") from which
+# completions are loaded on demand based on invoked commands' names,
+# so be sure to name your completion file accordingly, and to include
+# for example symbolic links in case the file provides completions
+# for more than one command. The other one which is present for
+# backwards compatibility reasons is 'compatdir' (get it with
+# "pkg-config --variable=compatdir bash-completion") from which files
+# are loaded when bash_completion is loaded.
+#
+# For packages using GNU autotools the installation can be handled
+# for example like this in configure.ac:
+#
+# PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], ,
+# bashcompdir="${sysconfdir}/bash_completion.d")
+# AC_SUBST(bashcompdir)
+#
+# ...accompanied by this in Makefile.am:
+#
+# bashcompdir = @bashcompdir@
+# dist_bashcomp_DATA = # completion files go here
+#
+# For cmake we ship the bash-completion-config.cmake and
+# bash-completion-config-version.cmake files. Example usage:
+#
+# find_package(bash-completion)
+# if(BASH_COMPLETION_FOUND)
+# message(STATUS
+# "Using bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}")
+# else()
+# set (BASH_COMPLETION_COMPLETIONSDIR "/etc/bash_completion.d")
+# message (STATUS
+# "Using fallback bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}")
+# endif()
+#
+# install(FILES your-completion-file DESTINATION
+# ${BASH_COMPLETION_COMPLETIONSDIR})
+#
+# For backwards compatibility it is still possible to put it into
+# ~/.bash_completion or /etc/bash_completion.d/.
#
# -----------------------------------------------------------------
#
-# Version 2.6
+# Version 2.9.2
#
# -----------------------------------------------------------------
@@ -56,14 +98,9 @@ shopt -s extglob
# Functions
# -----------------------------------------------------------------
-_ipset_colon_ltrim() {
-((got_bashcompl)) || return 0
-__ltrim_colon_completions "$1"
-}
-
_ipset_is_set() {
local -i idx
-((${#arr_sets[@]})) || arr_sets=( $(ipset list -n) )
+((${#arr_sets[@]})) || arr_sets=( $( ( "${words[0]}" list -n ) 2>/dev/null ) )
for idx in ${!arr_sets[@]}; do
if [[ ${arr_sets[idx]} = $1 ]]; then
return 0
@@ -76,34 +113,32 @@ _ipset_get_set_type() {
local n d
while read n d; do
[[ $n = Type: ]] && printf '%s\n' $d && break
-done < <(ipset -t list "$1" 2>/dev/null)
+done < <( ( "${words[0]}" -t list "$1" ) 2>/dev/null)
}
_ipset_set_has_option() {
while read -r; do
[[ $REPLY = Header:*$1* ]] && return 0
-done < <(ipset -t list "$2")
+done < <( ( "${words[0]}" -t list "$2" ) 2>/dev/null)
return 1
}
_ipset_get_supported_types() {
((${#arr_types[@]})) && return
-local -i i=0
+local -i i=0 x
while read -r; do
[[ $REPLY = "Supported set types:"* ]] && ((!i)) && i=1 && continue
((i)) || continue
if [[ $REPLY = *:* ]]; then
set -- $REPLY
- arr_types+=("$1")
+ for x in ${!arr_types[@]}; do # check if already registered
+ if [[ $1 = ${arr_types[x]} ]]; then
+ continue 2
+ fi
+ done
+ arr_types+=("$1") # register type
fi
-done < <(ipset help)
-for i in ${!arr_types[@]}; do # remove dupe entries
- for ((x=i+1; x < ${#arr_types[@]}; x++)); do
- if [[ ${arr_types[i]} = ${arr_types[x]} ]]; then
- unset arr_types[x]
- fi
- done
-done
+done < <( ( "${words[0]}" help ) 2>/dev/null )
}
_ipset_get_members() {
@@ -120,7 +155,7 @@ while read -r; do
else
arr_members+=("$REPLY")
fi
-done < <(ipset list "$1" 2>/dev/null)
+done < <( ( "${words[0]}" list "$1" ) 2>/dev/null)
}
_ipset_get_set_family() {
@@ -128,7 +163,7 @@ while read -r; do
[[ $REPLY = Header:*"family inet6"* ]] && printf "v6\n" && return
[[ $REPLY = Header:*"family inet "* ]] && printf "v4\n" && return
[[ $REPLY = Header:*"range "*.*.*.* ]] && printf "v4\n" && return
-done < <(ipset -t list "$1")
+done < <( ( "${words[0]}" -t list "$1" ) 2>/dev/null)
}
_ipset_dedupe_cmd_opts() {
@@ -152,35 +187,28 @@ _ipset_get_options() {
local str_list
local -i idx oidx ridx
if ((got_action)); then
- case "$str_action" in
- rename|e|swap|w|test|flush|destroy|x)
- str_list='-q -quiet'
- ;;
- save)
- str_list='-f -file -q -quiet'
- ;;
- create|n|add|del)
- str_list='-! -exist -q -quiet'
- ;;
- restore)
- str_list='-! -exist -f -file -q -quiet'
- ;;
- list)
- str_list='-f -file -q -quiet'
- if ((names_only || headers_only)); then
- str_list+=' -o -output'
- elif ((res_sort)); then
- str_list+=' -o -output -r -resolve -s -sorted'
- elif ((save_format == 1)); then
- str_list+=' -r -resolve -s -sorted -t -terse'
- elif ((save_format == 3)); then
- str_list+=' -r -resolve -s -sorted'
- else
- str_list+=' -n -name -o -output -r -resolve \
- -s -sorted -t -terse'
- fi
- ;;
- esac
+ if [[ $str_action = @(rename|e|swap|w|test|flush|destroy|x) ]]; then
+ str_list='-q -quiet'
+ elif [[ $str_action = save ]]; then
+ str_list='-f -file -q -quiet -o -output'
+ elif [[ $str_action = @(create|n|add|del) ]]; then
+ str_list='-! -exist -q -quiet'
+ elif [[ $str_action = restore ]]; then
+ str_list='-! -exist -f -file -q -quiet'
+ elif [[ $str_action = list ]]; then
+ str_list='-f -file -q -quiet'
+ if ((names_only || headers_only)); then
+ str_list+=' -o -output'
+ elif ((res_sort)); then
+ str_list+=' -o -output -r -resolve -s -sorted'
+ elif ((save_format == 1)); then
+ str_list+=' -r -resolve -s -sorted -t -terse'
+ elif ((save_format == 3)); then
+ str_list+=' -r -resolve -s -sorted'
+ else
+ str_list+=' -n -name -o -output -r -resolve -s -sorted -t -terse'
+ fi
+ fi
else
str_list='-f -file -q -quiet'
if ((names_only || headers_only)) && ((save_format == 1)); then
@@ -196,8 +224,8 @@ else
elif ((ignore_errors)); then
:
elif ((use_file)); then
- str_list='-! -exist -n -name -o -output -q -quiet -r \
- -resolve -s -sorted -t -terse'
+ str_list="-! -exist -n -name -o -output -q -quiet -r \
+ -resolve -s -sorted -t -terse"
else
str_list='- ${arr_opts[@]}'
fi
@@ -334,7 +362,7 @@ _ipset_get_ifnames() {
while read -r; do
REPLY="${REPLY#*: }"
printf "%s\n" ${REPLY%%:*}
-done < <(PATH=${PATH}:/sbin command ip -o link show)
+done < <(PATH=${PATH}:/sbin ( command ip -o link show ) 2>/dev/null)
}
_ipset_get_iplist() {
@@ -412,7 +440,7 @@ fi
if [[ $str_p ]]; then # we have a proto spec
COMPREPLY=( $(compgen -P "$str_p:$str_lprefix" \
-W '$(_ipset_get_services -o $str_var -p $str_p)' -- "$lcur" ) )
- _ipset_colon_ltrim "$str_p:$str_lprefix$lcur"
+ __ltrim_colon_completions "$str_p:$str_lprefix$lcur"
else
if [[ $str_lprefix ]]; then
COMPREPLY=( $(compgen -P "$str_lprefix" \
@@ -447,7 +475,6 @@ for idx in ${!COMPREPLY[@]}; do
((got_bracket)) && unset COMPREPLY[idx]
fi
done
-#_ipset_colon_ltrim "$lcur"
}
_ipset_complete_iface_spec() {
@@ -486,7 +513,7 @@ if [[ $lcur != *,* ]]; then
COMPREPLY=( ${COMPREPLY[*]}, ${COMPREPLY[*]}- )
fi
fi
- _ipset_colon_ltrim "$str_lprefix$lcur"
+ __ltrim_colon_completions "$str_lprefix$lcur"
elif [[ $lcur = *,* ]]; then
str_lprefix="${lcur}" lcur="${lcur#*,}" str_var=""
str_lprefix="${str_lprefix%"$lcur"}"
@@ -499,7 +526,7 @@ elif [[ $lcur = *,* ]]; then
COMPREPLY+=( $( compgen -P "$str_lprefix" -W \
'${str_var} $(_ipset_get_ifnames)' -- "$lcur" ) )
[[ ${COMPREPLY[0]} = *physdev: ]] && compopt -o nospace
- _ipset_colon_ltrim "$str_lprefix"
+ __ltrim_colon_completions "$str_lprefix"
fi
}
@@ -551,7 +578,7 @@ else
COMPREPLY+=( $( compgen -W \
'$(_ipset_get_iplist "$(_ipset_get_set_family "$str_setname")")' \
-- "$lcur" ) )
- _ipset_colon_ltrim "$lcur"
+ __ltrim_colon_completions "$lcur"
fi
_ipset_complete_hostnames "$lcur"
if [[ $str_lprefix ]]; then
@@ -613,7 +640,7 @@ if [[ $lcur != *,* ]]; then
-- "$lcur" ) )
if [[ $str_type = hash:net,port?(,net) ]]; then
COMPREPLY+=( $( compgen -W '$(_ipset_get_networks)' -- "$lcur" ) )
- _ipset_colon_ltrim "$lcur"
+ __ltrim_colon_completions "$lcur"
fi
_ipset_complete_hostnames "$lcur"
if [[ $str_lprefix ]]; then # range spec
@@ -626,7 +653,7 @@ if [[ $lcur != *,* ]]; then
COMPREPLY=( ${COMPREPLY[*]}, )
fi
fi
- _ipset_colon_ltrim "$str_lprefix$lcur"
+ __ltrim_colon_completions "$str_lprefix$lcur"
elif [[ $lcur =~ $str_regex ]]; then
compopt -o nospace
str_glob='[^[]*-' # otherwise messes up my vim syntax highlightning
@@ -653,7 +680,7 @@ elif [[ $lcur =~ $str_regex ]]; then
if [[ $str_lprefix = *:* ]]; then
str_lprefix="${str_lprefix%:*}:"
fi
- _ipset_colon_ltrim "${str_lprefix}"
+ __ltrim_colon_completions "${str_lprefix}"
if ((${#COMPREPLY[@]} == 1)); then
if [[ $str_lprefix && $str_type != hash:@(ip|net),port,@(ip|net) ]]; then
compopt +o nospace
@@ -676,7 +703,7 @@ elif [[ $lcur =~ $str_regex ]]; then
COMPREPLY+=( $( compgen -P "$str_lprefix" -W \
'$(_ipset_get_services -p $str_var)' -- "$lcur" ) )
fi
- _ipset_colon_ltrim "$str_lprefix"
+ __ltrim_colon_completions "$str_lprefix"
elif [[ $lcur = *,* ]]; then # first attempt :/ long list
str_lprefix="${lcur%,*}," lcur="${lcur#*,}"
str_var="tcp: udp: sctp: udplite: icmp: icmp6:"
@@ -686,7 +713,7 @@ elif [[ $lcur =~ $str_regex ]]; then
# add the protocols
COMPREPLY+=( $( compgen -P "$str_lprefix" -S ":0$str_suffix" -W \
'$(_ipset_get_protocols)' -- "$lcur" ) )
- _ipset_colon_ltrim "$str_lprefix$lcur"
+ __ltrim_colon_completions "$str_lprefix$lcur"
compopt -o nospace
fi
elif [[ $lcur = *,*,* && $str_type = hash:@(ip,port,@(ip|net)|net,port,net) ]]; then
@@ -727,7 +754,7 @@ elif [[ $lcur = *,*,* && $str_type = hash:@(ip,port,@(ip|net)|net,port,net) ]];
COMPREPLY=( $( compgen -P "$str_lprefix2" \
-W '${COMPREPLY[@]}' -- "$lcur2" ) )
fi
- _ipset_colon_ltrim "$str_lprefix2$lcur2"
+ __ltrim_colon_completions "$str_lprefix2$lcur2"
if ((${#COMPREPLY[@]} == 1)); then
if [[ $str_type = hash:@(ip|net),port,net && \
${COMPREPLY[*]##*,} != */* ]]
@@ -802,7 +829,7 @@ if ((y)); then
[[ $addr =~ $str_regex ]] && printf "%s\n" "$addr"
done < /etc/ethers)"
fi
- printf "%s\n" "$str_tmp"
+ printf "%s\n" "$str_tmp"
fi
}
@@ -811,6 +838,8 @@ fi
# -----------------------------------------------------------------
_ipset_complete() {
+# at least bash 4 is required
+((${BASH_VERSINFO[0]} < 4)) && return 0
local cur prev cword words ips_version
local str_action str_setname str_type str_filename
local str_glob str_regex str_prefix str_suffix
@@ -822,7 +851,7 @@ local -i i=x=y=0
local -i got_bashcompl=got_action=action_index=order_index=set_has_timeout=0
local -i got_bp_proto=0
local -i ignore_errors=use_file=names_only=headers_only=save_format=res_sort=0
-local arr_sets=() arr_types=() arr_members=() arr_unknown_opts=()
+local arr_sets=() arr_types=() arr_members=()
local arr_dupe_cmd_opts=() arr_used_opts=() arr_tmp=()
local arr_opts=(
"-! -exist"
@@ -894,19 +923,45 @@ neigbour-advertisement
redirect
)
-# at least bash 4 is required
-((${BASH_VERSINFO[0]} < 4)) && return 0
-
COMPREPLY=()
+# expecting _get_comp_words_by_ref() to exist from bash_completion
+if declare -f _get_comp_words_by_ref &>/dev/null; then got_bashcompl=1
+ _get_comp_words_by_ref -n : cur prev cword words || return
+else got_bashcompl=0 # not so neat, but a workaround
+ COMP_WORDBREAKS="${COMP_WORDBREAKS//:/}"
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+ cword=$COMP_CWORD
+ for i in ${!COMP_WORDS[@]}; do words[i]="${COMP_WORDS[i]}"; done
+fi
+
# ipset version check 6.x upwards (to v?) is supported
-ips_version="$(ipset version)"
-ips_version="${ips_version#ipset v}"
-ips_version="${ips_version%,+([[:blank:]])protocol*}"
-read -a ips_version <<< ${ips_version//./ }
-[[ ${ips_version[0]} = +([[:digit:]]) ]] || return 1
+
+# All calls of ipset should be done in a subshell with stderr
+# pointing to /dev/null, to avoid printing of
+# `-bash command ipset not found' errors
+
+i=0 # for safety
+if ((UID != 0)); then # not root user
+ "${words[0]}" version &>/dev/null # can we retrieve the version?
+ i=$?
+fi
+if ((i == 0)); then
+ ips_version="$("${words[0]}" version)"
+ ips_version="${ips_version#ipset v}"
+ ips_version="${ips_version%,+([[:blank:]])protocol*}"
+ read -a ips_version <<< ${ips_version//./ }
+ [[ ${ips_version[0]} = +([[:digit:]]) ]] || return 1
+else
+ # assume we have no permissions to run ipset
+ # set version to 6.22 = show all features
+ # though many things won't work, as of missing permissions
+ ips_version=( 6 22 )
+fi
((ips_version[0] < 6)) && return 1
+
# ipset -ge v6.19 has counters flag
# ipset -ge v6.20 has comment flag
# ipset -ge v6.21 has hash:ip,mark markmask flag
@@ -938,45 +993,22 @@ elif ((ips_version[0] == 6)); then
str_bp_counters="bytes packets"
fi
else
+ # ipset versions -lt 6 are not supported
return 0
fi
-# expecting _get_comp_words_by_ref() to exist from bash_completion
-if declare -f _get_comp_words_by_ref &>/dev/null; then got_bashcompl=1
- _get_comp_words_by_ref -n : cur prev cword words || return
-else got_bashcompl=0 # not so neat, but a workaround
- COMP_WORDBREAKS="${COMP_WORDBREAKS//:/}"
- cur="${COMP_WORDS[COMP_CWORD]}"
- prev="${COMP_WORDS[COMP_CWORD-1]}"
- cword=$COMP_CWORD
- for i in ${!COMP_WORDS[@]}; do words[i]="${COMP_WORDS[i]}"; done
-fi
-
-if ((got_bashcompl)); then
-# current bash completion got a bug i reported:
-# https://alioth.debian.org/tracker/index.php?func=detail&aid=314056&group_id=100114&atid=413095
-# putting corrected function here, so things don't break
-__ltrim_colon_completions() {
- if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
- # Remove colon-word prefix from COMPREPLY items
- local colon_word="${1%"${1##*:}"}"
- local i=${#COMPREPLY[*]}
- while [[ $((--i)) -ge 0 ]]; do
- COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
- done
- fi
-}
-
# construct own known_hosts function from origin
# just remove the __ltrim_colon_completions call
# to avoid unwanted ltrim if we need to work with the list of hosts
# ugly hack - gimme better ;p
-if ! declare -F _ipset_known_hosts &>/dev/null; then
-eval '_ipset_known_hosts() { '$(declare -f _known_hosts_real | grep -v __ltrim_colon_completions | grep -Ev "^_known_hosts_real.*$" | grep -Ev "^(\{|\})")'; }'
-fi
+if ((got_bashcompl)); then
+ if ! declare -F _ipset_known_hosts &>/dev/null; then
+ eval '_ipset_known_hosts() { '$(declare -f _known_hosts_real | \
+ grep -v __ltrim_colon_completions | \
+ grep -Ev "^_known_hosts_real.*$" | grep -Ev "^(\{|\})")'; }'
+ fi
fi
-#_DEBUG_NF_COMPLETION=Y
if [[ $_DEBUG_NF_COMPLETION ]]; then
printf "\nCOMP_WORDBREAKS: <%s>\n" "$COMP_WORDBREAKS"
printf "COMP_LINE: <%s>\n" "$COMP_LINE"
@@ -991,78 +1023,66 @@ fi
# collect information about used options
for ((i=1; i < ${#words[@]}-1; i++)); do
-case "${words[i]}" in
- @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w|help|version))
- [[ ${words[i-1]} = @(-f|-file) ]] && continue # there could be a file named like a command
- if ! ((got_action)); then
- if [[ ${words[i]} != save ]]; then
- got_action=1 action_index=$i str_action=${words[i]}
- elif [[ ${words[i-1]} != @(-o|-output) ]]; then
- got_action=1 action_index=$i str_action=${words[i]}
- fi
- if [[ $str_action = @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w) ]]
- then str_setname=${words[i+1]} # register the set name
- fi
+if [[ ${words[i]} = @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w|help|version) ]]
+then
+ [[ ${words[i-1]} = @(-f|-file) ]] && continue # could be a file named like a command
+ if ! ((got_action)); then
+ if [[ ${words[i]} != save ]]; then
+ got_action=1 action_index=$i str_action=${words[i]}
+ elif [[ ${words[i-1]} != @(-o|-output) ]]; then
+ got_action=1 action_index=$i str_action=${words[i]}
fi
- ;;
- -\!|-exist)
- [[ ${words[i-1]} != @(-f|-file) ]] &&\
- ignore_errors=1 arr_used_opts+=(${words[i]})
- ;;
- -f|-file)
- [[ ${words[i-1]} != @(-f|-file) ]] &&\
- use_file=1 str_filename="${words[i+1]}" \
- arr_used_opts+=(${words[i]})
- ;;
- -n|-name)
- [[ ${words[i-1]} != @(-f|-file) ]] &&\
- names_only=1 arr_used_opts+=(${words[i]})
- ;;
- -t|-terse)
- [[ ${words[i-1]} != @(-f|-file) ]] &&\
- headers_only=1 arr_used_opts+=(${words[i]})
- ;;
- -o|-output)
- if [[ ${words[i-1]} != @(-f|-file) ]]; then
- arr_used_opts+=(${words[i]})
- if [[ $prev = @(-o|-output) ]]; then
- save_format=2 # expecting opt-arg
- elif [[ ${words[i+1]} = save ]]; then
- save_format=3 # no -n/-t with -o save
- else
- save_format=1
- fi
+ if [[ $str_action = @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w) ]]
+ then
+ str_setname=${words[i+1]} # register the set name
fi
- ;;
- -r|-resolve|-s|-sorted)
- [[ ${words[i-1]} != @(-f|-file) ]] &&\
- res_sort=1 arr_used_opts+=(${words[i]})
- ;;
- -q|-quiet)
+ fi
+elif [[ ${words[i]} = @(-\!|-exist) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
+ ignore_errors=1 arr_used_opts+=(${words[i]})
+ fi
+elif [[ ${words[i]} = @(-f|-file) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
+ use_file=1 str_filename="${words[i+1]}" arr_used_opts+=(${words[i]})
+ fi
+elif [[ ${words[i]} = @(-n|-name) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
+ names_only=1 arr_used_opts+=(${words[i]})
+ fi
+elif [[ ${words[i]} = @(-t|-terse) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
+ headers_only=1 arr_used_opts+=(${words[i]})
+ fi
+elif [[ ${words[i]} = @(-o|-output) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
arr_used_opts+=(${words[i]})
- ;;
-# -?*)
-# if [[ ${words[i]#-} != @(q|quiet) ]]; then
-# # don't include filenames
-# if [[ ${words[i-1]} != @(-f|-file|\>) || ${words[i+1]} != \< ]]; then
-# arr_unknown_opts[${#arr_unknown_opts[@]}]="${words[i]}"
-# fi
-# fi
-# ;;
- before|after)
- if ((got_action && ! order_index && i == action_index+3)); then
- order_index=$i str_order=""
- fi
- ;;
- timeout|range|maxelem|family|hashsize|size|netmask|nomatch|counters|bytes|packets|comment|markmask|forceadd|skbinfo|skbmark|skbprio|skbqueue)
- if ((got_action && i > action_index+2)); then
- str_tmp="$COMP_LINE"
- [[ $str_setname = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}"
- [[ $str_filename = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}"
- [[ $str_tmp = *${words[i]}* ]] && arr_dupe_cmd_opts[${#arr_dupe_cmd_opts[@]}]="${words[i]}"
+ if [[ $prev = @(-o|-output) ]]; then
+ save_format=2 # expecting opt-arg
+ elif [[ ${words[i+1]} = save ]]; then
+ save_format=3 # no -n/-t with -o save
+ else
+ save_format=1
fi
- ;;
-esac
+ fi
+elif [[ ${words[i]} = @(-r|-resolve|-s|-sorted) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
+ res_sort=1 arr_used_opts+=(${words[i]})
+ fi
+elif [[ ${words[i]} = @(-q|-quiet) ]]; then
+ arr_used_opts+=(${words[i]})
+elif [[ ${words[i]} = @(before|after) ]]; then
+ if ((got_action && ! order_index && i == action_index+3)); then
+ order_index=$i str_order=""
+ fi
+elif [[ ${words[i]} = @(timeout|range|maxelem|family|hashsize|size|netmask|nomatch|counters|bytes|packets|comment|markmask|forceadd|skbinfo|skbmark|skbprio|skbqueue) ]]
+then
+ if ((got_action && i > action_index+2)); then
+ str_tmp="$COMP_LINE"
+ [[ $str_setname = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}"
+ [[ $str_filename = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}"
+ [[ $str_tmp = *${words[i]}* ]] && arr_dupe_cmd_opts[${#arr_dupe_cmd_opts[@]}]="${words[i]}"
+ fi
+fi
done
if [[ $_DEBUG_NF_COMPLETION ]]; then
@@ -1076,7 +1096,6 @@ if [[ $_DEBUG_NF_COMPLETION ]]; then
printf "ignore_errors: <%s>\n" "$ignore_errors"
printf "names_only: <%s>\n" "$names_only"
printf "headers_only: <%s>\n" "$headers_only"
-# printf "arr_unknown_opts: <%s>\n" "${arr_unknown_opts[@]}"
printf "arr_used_opts: <%s>\n" "${arr_used_opts[@]}"
printf "arr_dupe_cmd_opts: <%s>\n" "${arr_dupe_cmd_opts[@]}"
fi
@@ -1094,13 +1113,6 @@ elif ((ignore_errors)); then
fi
fi
-#case "$cur" in # depend on current
-# \<|\>) # redirection operator
-# compopt -o nospace
-# COMPREPLY=( $( compgen -f ) ) # no $cur, so completion starts without space after redirection
-# return 0
-# ;;
-#esac
# catch variables and command substitution
if [[ $cur == \$\(* ]]; then # command substitution
COMPREPLY=( $(compgen -c -P '$(' ${cur#??}) )
@@ -1113,28 +1125,26 @@ elif [[ $cur == \$* ]]; then # variables with a leading `$'
return 0
fi
-case "$prev" in # depend on previous option
- -o|-output)
- # make sure it's not a filename named -o or -output
- if [[ $str_filename != $prev ]]; then
- if ((names_only || headers_only)); then
- COMPREPLY=( $( compgen -W 'plain xml' -- "$cur" ) )
- else
- COMPREPLY=( $( compgen -W 'plain save xml' -- "$cur" ) )
- fi
- return 0
- fi
- ;;
- -f|-file|\<|\>)
- if ((got_bashcompl)); then
- _filedir
+# depend on previous option
+if [[ $prev = @(-o|-output) ]]; then
+ # make sure it's not a filename named -o or -output
+ if [[ $str_filename != $prev ]]; then
+ if ((names_only || headers_only)); then
+ COMPREPLY=( $( compgen -W 'plain xml' -- "$cur" ) )
else
- compopt -o nospace
- COMPREPLY=( $( compgen -f -- "$cur" ) )
+ COMPREPLY=( $( compgen -W 'plain save xml' -- "$cur" ) )
fi
return 0
- ;;
-esac
+ fi
+elif [[ $prev = @(-f|-file|\<|\>) ]]; then
+ if ((got_bashcompl)); then
+ _filedir
+ else
+ compopt -o nospace
+ COMPREPLY=( $( compgen -f -- "$cur" ) )
+ fi
+ return 0
+fi
if ((got_action)); then # we got the main action
# Disallow sets with names of options starting with a hyphen
@@ -1147,412 +1157,374 @@ then
fi
if ((cword == action_index+1)) && [[ $str_action = $prev ]]; then
# depend on previous option which should be the action
- case "$str_action" in
-# create|n|version) :
-# ;;
- help)
- _ipset_get_supported_types
- COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- ;;
- add|del|rename|e|swap|w|test)
- COMPREPLY=( $( compgen -W '$(ipset list -n)' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- ;;
- list|flush|save|destroy|x)
- # we don't know if its an option request, could also be a set
- # named `-*', if the latter is true, show sets and options
- if [[ $cur = -* ]]; then
- _ipset_get_options
- if _ipset_is_set "${cur}*"; then
- COMPREPLY=( $( compgen -W '${arr_sets[@]}' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- fi
- else
- COMPREPLY=( $( compgen -W '$(ipset list -n)' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- fi
- ;;
- restore)
- if [[ $cur = -* ]]; then
- _ipset_get_options
- elif ! [[ $str_filename ]]; then
- # don't show redirector if we have option -f
- COMPREPLY=( \< )
+ # create|n|version - take no aktion
+ if [[ $str_action = help ]]; then
+ _ipset_get_supported_types
+ COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_action = @(add|del|rename|e|swap|w|test) ]]; then
+ COMPREPLY=( $( compgen -W '$( ( "${words[0]}" list -n ) 2>/dev/null )' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_action = @(list|flush|save|destroy|x) ]]; then
+ # we don't know if its an option request, could also be a set
+ # named `-*', if the latter is true, show sets and options
+ if [[ $cur = -* ]]; then
+ _ipset_get_options
+ if _ipset_is_set "${cur}*"; then
+ COMPREPLY=( $( compgen -W '${arr_sets[@]}' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
fi
- ;;
- esac
+ else
+ COMPREPLY=( $( compgen -W '$( ( "${words[0]}" list -n ) 2>/dev/null )' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_action = restore ]]; then
+ if [[ $cur = -* ]]; then
+ _ipset_get_options
+ elif ! [[ $str_filename ]]; then
+ # don't show redirector if we have option -f
+ COMPREPLY=( \< )
+ fi
+ fi
elif ((cword == action_index+2)) && [[ $str_setname = $prev ]]; then
- case "$str_action" in
-# rename|e) :
-# ;;
- save|restore|list|flush|destroy|x)
- if [[ $cur = -* ]]; then
- _ipset_get_options
+ # rename|e - take no aktion
+ if [[ $str_action = @(save|restore|list|flush|destroy|x) ]]; then
+ if [[ $cur = -* ]]; then
+ _ipset_get_options
+ fi
+ elif [[ $str_action = @(create|n) ]]; then
+ _ipset_get_supported_types
+ COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_action = @(swap|w) ]]; then # list two sets
+ COMPREPLY=( $( compgen -W '$( ( "${words[0]}" list -n ) 2>/dev/null )' -- "$cur" ) )
+ for i in ${!COMPREPLY[@]}; do # remove the dupe setname from the list
+ [[ ${COMPREPLY[i]} = $str_setname ]] && unset COMPREPLY[i] && break
+ done
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_action = add ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if [[ $str_type = bitmap:ip ]]; then
+ _ipset_complete_host_spec "$cur" --v4
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_type = @(hash:ip|hash:net|hash:ip,mark) ]]; then
+ _ipset_complete_host_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_type = hash:net,iface ]]; then
+ _ipset_complete_iface_spec "$cur"
+ elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]]
+ then
+ _ipset_complete_hostport_spec "$cur"
+ elif [[ $str_type = hash:net,net ]]; then
+ _ipset_complete_netnet_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_type = hash:mac ]]; then
+ COMPREPLY=( $( compgen -W '$(_ipset_complete_mac_spec)' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_type = bitmap:ip,mac ]]; then
+ if [[ $cur = *,* ]]; then
+ str_prefix="$cur" cur="${cur#*,}"
+ str_prefix="${str_prefix%$cur}"
+ COMPREPLY+=( $( compgen -P "$str_prefix" -W '$(_ipset_complete_mac_spec)' \
+ -- "$cur" ) )
+ __ltrim_colon_completions "$str_prefix$cur"
+ else
+ compopt -o nospace
+ _ipset_complete_host_spec "$cur" --v4 --no-range
+ __ltrim_colon_completions "$cur"
+ if ((${#COMPREPLY[@]} == 1)); then
+ COMPREPLY=( ${COMPREPLY[*]}, )
+ fi
fi
- ;;
- @(create|n))
- _ipset_get_supported_types
- COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- ;;
- @(swap|w)) # list two sets
- COMPREPLY=( $( compgen -W '$(ipset list -n)' -- "$cur" ) )
- for i in ${!COMPREPLY[@]}; do # remove the dupe setname from the list
- [[ ${COMPREPLY[i]} = $str_setname ]] && unset COMPREPLY[i] && break
+ elif [[ $str_type = bitmap:port ]]; then # complete port [range]
+ _ipset_complete_portrange "$cur"
+ elif [[ $str_type = list:* ]]; then
+ # show sets if the set to add is of type list:set
+ arr_tmp=() arr_sets=( $( ( "${words[0]}" list -n ) 2>/dev/null ) )
+ _ipset_get_members --names-only "$str_setname"
+ for x in ${!arr_sets[@]}; do
+ [[ ${arr_sets[x]} = $str_setname ]] && continue
+ for y in ${!arr_members[@]}; do
+ [[ ${arr_sets[x]} = ${arr_members[y]} ]] && continue 2
+ done
+ arr_tmp+=("${arr_sets[x]}")
done
- _ipset_colon_ltrim "$cur"
- ;;
- add)
- str_type=$(_ipset_get_set_type "$str_setname")
- case "$str_type" in
- bitmap:ip)
- _ipset_complete_host_spec "$cur" --v4
- _ipset_colon_ltrim "$cur"
- ;;
- hash:ip|hash:net|hash:ip,mark)
- _ipset_complete_host_spec "$cur"
- _ipset_colon_ltrim "$cur"
- ;;
- hash:net,iface)
- _ipset_complete_iface_spec "$cur"
- ;;
- hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net))
- _ipset_complete_hostport_spec "$cur"
- ;;
- hash:net,net)
- _ipset_complete_netnet_spec "$cur"
- _ipset_colon_ltrim "$cur"
- ;;
- hash:mac)
- COMPREPLY=( $( compgen -W '$(_ipset_complete_mac_spec)' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- ;;
- bitmap:ip,mac)
- if [[ $cur = *,* ]]; then
- str_prefix="$cur" cur="${cur#*,}"
- str_prefix="${str_prefix%$cur}"
- COMPREPLY+=( $( compgen -P "$str_prefix" -W '$(_ipset_complete_mac_spec)' \
- -- "$cur" ) )
- _ipset_colon_ltrim "$str_prefix$cur"
- else
- compopt -o nospace
- _ipset_complete_host_spec "$cur" --v4 --no-range
- _ipset_colon_ltrim "$cur"
- if ((${#COMPREPLY[@]} == 1)); then
- COMPREPLY=( ${COMPREPLY[*]}, )
+ COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_action = del ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if [[ $str_type = bitmap:ip ]]; then
+ str_prefix=""
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur" --v4
+ __ltrim_colon_completions "$cur"
+ else
+ _ipset_complete_host_spec "$cur" --v4
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_type = bitmap:port ]]; then
+ str_prefix=""
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_portrange "$cur"
+ else
+ _ipset_complete_portrange "$cur"
+ _ipset_get_members --names-only "$str_setname"
+ str_glob='?(tcp:|udp:)@([![]*-*|\[?*\]-*)'
+ if [[ $cur = $str_glob ]]; then
+ str_var="${cur#?(tcp:|udp:)}" # offset
+ str_tmp="${cur%"$str_var"}" # proto
+ # identify service number by name, to find the offset
+ if [[ $str_var != +([[:digit:]]) ]]; then
+ if [[ $str_var = \[+([![])\]-* ]]; then
+ str_var="${str_var%%\]*}"
+ str_var="${str_var#\[}"
+ elif [[ $str_var = *-* ]]; then
+ str_var="${str_var%%-*}"
fi
+ str_var=$(_ipset_get_svnum -p "${str_tmp:-all}" -o "$str_var")
fi
- ;;
- bitmap:port)
- # complete port [range]
- _ipset_complete_portrange "$cur"
- ;;
- # show sets if the set to add is of type list:set
- list:*) arr_tmp=() arr_sets=( $(ipset list -n) )
- _ipset_get_members --names-only "$str_setname"
- for x in ${!arr_sets[@]}; do
- [[ ${arr_sets[x]} = $str_setname ]] && continue
- for y in ${!arr_members[@]}; do
- [[ ${arr_sets[x]} = ${arr_members[y]} ]] && continue 2
+ if [[ $str_var = +([[:digit:]]) ]]; then
+ for i in ${!arr_members[@]}; do
+ ((${arr_members[i]} <= $str_var)) && \
+ unset arr_members[i] || break
done
- arr_tmp+=("${arr_sets[x]}")
- done
- COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- ;;
- esac
- ;;
- del)
- str_type=$(_ipset_get_set_type "$str_setname")
- if [[ $str_type = bitmap:ip ]]; then
- str_prefix=""
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur" --v4
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_host_spec "$cur" --v4
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = bitmap:port ]]; then
- str_prefix=""
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_portrange "$cur"
- else
- _ipset_complete_portrange "$cur"
- _ipset_get_members --names-only "$str_setname"
- str_glob='?(tcp:|udp:)@([![]*-*|\[?*\]-*)'
- if [[ $cur = $str_glob ]]; then
- str_var="${cur#?(tcp:|udp:)}" # offset
- str_tmp="${cur%"$str_var"}" # proto
- # identify service number by name, to find the offset
- if [[ $str_var != +([[:digit:]]) ]]; then
- if [[ $str_var = \[+([![])\]-* ]]; then
- str_var="${str_var%%\]*}"
- str_var="${str_var#\[}"
- elif [[ $str_var = *-* ]]; then
- str_var="${str_var%%-*}"
- fi
- str_var=$(_ipset_get_svnum -p "${str_tmp:-all}" -o "$str_var")
- fi
- if [[ $str_var = +([[:digit:]]) ]]; then
- for i in ${!arr_members[@]}; do
- ((${arr_members[i]} <= $str_var)) && \
- unset arr_members[i] || break
- done
- fi
- str_prefix="${cur%-*}-" cur="${cur##*-}"
fi
- COMPREPLY+=( $( compgen -P "$str_prefix" -W '${arr_members[@]}' -- "$cur" ) )
- fi
- elif [[ $str_type = bitmap:ip,mac ]]; then
- str_prefix=""
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur" --v4 --no-range
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_host_spec "$cur" --v4 --no-range
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:@(ip?(,mark)|net) ]]; then
- str_prefix=""
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur"
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_host_spec "$cur"
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:net,net ]]; then
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_netnet_spec "$cur"
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_netnet_spec "$cur"
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]]
- then
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_hostport_spec "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- _ipset_complete_hostport_spec "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:net,iface ]]; then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_iface_spec "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- _ipset_complete_iface_spec "$cur"
- _ipset_colon_ltrim "$cur"
+ str_prefix="${cur%-*}-" cur="${cur##*-}"
fi
+ COMPREPLY+=( $( compgen -P "$str_prefix" -W '${arr_members[@]}' -- "$cur" ) )
+ fi
+ elif [[ $str_type = bitmap:ip,mac ]]; then
+ str_prefix=""
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur" --v4 --no-range
+ __ltrim_colon_completions "$cur"
else
+ _ipset_complete_host_spec "$cur" --v4 --no-range
_ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
+ __ltrim_colon_completions "$cur"
fi
- ;;
- test)
- str_type=$(_ipset_get_set_type "$str_setname")
- if [[ $str_type = bitmap:ip ]]; then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur" --no-range --v4
- else
- _ipset_complete_elements "$cur" --no-range
- if ! _ipset_complete_host_spec "$cur" --no-range --v4; then
- COMPREPLY=()
- fi
- fi
- elif [[ $str_type = hash:ip?(,mark) ]]; then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- if ! _ipset_complete_host_spec "$cur" --no-range; then
- COMPREPLY=()
- fi
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:net ]]; then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur"
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- if ! _ipset_complete_host_spec "$cur"; then
- COMPREPLY=()
- fi
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]]
- then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_hostport_spec "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- _ipset_complete_hostport_spec "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:net,iface ]]; then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_iface_spec "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- _ipset_complete_iface_spec "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = bitmap:port ]]; then
- str_prefix="" str_tmp="$cur"
- if [[ $cur = @(tcp|udp):* ]]; then
- ((got_bp_proto)) || return 0 # supported since ipset v6.20
- str_prefix="${cur%:*}"
- str_tmp="${str_tmp#${str_prefix}:}"
- fi
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- if ((got_bp_proto)); then # supported since ipset v6.20
- COMPREPLY=( $(compgen -W \
- 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) )
- [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace
- _ipset_colon_ltrim "$cur"
- else # only tcp services prior to ipset v6.20
- COMPREPLY=( $(compgen \
- -W '$(_ipset_get_services -p tcp)' -- "$cur" ) )
- fi
- else
- if ((got_bp_proto)); then # supported since ipset v6.20
- COMPREPLY=( $(compgen -W \
- 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) )
- [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace
- _ipset_colon_ltrim "$cur"
- else # only tcp services prior to ipset v6.20
- COMPREPLY=( $(compgen \
- -W '$(_ipset_get_services -p tcp)' -- "$cur" ) )
- fi
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
+ elif [[ $str_type = hash:@(ip?(,mark)|net) ]]; then
+ str_prefix=""
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ else
+ _ipset_complete_host_spec "$cur"
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_type = hash:net,net ]]; then
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_netnet_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ else
+ _ipset_complete_netnet_spec "$cur"
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]]
+ then
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_hostport_spec "$cur"
+ else
+ _ipset_complete_elements "$cur" --no-range
+ _ipset_complete_hostport_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_type = hash:net,iface ]]; then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_iface_spec "$cur"
+ else
+ _ipset_complete_elements "$cur" --no-range
+ _ipset_complete_iface_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ fi
+ else
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_action = test ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if [[ $str_type = bitmap:ip ]]; then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur" --no-range --v4
+ else
+ _ipset_complete_elements "$cur" --no-range
+ if ! _ipset_complete_host_spec "$cur" --no-range --v4; then
+ COMPREPLY=()
fi
+ fi
+ elif [[ $str_type = hash:ip?(,mark) ]]; then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur" --no-range
+ __ltrim_colon_completions "$cur"
else
_ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
+ if ! _ipset_complete_host_spec "$cur" --no-range; then
+ COMPREPLY=()
+ fi
+ __ltrim_colon_completions "$cur"
fi
- ;;
- esac
-elif ((cword == action_index+3)) && [[ $cur != -* ]]; then
- case "$str_action" in
- add)
- str_type=$(_ipset_get_set_type "$str_setname")
- if _ipset_set_has_option timeout "$str_setname"; then
- str_timeout=timeout
+ elif [[ $str_type = hash:net ]]; then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur"
+ __ltrim_colon_completions "$cur"
else
- str_timeout=""
+ _ipset_complete_elements "$cur" --no-range
+ if ! _ipset_complete_host_spec "$cur"; then
+ COMPREPLY=()
+ fi
+ __ltrim_colon_completions "$cur"
fi
- if ! _ipset_set_has_option counters "$str_setname"; then
- str_bp_counters=""
+ elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]]
+ then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_hostport_spec "$cur"
+ else
+ _ipset_complete_elements "$cur" --no-range
+ _ipset_complete_hostport_spec "$cur"
+ __ltrim_colon_completions "$cur"
fi
- if ! _ipset_set_has_option comment "$str_setname"; then
- str_comment=""
+ elif [[ $str_type = hash:net,iface ]]; then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_iface_spec "$cur"
+ else
+ _ipset_complete_elements "$cur" --no-range
+ _ipset_complete_iface_spec "$cur"
+ __ltrim_colon_completions "$cur"
fi
- if ! _ipset_set_has_option skbinfo "$str_setname"; then
- str_skbflags=""
+ elif [[ $str_type = bitmap:port ]]; then
+ str_prefix="" str_tmp="$cur"
+ if [[ $cur = @(tcp|udp):* ]]; then
+ ((got_bp_proto)) || return 0 # supported since ipset v6.20
+ str_prefix="${cur%:*}"
+ str_tmp="${str_tmp#${str_prefix}:}"
fi
- case "$str_type" in
- hash:*net*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \
- -- "$cur" ) )
- ;;
- hash:*!(net)*|bitmap:*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_skbflags $str_comment)' \
- -- "$cur" ) )
- ;;
- list:*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_skbflags $str_comment)' \
- -- "$cur" ) )
- ;;
- esac
- ;;
- create|n)
- case "$prev" in
- hash:ip,mark)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_markmask $str_comment $str_forceadd)' \
- -- "$cur" ) )
- ;;
- hash:*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_comment $str_forceadd)' \
- -- "$cur" ) )
- ;;
- bitmap:ip)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_skbinfo $str_comment)' \
- -- "$cur" ) )
- ;;
- bitmap:!(ip)?*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_skbinfo $str_comment)' \
- -- "$cur" ) )
- ;;
- list:*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_skbinfo $str_comment)' \
- -- "$cur" ) )
- ;;
- esac
- ;;
- del|test)
- str_type=$(_ipset_get_set_type "$str_setname")
- if [[ $str_type = list:* ]]; then
- COMPREPLY=( $( compgen -W '$str_order' -- "$cur" ) )
- elif [[ $str_action = test && $str_type = hash:*net* ]]; then
- COMPREPLY=( $( compgen -W 'nomatch' -- "$cur" ) )
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ if ((got_bp_proto)); then # supported since ipset v6.20
+ COMPREPLY=( $(compgen -W \
+ 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) )
+ [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace
+ __ltrim_colon_completions "$cur"
+ else # only tcp services prior to ipset v6.20
+ COMPREPLY=( $(compgen \
+ -W '$(_ipset_get_services -p tcp)' -- "$cur" ) )
+ fi
+ else
+ if ((got_bp_proto)); then # supported since ipset v6.20
+ COMPREPLY=( $(compgen -W \
+ 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) )
+ [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace
+ __ltrim_colon_completions "$cur"
+ else # only tcp services prior to ipset v6.20
+ COMPREPLY=( $(compgen -W '$(_ipset_get_services -p tcp)' -- "$cur" ) )
+ fi
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
fi
- ;;
- esac
+ else
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ fi
+ fi
+elif ((cword == action_index+3)) && [[ $cur != -* ]]; then
+ if [[ $str_action = add ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if _ipset_set_has_option timeout "$str_setname"; then
+ str_timeout=timeout
+ else
+ str_timeout=""
+ fi
+ if ! _ipset_set_has_option counters "$str_setname"; then
+ str_bp_counters=""
+ fi
+ if ! _ipset_set_has_option comment "$str_setname"; then
+ str_comment=""
+ fi
+ if ! _ipset_set_has_option skbinfo "$str_setname"; then
+ str_skbflags=""
+ fi
+ if [[ $str_type = hash:*net* ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \
+ -- "$cur" ) )
+ elif [[ $str_type = @(hash:*!(net)*|bitmap:*) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_skbflags $str_comment)' \
+ -- "$cur" ) )
+ elif [[ $str_type = list:* ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_skbflags $str_comment)' \
+ -- "$cur" ) )
+ fi
+ elif [[ $str_action = @(create|n) ]]; then
+ if [[ $prev = hash:ip,mark ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_markmask $str_comment $str_forceadd)' \
+ -- "$cur" ) )
+ elif [[ $prev = hash:* ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_comment $str_forceadd)' \
+ -- "$cur" ) )
+ elif [[ $prev = bitmap:ip ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_skbinfo $str_comment)' \
+ -- "$cur" ) )
+ elif [[ $prev = bitmap:!(ip)?* ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_skbinfo $str_comment)' \
+ -- "$cur" ) )
+ elif [[ $prev = list:* ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_skbinfo $str_comment)' \
+ -- "$cur" ) )
+ fi
+ elif [[ $str_action = @(del|test) ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if [[ $str_type = list:* ]]; then
+ COMPREPLY=( $( compgen -W '$str_order' -- "$cur" ) )
+ elif [[ $str_action = test && $str_type = hash:*net* ]]; then
+ COMPREPLY=( $( compgen -W 'nomatch' -- "$cur" ) )
+ fi
+ fi
elif ((cword == action_index+3)) && [[ $cur = -* ]]; then
_ipset_get_options
elif ((cword >= action_index+4)) && [[ $cur = -* ]]; then # add all following hyphen options
@@ -1561,207 +1533,180 @@ elif ((cword >= action_index+4)) && [[ $cur = -* ]]; then # add all following hy
_ipset_get_options
fi
elif ((cword >= action_index+4)); then # add all following non-hyphen options
- case "$str_action" in
- add)
- str_type=$(_ipset_get_set_type "$str_setname")
- if _ipset_set_has_option timeout "$str_setname"; then
- str_timeout=timeout
- else
- str_timeout=""
- fi
- if ! _ipset_set_has_option counters "$str_setname"; then
- str_bp_counters=""
+ if [[ $str_action = add ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if _ipset_set_has_option timeout "$str_setname"; then
+ str_timeout=timeout
+ else
+ str_timeout=""
+ fi
+ if ! _ipset_set_has_option counters "$str_setname"; then
+ str_bp_counters=""
+ fi
+ if ! _ipset_set_has_option comment "$str_setname"; then
+ str_comment=""
+ fi
+ if ! _ipset_set_has_option skbinfo "$str_setname"; then
+ str_skbflags=""
+ fi
+ # validate option argument values
+ if [[ $_IPSET_VALIDATE_INPUT ]]; then
+ for ((x=$action_index+3; x < ${#words[@]}; x++)); do
+ if [[ ${words[x]} = @(timeout|bytes|packets) ]]; then
+ [[ ${words[x+1]} = @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] || return 0
+ elif [[ ${words[x]} = skbmark ]]; then
+ if [[ ${words[x+1]} = 0[xX]+([[:xdigit:]])?(/0[xX]+([[:xdigit:]])) ]]; then
+ (( ${words[x+1]%/*} >= 0 && ${words[x+1]%/*} <= 0xFFFFFFFF )) || return 0
+ (( ${words[x+1]#*/} >= 0 && ${words[x+1]#*/} <= 0xFFFFFFFF )) || return 0
+ else
+ return 0
+ fi
+ elif [[ ${words[x]} = skbprio ]]; then
+ [[ ${words[x+1]} = +([[:xdigit:]]):?(+([[:xdigit:]])) ]] || return 0
+ elif [[ ${words[x]} = skbqueue ]]; then
+ [[ ${words[x+1]} = +([[:digit:]]) ]] || return 0
+ fi
+ done
+ fi
+ if [[ $str_type = hash:*net* ]]; then
+ if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \
+ -- "$cur" ) )
fi
- if ! _ipset_set_has_option comment "$str_setname"; then
- str_comment=""
+ elif [[ $str_type = @(hash:*!(net)*|bitmap:*) ]]; then
+ if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags)' \
+ -- "$cur" ) )
fi
- if ! _ipset_set_has_option skbinfo "$str_setname"; then
- str_skbflags=""
+ elif [[ $str_type = list:* ]]; then
+ if [[ $prev = @(before|after) ]] && ((cword-1 == order_index)); then
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ elif [[ $prev != @(timeout|bytes|packets|skbmark|skbprio|skbqueue) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_comment $str_skbflags)' \
+ -- "$cur" ) )
fi
- # validate option argument values
- if [[ ${_IPSET_VALIDATE_INPUT-1} ]]; then
- for ((x=$action_index+3; x < ${#words[@]}; x++)); do
- if [[ ${words[x]} = @(timeout|bytes|packets) ]]; then
- [[ ${words[x+1]} = @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] || return 0
- elif [[ ${words[x]} = skbmark ]]; then
- if [[ ${words[x+1]} = 0[xX]+([[:xdigit:]])?(/0[xX]+([[:xdigit:]])) ]]; then
- (( ${words[x+1]%/*} >= 0 && ${words[x+1]%/*} <= 0xFFFFFFFF )) || return 0
- (( ${words[x+1]#*/} >= 0 && ${words[x+1]#*/} <= 0xFFFFFFFF )) || return 0
+ fi
+ elif [[ $str_action = @(create|n) ]]; then
+ # validate option argument values
+ if [[ $_IPSET_VALIDATE_INPUT ]]; then
+ for ((x=$action_index+3; x < ${#words[@]}; x++)); do
+ if [[ ${words[x+1]} && ${words[x+1]} != $cur ]]; then
+ if [[ ${words[x]} = @(hashsize|timeout|size|maxelem|markmask) ]]; then
+ [[ ${words[x+1]} != @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] && return 0
+ elif [[ ${words[x]} = family ]]; then
+ [[ ${words[x+1]} != inet?(6) ]] && return 0
+ elif [[ ${words[x]} = range ]]; then
+ if [[ $str_type = bitmap:port ]]; then
+ [[ ${words[x+1]} != *-* ]] && return 0
else
- return 0
+ [[ ${words[x+1]} != @(*-*|*/+([[:digit:]])) ]] && return 0
fi
- elif [[ ${words[x]} = skbprio ]]; then
- [[ ${words[x+1]} = +([[:xdigit:]]):?(+([[:xdigit:]])) ]] || return 0
- elif [[ ${words[x]} = skbqueue ]]; then
- [[ ${words[x+1]} = +([[:digit:]]) ]] || return 0
fi
- done
+ fi
+ done
+ fi
+ if [[ ${words[action_index+2]} = hash:ip,mark ]]; then # must be the set type
+ if [[ $prev = family ]]; then
+ COMPREPLY=( $( compgen -W '$(_ipset_dedupe_cmd_opts inet inet6)' \
+ -- "$cur" ) )
+ elif [[ $prev != @(hashsize|timeout|maxelem|markmask) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_markmask $str_comment $str_forceadd $str_skbinfo)' \
+ -- "$cur" ) )
fi
- case "$str_type" in
- hash:*net*)
- if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \
- -- "$cur" ) )
- fi
- ;;
- hash:*!(net)*|bitmap:*)
- if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags)' \
- -- "$cur" ) )
- fi
- ;;
- list:*)
- if [[ $prev = @(before|after) ]] && ((cword-1 == order_index)); then
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- elif [[ $prev != @(timeout|bytes|packets|skbmark|skbprio|skbqueue) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_comment $str_skbflags)' \
- -- "$cur" ) )
- fi
- ;;
- esac
- ;;
- create|n)
- # validate option argument values
- if [[ ${_IPSET_VALIDATE_INPUT-1} ]]; then
- for ((x=$action_index+3; x < ${#words[@]}; x++)); do
- if [[ ${words[x+1]} && ${words[x+1]} != $cur ]]; then
- case "${words[x]}" in
- @(hashsize|timeout|size|maxelem|markmask))
- [[ ${words[x+1]} != @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] && return 0
- ;;
- family)
- [[ ${words[x+1]} != inet?(6) ]] && return 0
- ;;
- range)
- case "$str_type" in
- bitmap:port)
- [[ ${words[x+1]} != *-* ]] && return 0
- ;;
- *)
- [[ ${words[x+1]} != @(*-*|*/+([[:digit:]])) ]] && return 0
- ;;
- esac
- ;;
- esac
- fi
- done
+ elif [[ ${words[action_index+2]} = hash:* ]]; then
+ if [[ $prev = family ]]; then
+ COMPREPLY=( $( compgen -W '$(_ipset_dedupe_cmd_opts inet inet6)' \
+ -- "$cur" ) )
+ elif [[ $prev != @(hashsize|timeout|maxelem) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_comment $str_forceadd $str_skbinfo)' \
+ -- "$cur" ) )
fi
- case "${words[action_index+2]}" in # must be the set type
- hash:ip,mark)
- if [[ $prev = family ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts inet inet6)' \
- -- "$cur" ) )
- elif [[ $prev != @(hashsize|timeout|maxelem|markmask) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_markmask $str_comment $str_forceadd $str_skbinfo)' \
- -- "$cur" ) )
- fi
- ;;
- hash:*)
- if [[ $prev = family ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts inet inet6)' \
- -- "$cur" ) )
- elif [[ $prev != @(hashsize|timeout|maxelem) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_comment $str_forceadd $str_skbinfo)' \
- -- "$cur" ) )
- fi
- ;;
- bitmap:ip)
- if [[ $prev != @(range|netmask|timeout) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_comment $str_skbinfo)' \
- -- "$cur" ) )
- fi
- ;;
- bitmap:!(ip)?*)
- if [[ $prev != @(range|timeout) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_comment $str_skbinfo)' \
- -- "$cur" ) )
- fi
- ;;
- list:*)
- if [[ $prev != @(size|timeout) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_comment $str_skbinfo)' \
- -- "$cur" ) )
- fi
- ;;
- esac
- if [[ ${words[action_index+2]} = bitmap:port && $prev = range ]]; then
- # complete port ranges
- _ipset_complete_portrange "$cur"
- elif [[ ${words[action_index+2]} = bitmap:* && $prev = range ]]; then
- str_prefix=""
- if [[ $cur = @(""|+([[:word:]])) ]]; then # empty or [:word:]
- :
- elif [[ $cur = [\[]*-*[\]] ]]; then # host with hyphen
- :
- elif [[ $cur = [[]*([!]]) ]]; then # incomplete host with dash
- :
- elif [[ $cur = *-[[]+([!]]) ]]; then # incomplete range - host with dash
- str_prefix="${cur%\-[*}-"
- elif [[ $cur = \[*\]-* ]]; then # first part of hostname range
- str_prefix="${cur%\]-*}]-"
- elif [[ $cur != *-* ]]; then # no hypen
- :
- else # ip-range
- str_prefix="${cur%-*}-"
+ elif [[ ${words[action_index+2]} = bitmap:ip ]]; then
+ if [[ $prev != @(range|netmask|timeout) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_comment $str_skbinfo)' \
+ -- "$cur" ) )
+ fi
+ elif [[ ${words[action_index+2]} = bitmap:!(ip)?* ]]; then
+ if [[ $prev != @(range|timeout) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_comment $str_skbinfo)' \
+ -- "$cur" ) )
+ fi
+ elif [[ ${words[action_index+2]} = list:* ]]; then
+ if [[ $prev != @(size|timeout) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_comment $str_skbinfo)' \
+ -- "$cur" ) )
+ fi
+ fi
+ if [[ ${words[action_index+2]} = bitmap:port && $prev = range ]]; then
+ # complete port ranges
+ _ipset_complete_portrange "$cur"
+ elif [[ ${words[action_index+2]} = bitmap:* && $prev = range ]]; then
+ str_prefix=""
+ if [[ $cur = @(""|+([[:word:]])) ]]; then # empty or [:word:]
+ :
+ elif [[ $cur = [\[]*-*[\]] ]]; then # host with hyphen
+ :
+ elif [[ $cur = [[]*([!]]) ]]; then # incomplete host with dash
+ :
+ elif [[ $cur = *-[[]+([!]]) ]]; then # incomplete range - host with dash
+ str_prefix="${cur%\-[*}-"
+ elif [[ $cur = \[*\]-* ]]; then # first part of hostname range
+ str_prefix="${cur%\]-*}]-"
+ elif [[ $cur != *-* ]]; then # no hypen
+ :
+ else # ip-range
+ str_prefix="${cur%-*}-"
+ fi
+ _ipset_complete_host_spec "$cur" --v4
+ if ((${#COMPREPLY[@]} == 1)); then
+ if [[ -z $str_prefix && ${COMPREPLY[*]} != */* ]]; then
+ compopt -o nospace
+ COMPREPLY=( $( compgen -W '${COMPREPLY[*]}/ ${COMPREPLY[*]}-' -- "$cur" ) )
fi
- _ipset_complete_host_spec "$cur" --v4
- if ((${#COMPREPLY[@]} == 1)); then
- if [[ -z $str_prefix && ${COMPREPLY[*]} != */* ]]; then
- compopt -o nospace
- COMPREPLY=( $( compgen -W '${COMPREPLY[*]}/ ${COMPREPLY[*]}-' -- "$cur" ) )
- fi
+ fi
+ fi
+ elif [[ $str_action = @(del|test) ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if [[ $str_type = list:* ]]; then
+ arr_tmp=()
+ _ipset_get_members --names-only "$str_setname"
+ if [[ $prev = @(before|after) ]] && ((cword-1 == order_index))
+ then
+ if [[ $prev = before ]]; then
+ for x in ${!arr_members[@]}; do
+ if [[ ${arr_members[x]} = ${words[action_index+2]} ]]
+ then
+ if [[ ${arr_members[x+1]} ]]; then
+ arr_tmp+=(${arr_members[x+1]})
+ break
+ fi
+ fi
+ done
+ elif [[ $prev = after ]]; then
+ for x in ${!arr_members[@]}; do
+ if [[ ${arr_members[x]} = ${words[action_index+2]} ]]
+ then
+ if ((x>0)) && [[ ${arr_members[x-1]} ]]; then
+ arr_tmp+=(${arr_members[x-1]})
+ break
+ fi
+ fi
+ done
fi
+ COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
fi
- ;;
- del|test)
- str_type=$(_ipset_get_set_type "$str_setname")
- case "$str_type" in
- list:*) arr_tmp=()
- _ipset_get_members --names-only "$str_setname"
- if [[ $prev = @(before|after) ]] && ((cword-1 == order_index))
- then
- case "$prev" in
- before)
- for x in ${!arr_members[@]}; do
- if [[ ${arr_members[x]} = ${words[action_index+2]} ]]
- then
- if [[ ${arr_members[x+1]} ]]; then
- arr_tmp+=(${arr_members[x+1]})
- break
- fi
- fi
- done
- ;;
- after)
- for x in ${!arr_members[@]}; do
- if [[ ${arr_members[x]} = ${words[action_index+2]} ]]
- then
- if ((x>0)) && [[ ${arr_members[x-1]} ]]; then
- arr_tmp+=(${arr_members[x-1]})
- break
- fi
- fi
- done
- ;;
- esac
- COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- fi
- ;;
- esac
- ;;
- esac
+ fi
+ fi
fi
else # we don't have the main action yet
if [[ $prev = - ]] && ((cword == 2)); then
@@ -1771,7 +1716,9 @@ if [[ $cur = -* ]]; then # any option is requested
_ipset_get_options
else
# we don't have the action yet, check options to display appropiate actions
- if ((save_format || names_only || headers_only)); then
+ if ((save_format && !headers_only && !names_only)); then
+ COMPREPLY=( $( compgen -W 'list save' -- "$cur" ) )
+ elif ((save_format || names_only || headers_only)); then
COMPREPLY=( $( compgen -W 'list' -- "$cur" ) )
elif ((res_sort)); then
COMPREPLY=( $( compgen -W 'list save' -- "$cur" ) )
@@ -1782,8 +1729,8 @@ else
elif ((use_file)); then
COMPREPLY=( $( compgen -W 'list save restore' -- "$cur" ) )
else
- COMPREPLY=( $( compgen -W 'create n add del test destroy x list save \
- restore flush rename e swap w help version' -- "$cur" ) )
+ COMPREPLY=( $( compgen -W 'create n add del test destroy x list save \
+ restore flush rename e swap w help version' -- "$cur" ) )
fi
fi
fi
diff --git a/utils/ipset_list/ipset_list b/utils/ipset_list/ipset_list
index ad15f18..306ddac 100755..100644
--- a/utils/ipset_list/ipset_list
+++ b/utils/ipset_list/ipset_list
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# -----------------------------------------------------------------
# ipset set listing wrapper script
@@ -7,7 +7,7 @@
# https://sourceforge.net/projects/ipset-list/
# -----------------------------------------------------------------
-# Copyright (C) 2013-2014 AllKind (AllKind@fastest.cc)
+# Copyright (C) 2013-2019 Mart Frauenlob aka AllKind (AllKind@fastest.cc)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -23,1050 +23,353 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------
-# Compatible with ipset version 6+
-# Tested with ipset versions:
-# 6.16.1, 6.20.1, 6.22
-# -----------------------------------------------------------------
-
-# -----------------------------------------------------------------
-# Features (in addition to the native ipset options):
-# - Calculate sum of set members (and match on that count).
-# - List only members of a specified set.
-# - Choose a delimiter character for separating members.
-# - Show only sets containing a specific (glob matching) header.
-# - Arithmetic comparison on headers with an integer value.
-# - Arithmetic comparison on flags of the headers 'Header' field.
-# - Arithmetic comparison on member options with an integer value.
-# - Match members using a globbing or regex pattern.
-# - Suppress listing of (glob matching) sets.
-# - Suppress listing of (glob matching) headers.
-# - Suppress listing of members matching a glob or regex pattern.
-# - Calculate the total size in memory of all matching sets.
-# - Calculate the amount of matching, excluded and traversed sets.
-# - Colorize the output.
-# - Operate on a single, selected, or all sets.
-# - Programmable completion is included to make usage easier and faster.
-# -----------------------------------------------------------------
-
-# -----------------------------------------------------------------
-# Examples:
-# $0 - no args, just list set names
-# $0 -c - show all set names and their member sum
-# $0 -t - show all sets, but headers only
-# $0 -c -t setA - show headers and member sum of setA
-# $0 -i setA - show only members entries of setA
-# $0 -c -m setA setB - show members and sum of setA & setB
-# $0 -a -c -d : - show all sets members, sum and use `:' as entry delimiter
-# $0 -a -c setA - show all info of setA and its members sum
-# $0 -c -m -d $'\n' setA - show members and sum of setA, delim with newline
-# $0 -m -r -s setA - show members of setA resolved and sorted
-# $0 -Ts - show all set names and total count of sets.
-# $0 -Tm - calculate total size in memory of all sets.
-# $0 -Mc 0 - show sets with zero members
-# $0 -Fi References:0 - show all sets with 0 references
-# $0 -Hr 0 - shortcut for `-Fi References:0'
-# $0 -Xs setA -Xs setB - show all set names, but exclude setA and setB.
-# $0 -Xs "set[AB]" - show all set names, but exclude setA and setB.
-# $0 -Cs -Ht "hash:*" - find sets of any hash type, count their amount.
-# $0 -Ht "!(hash:ip)" - show sets which are not of type hash:ip
-# $0 -Ht "!(bitmap:*)" - show sets wich are not of any bitmap type
-# $0 -i -Fr "^210\..*" setA - show only members of setA matching the regex "^210\..*"
-# $0 -Mc \>=100 -Mc \<=150 - show sets with a member count greater or equal to 100
-#+ and not greater than 150.
-# $0 -a -c -Fh "Type:hash:ip" -Fr "^210\..*"
-#+ - show all information of sets with type hash:ip,
-#+ matching the regex "^210\..*", show match and members sum.
#
-# $0 -m -Fg "!(210.*)" setA
-#+ show members of setA excluding the elements matching the negated glob.
+# This is the bash programmable completion for ipset_list
#
-# $0 -Hr \>=1 -Hv 0 -Hs \>10000 - find sets with at least one reference,
-#+ revision of 0 and size in memory greater than 10000
-#
-# $0 -Fh Type:hash:ip -Fh "Header:family inet *"
-#+ - show all set names, which are of type hash:ip and header of ipv4.
-#
-# $0 -t -Xh "Revision:*" -Xh "References:*"
-#+ - show all sets headers, but exclude Revision and References entries.
-#
-# $0 -t -Ht "!(@(bit|port)map):*" -Xh "!(Type):*" - show all sets that are
-#+ neither of type bitmap or portmap, suppress all but the type header.
-#
-# $0 -c -m -Xg "210.*" setA - show members of setA, but suppress listing of entries
-#+ matching the glob pattern "210.*", show count of excluded and total members.
+# -----------------------------------------------------------------
+# Requirements:
#
-# $0 -t -Tm -Xh "@(Type|Re*|Header):*"
-#+ show all sets headers, but suppress all but name and memsize entry,
-#+ calculate the total memory size of all sets.
+# The bash completion package version 2.0 or greater is recommended.
+# https://github.com/scop/bash-completion
#
-# $0 -t -Tm -Xh "!(Size*|Type):*" -Ts -Co
-# + List all sets headers, but suppress all but name, type and memsize entry,
-# + count amount of sets, calculate total memory usage, colorize the output.
+# If the package is not available, things might not be so reliable.
+# Also the colon (if there) is removed from COMP_WORDBREAKS.
+# This alteration is globally. Which might affect other completions
+# if they don't take care of it themselves.
#
-# $0 -c -t -Cs -Ts -Xh "@(Size*|Re*|Header):*" -Ht "!(bitmap:*)"
-#+ find all sets not of any bitmap type, count their members sum,
-#+ display only the 'Type' header,
-#+ count amount of matching and traversed sets.
+# -----------------------------------------------------------------
+# Installation (quote from bash-completion README):
#
-# $0 -a -Xh "@(@(H|R|M)e*):*" - show all info of all sets,
-#+ but suppress Header, References, Revision and Member header entries.
-#+ (headers existing as per ipset 6.x -> tested version).
+# Install it in one of the directories pointed to by
+# bash-completion's pkgconfig file variables. There are two
+# alternatives: the recommended one is 'completionsdir' (get it with
+# "pkg-config --variable=completionsdir bash-completion") from which
+# completions are loaded on demand based on invoked commands' names,
+# so be sure to name your completion file accordingly, and to include
+# for example symbolic links in case the file provides completions
+# for more than one command. The other one which is present for
+# backwards compatibility reasons is 'compatdir' (get it with
+# "pkg-config --variable=compatdir bash-completion") from which files
+# are loaded when bash_completion is loaded.
#
-# $0 -Co -c -Ts -Tm - show all set names, count their members,
-# + count total amount of sets, show total memory usage of all sets,
-# + colorize the output
+# For packages using GNU autotools the installation can be handled
+# for example like this in configure.ac:
#
-# $0 -m -r -To 0 - show members of all sets, try to resolve hosts,
-# set the timeout to 0 (effectivly disabling it).
+# PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], ,
+# bashcompdir="${sysconfdir}/bash_completion.d")
+# AC_SUBST(bashcompdir)
#
-# $0 -m -Xo setA - show members of setA,
-# + but suppress displaying of the elements options.
+# ...accompanied by this in Makefile.am:
#
-# $0 -m -Oi packets:0
-# + show members of all sets which have a packet count of 0.
+# bashcompdir = @bashcompdir@
+# dist_bashcomp_DATA = # completion files go here
#
-# $0 -m -Oi "packets:>100" -Oi "bytes:>1024"
-# + show members of all sets which have a
-# + packet count greater than 100 and a byte count greater than 1024.
+# For cmake we ship the bash-completion-config.cmake and
+# bash-completion-config-version.cmake files. Example usage:
#
-# $0 -m -Oi "skbmark:>0x123/0XFF" -Oi skbprio:\>=2:<=3 -Oi skbqueue:\!1
-# + show members of all sets which have the following member options set:
-# + skbmark greater than 0x123/0xFF, skbprio major greater or equal to 2
-# + and minor lower or equal to 3, skbqueue not of value 1.
+# find_package(bash-completion)
+# if(BASH_COMPLETION_FOUND)
+# message(STATUS
+# "Using bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}")
+# else()
+# set (BASH_COMPLETION_COMPLETIONSDIR "/etc/bash_completion.d")
+# message (STATUS
+# "Using fallback bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}")
+# endif()
#
-# $0 -n -Ca "foo*"
-# + show only set names matching the glob "foo*" and enable all counters.
+# install(FILES your-completion-file DESTINATION
+# ${BASH_COMPLETION_COMPLETIONSDIR})
#
-# $0 -Hi "markmask:>=0x0000beef" -Hi timeout:\!10000`
-# + show only sets with the header 'Header' fields containing a markmask
-# + greater or equal to 0x0000beef and a timeout which is not 10000.
+# For backwards compatibility it is still possible to put it into
+# ~/.bash_completion or /etc/bash_completion.d/.
# -----------------------------------------------------------------
-# -----------------------------------------------------------------
-# Modify here
-# -----------------------------------------------------------------
-
-# modify your PATH variable
-# by default the path is only set if the PATH variable is not already set in the environment
-# PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
-: ${PATH:=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin}
-
-# path to ipset.
-# defaults to `/sbin/ipset' if unset.
-#ipset="/sbin/ipset"
-# find in path if not declared in parent environment
-: ${ipset:=$(command -v ipset)}
-
-# default delimiter character for set members (elements).
-# defaults to whitespace if unset.
-# use delim=$'\n' to use the ipset default newline as delimiter.
-delim=" "
-
-# default read timeout (for reading sets - esp. with the -r switch).
-# the command line option -To overrides this.
-TMOUT=30
-
-# colorize the output (bool 0/1).
-colorize=0
-
-# path to cl (to colorize the output).
-# http://sourceforge.net/projects/colorize-shell/ or
-# https://github.com/AllKind/cl
-# defaults to `/usr/local/bin/cl' if unset.
-cl="/usr/local/bin/cl"
-
-# define colors
-# run `cl --list' to retrieve the valid color names
-#
-# default foreground color
-# defaults to: white
-col_fg="white"
-
-# default background color
-# defaults to: black
-col_bg="black"
+# Name may be modified
+ipset_list=ipset_list
-# color for headers
-# defaults to: cyan
-col_headers="cyan"
-
-# color for members
-# defaults to: yellow
-col_members="yellow"
-
-# color for matches
-# defaults to: red
-col_match="red"
-
-# color for displaying of memsize
-# defaults to: green
-col_memsize="green"
-
-# color for counting of matched sets
-# defaults to: magenta
-col_set_count="magenta"
-
-# color for counting of traversed sets
-# defaults to: blue
-col_set_total="blue"
-
-# general higlightning color
-# defaults to: white
-col_highlight="white"
+# -----------------------------------------------------------------
# -----------------------------------------------------------------
# DO NOT MODIFY ANYTHING BEYOND THIS LINE!
# -----------------------------------------------------------------
-
-# bash check
-if [ -z "$BASH" ]; then
- printf "\`BASH' variable is not available. Not running bash?\n" >&2
- exit 1
-fi
-
-# shell settings
shopt -s extglob
-set -f
-set +o posix
-set +u
-
-# variables
-export LC_ALL=C
-readonly version=3.2.1
-readonly me="${0//*\//}"
-readonly oIFS="$IFS"
-declare ips_version="" str_search="" str_xclude="" opt str_name str_val str_op
-declare -i show_all=show_count=show_members=headers_only=names_only=isolate=calc_mem=count_sets=sets_total=0
-declare -i match_on_header=glob_search=regex_search=member_count=match_count=do_count=opt_int_search=0
-declare -i exclude_header=glob_xclude_element=glob_xclude_element=exclude_set=xclude_member_opts=0
-declare -i in_header=found_set=found_member_opt=found_hxclude=found_sxclude=xclude_count=mem_total=mem_tmp=set_count=sets_sum=i=x=y=idx=0
-declare -a arr_sets=() arr_par=() arr_hcache=() arr_mcache=() arr_hsearch=() arr_tmp=()
-declare -a arr_hsearch_int=() arr_hsearch_xint=() arr_hxclude=() arr_sxclude=() arr_match_on_msum=() arr_opt_int_search=()
# -----------------------------------------------------------------
-# functions
+# Functions
# -----------------------------------------------------------------
-ex_miss_optarg() {
-printf "%s of option \`%s' is missing\n" "$2" "$1" >&2
-exit 2
-}
-
-ex_invalid_usage() {
-printf "%s\n" "$*" >&2
-exit 2
-}
-
-is_int() {
-[[ $1 = +([[:digit:]]) ]]
-}
-
-is_digit_or_xigit() {
-[[ $1 = @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]]
-}
-
-is_compare_str() {
- [[ $1 = ?(\!|<|>|<=|>=)@(+([[:digit:]])|0[x|X]+([[:xdigit:]])) ]]
-}
-
-is_compare_str_complex() {
- [[ $1 = ?(\!|<|>|<=|>=)@(+([[:digit:]])|0@(x|X)+([[:xdigit:]])?(/0@(x|X)+([[:xdigit:]]))|+([[:xdigit:]]):?(\!|<|>|<=|>=)+([[:xdigit:]])) ]]
-}
-
-add_search_to_member_cache() {
-if ((show_members || show_all || isolate)); then
- arr_mcache[i++]="$REPLY"
-fi
-}
-
-arith_elem_opt_search() {
-local str_opt_val str_val2 str_op2 str_cg='?(\!|<|>|<=|>=)' str_xdig='0[xX]+([[:xdigit:]])'
-found_member_opt=0
-for y in ${!arr_opt_int_search[@]}; do
- str_val="${arr_opt_int_search[y]#*:}"
- if [[ $str_val = ${str_cg}@(+([[:digit:]])|$str_xdig) ]]; then # i.e. timeout or skbqueue
- str_op="${str_val//[![:punct:]]}"
- str_val="${str_val//[=\!\>\<]}"
- elif [[ $str_val = ${str_cg}${str_xdig}/$str_xdig ]]; then # i.e. skbmark
- str_op="${str_val//[![:punct:]]}"
- str_op="${str_op//\/}"
- str_val="${str_val//[=\!\>\<]}"
- elif [[ $str_val = ${str_cg}+([[:xdigit:]]):${str_cg}+([[:xdigit:]]) ]]; then # i.e. skbprio
- str_op="${str_val%:*}"
- str_op="${str_op%%+([[:xdigit:]])}"
- str_op2="${str_val#*:}"
- str_op2="${str_op2%%+([[:xdigit:]])}"
- str_val="${str_val##+([[:punct:]])}"
- str_val2="${str_val#*:}"
- str_val2="${str_val2//[[:punct:]]}"
- fi
- # compare operator defaults to `=='
- # if it's a '!' set it to '!='
- [[ ${str_op:===} = \! ]] && str_op='!='
- [[ ${str_op2:===} = \! ]] && str_op2='!='
- set -- $REPLY
- shift
- while (($# > 1)); do # cycle through options
- if [[ $1 = ${arr_opt_int_search[y]%%:*} ]]; then str_opt_val="$2"
- if [[ $str_val = @(+([[:digit:]])|$str_xdig) && $str_opt_val = @(+([[:digit:]])|$str_xdig) ]]; then # i.e. timeout or skbqueue
- if (( $str_opt_val $str_op $str_val )); then
- let found_member_opt+=1
- fi
- shift
- elif [[ $str_val = $str_xdig && $str_opt_val = ${str_xdig}/$str_xdig ]]; then # i.e. skbmark
- if (( $str_opt_val $str_op $(( ${str_val%/*} & ${str_val#*/} )) )); then # logicaly AND mark/mask
- let found_member_opt+=1
- fi
- shift
- elif [[ $str_val = ${str_xdig}/$str_xdig && $str_opt_val = ${str_xdig}/$str_xdig ]]; then # i.e. skbmark
- if (( $(( ${str_opt_val%/*} & ${str_opt_val#*/} )) $str_op $(( ${str_val%/*} & ${str_val#*/} )) )); then # logicaly AND mark/mask
- let found_member_opt+=1
- fi
- shift
- elif [[ $str_val = +([[:xdigit:]]):${str_cg}+([[:xdigit:]]) && $str_opt_val = +([[:xdigit:]]):+([[:xdigit:]]) ]]; then # i.e. skbprio
- if (( ${str_opt_val%:*} $str_op ${str_val%:*} && ${str_opt_val#*:} $str_op2 $str_val2 )); then
- let found_member_opt+=1
- fi
- shift
- fi
- fi
- shift
- done
+_ipset_list_show_sets() {
+COMPREPLY=( $( compgen -W '${sets[@]}' -- "$cur" ) )
+# dedupe sets listing
+for ((i=set_index; i < ${#words[@]}-1; i++)); do
+ _ipset_list_remove_reply_entry "${words[i]}"
done
-if ((opt_int_search == found_member_opt)); then
- let match_count+=1
- add_search_to_member_cache
-fi
}
-xclude_elem_search() {
-if ((glob_xclude_element)); then # exclude matching members
- if [[ $REPLY = $str_xclude ]]; then
- let xclude_count+=1
- return 0
- fi
-elif ((regex_xclude_element)); then # exclude matching members
- if [[ $REPLY =~ $str_xclude ]]; then
- let xclude_count+=1
- return 0
- else
- if (($? == 2)); then
- printf "Invalid regex pattern \`%s'.\n" "$str_xclude" >&2
- exit 1
- fi
- fi
-fi
-return 1
+_ipset_list_remove_reply_entry() {
+local -i x
+while (($#)); do
+ for x in ${!COMPREPLY[@]}; do
+ if [[ ${COMPREPLY[x]} = $1 ]]; then
+ if [[ $_DEBUG_NF_COMPLETION ]]; then
+ printf "removing dupe entry COMPREPLY[$x]: %s\n" \
+ "${COMPREPLY[x]}"
+ fi
+ unset COMPREPLY[x]
+ break
+ fi
+ done
+ shift
+done
}
# -----------------------------------------------------------------
-# main
+# Main
# -----------------------------------------------------------------
-# validate value of colorize
-if [[ ${colorize:=0} != [01] ]]; then
- ex_invalid_usage "value of variable \`colorize' \`$colorize' is not 0 or 1."
-fi
+_ipset_list_complete() {
+local -i i=x=got_bashcompl=iactive=0
+local -i show_all=isolate=show_members=resolve=headers_only=names_only=0
+local -i header_operation=set_index=0
+local cur prev cword words str_tmp
+local sets=( $(command "${ipset_list:-ipset_list}" -n 2>/dev/null) ) 2>/dev/null
+local opts=(- -- -? -a -c -d -h -i -m -n -r -s -t -v)
+local Copts=(-Ca -Cs -Co)
+local Fopts=(-Fh -Fi -Fg -Fr -Oi)
+local Gopts=(-Gp -Gs -Gx)
+local Iopts=(-- -d -r -s -G ${Gopts[@]} -To)
+local Hopts=(-Hi -Hr -Hs -Ht -Hv)
+local Topts=(-T -Tm -To -Ts)
+local Xopts=(-Xh -Xg -Xr -Xs -Xo)
+local arr_types=() arr_tmp=()
-# parse cmd-line options
-while (($#)); do
- case "$1" in
- -\?|-h) printf "\n\tipset set listing wrapper script\n\n"
- printf '%s [option [opt-arg]] [set-name-glob] [...]\n\n' "$me"
- printf '%s %s\n' "$me" "{-?|-h} | -v"
- printf '%s %s\n\t%s\n\t%s\n' "$me"\
- "[-i|-r|-s|-Co|-Xo] [-d char] [-To value]"\
- "[-Fg|-Fr pattern] [-Xg|-Xr pattern]"\
- "[-Oi option-glob:[!|<|>|<=|>=]value] [...] -- set-name"
- printf '%s %s\n\t%s\n\t%s\n\t%s\n' "$me"\
- "[-n|-c|-Ca|-Co|-Cs|-Tm|-Ts|-Xs] [-To value]"\
- "[-Fh header-glob:value-glob] [...] [-Fg|-Fr pattern]"\
- "[-Hi glob:[!|<|>|<=|>=]value] [...]"\
- "[-Oi option-glob:[!|<|>|<=|>=]value] [...] -- [set-name-glob] [...]"
- printf '%s %s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n' "$me"\
- "[-t|-c|-Ca|-Co|-Cs|-Tm|-Ts]"\
- "[-Fh header-glob:value-glob] [...]"\
- "[-Fi header-glob:[!|<|>|<=|>=]value] [...]"\
- "[-Fg|-Fr pattern] [-Ht type-glob]"\
- "[-Hi glob:[!|<|>|<=|>=]value] [...]"\
- "[-Hr|-Hs|-Hv [!|<|>|<=|>=]value]"\
- "[-Mc [!|<|>|<=|>=]value] [...] [-To value]"\
- "[-Oi option-glob:[!|<|>|<=|>=]value] [...]"\
- "[-Xh header-glob:value-glob] [...]"\
- "[-Xs set-name-glob] [...] -- [set-name-glob] [...]"
- printf '%s %s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n' "$me"\
- "[-a|-c|-m|-r|-s|-Ca|-Co|-Cs|-Tm|-Ts|-Xo] [-d char]"\
- "[-Fh header-glob:value-glob] [...]"\
- "[-Fi header-glob:[!|<|>|<=|>=]value] [...]"\
- "[-Fg|-Fr pattern] [-Ht type-glob]"\
- "[-Hi glob:[!|<|>|<=|>=]value] [...]"\
- "[-Hr|-Hs|-Hv [!|<|>|<=|>=]value]"\
- "[-Mc [!|<|>|<=|>=]value] [...]"\
- "[-Oi option-glob:[!|<|>|<=|>=]value] [...]"\
- "[-To value] [-Xh header-glob:value-glob] [...]"\
- "[-Xg|-Xr pattern] [-Xs set-name-glob] [...] -- [set-name-glob] [...]"
- printf 'options:\n'
- printf '%-13s%s\n' '-a' 'show all information but with default delim (whitespace).'\
- '-c' 'calculate members and match sum.'\
- '-d delim' 'delimiter character for separating member entries.'\
- '-h|-?' 'show this help text.'\
- '-i' 'show only the members of a single set.'\
- '-m' 'show set members.'\
- '-n' "show set names only."\
- '-r' 'try to resolve ip addresses in the output (slow!).'\
- '-s' 'print elements sorted (if supported by the set type).'\
- '-t' 'show set headers only.'\
- '-v' 'version information.'\
- '-Ca' "shortcut for -c -Cs -Ts -Tm (enable all counters)."\
- '-Co' "colorize output (requires \`cl')."\
- '-Cs' 'count amount of matching sets.'\
- '-Fg pattern' 'match on members using a [ext]glob pattern.'\
- '-Fr pattern' 'match on members using a regex (=~ operator) pattern.'
- printf '%s\n\t%s\n' '-Fh header-glob:value-glob [...]'\
- 'show sets containing one or more [ext]glob matching headers.'
- printf '%s\n\t%s\n' '-Fi header-glob:[!|<|>|<=|>=]value [...]'\
- 'show sets matching one or more integer valued header entries.'
- printf '%s\n\t%s\n' '-Hi header-glob:[!|<|>|<=|>=]value [...]'\
- "match one or more integer valued headers \`Header' entries."
- printf '%-24s%s\n' '-Ht set-type-glob' 'match on set type.'\
- '-Hr [!|<|>|<=|>=]value' 'match on number of references (value=int).'\
- '-Hs [!|<|>|<=|>=]value' 'match on size in memory (value=int).'\
- '-Hv [!|<|>|<=|>=]value' 'match on revision number (value=int).'
- printf '%-30s%s\n' '-Mc [!|<|>|<=|>=]value [...]' 'match on member count (value=int).'
- printf '%s\n\t%s\n' '-Oi option-glob:[!|<|>|<=|>=]value [...]'\
- 'match member options (value=int | 0xhex[/0xhex] | hex:[!|<|>|<=|>=]hex).'
- printf '%-13s%s\n' '-Tm' 'calculate total memory usage of all matching sets.'\
- '-To' 'set timeout value (int) for read (listing sets).'\
- '-Ts' 'count amount of traversed sets.'\
- '-Xo' 'suppress display of member options.'
- printf '%s\n\t%s\n' '-Xh header-glob:value-glob [...]'\
- 'exclude one or more [ext]glob matching header entries.'
- printf '%-13s%s\n' '-Xg pattern' 'exclude members matching a [ext]glob pattern.'\
- '-Xr pattern' 'exclude members matching a regex pattern.'\
- '-Xs pattern' 'exclude sets matching a [ext]glob pattern.'
- printf '%-13s%s\n' '--' 'stop further option processing.'
- exit 0
- ;;
- -a) show_all=1 # like `ipset list', but with $delim as delim
- ;;
- -c) show_count=1 # show sum of member entries
- ;;
- -i) isolate=1 # show only members of a single set
- ;;
- -m) show_members=1 # show set members
- ;;
- -n) names_only=1 # only list set names
- ;;
- -t) headers_only=1 # show only set headers
- ;;
- -s|-r) arr_par[i++]="$1" # ipset sort & resolve options are passed on
- ;;
- -d) # delimiter char for separating member entries
- [[ $2 ]] || ex_miss_optarg $1 "delim character"
- if ((${#2} > 1)); then
- ex_invalid_usage "only one character is allowed as delim"
- fi
- delim="$2"
- shift
- ;;
- -o) if [[ $2 != plain ]]; then
- ex_invalid_usage "only plain output is supported"
- fi
- ;;
- -Ca) # shortcut for -c -Cs -Ts -Tm
- show_count=1 count_sets=1 calc_mem=1 sets_total=1
- ;;
- -Cs) count_sets=1 # calculate total count of matching sets
- ;;
- -Co) colorize=1 # colorize the output (requires cl)
- ;;
- -Fg) glob_search=1 # find entry with globbing pattern
- [[ $2 ]] || ex_miss_optarg $1 "glob pattern"
- str_search="$2"
- shift
- ;;
- -Fr) regex_search=1 # find entry with regex pattern
- [[ $2 ]] || ex_miss_optarg $1 "regex pattern"
- str_search="$2"
- shift
- ;;
- -Oi) let opt_int_search+=1
- [[ $2 ]] || ex_miss_optarg $1 "pattern"
- if [[ $2 = *:* ]] && is_compare_str_complex "${2#*:}"; then
- arr_opt_int_search[y++]="$2"
- shift
- else
- ex_invalid_usage "invalid format of header descriptor. expecting: \`glob:[!|<|>|<=|>=]value'"
- fi
- ;;
- -Fh) let match_on_header+=1 # show only sets, which contain a matching header entry
- [[ $2 ]] || ex_miss_optarg $1 "header pattern"
- if [[ $2 = *:* ]]; then
- arr_hsearch[x++]="$2"
- shift
- else
- ex_invalid_usage "invalid format of header descriptor. expecting: \`*:*'"
- fi
- ;;
- -Fi) let match_on_header+=1 # show only sets, containing a matching (int compare) header entry
- [[ $2 ]] || ex_miss_optarg $1 "header pattern"
- if [[ $2 = *:* ]] && is_compare_str "${2#*:}"; then
- arr_hsearch_int[idx++]="$2"
- shift
- else
- ex_invalid_usage "invalid format of header descriptor. expecting: \`name:[!|<|>|<=|>=]value'"
- fi
- ;;
- -Hi) let match_on_header+=1 # match on name + integer (digit & xdigit) inside of headers 'Header' flag
- [[ $2 ]] || ex_miss_optarg $1 "header pattern"
- if [[ $2 = *:?(\!|<|>|<=|>=)@(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]]; then
- arr_hsearch_xint[${#arr_hsearch_xint[@]}]="$2"
- shift
- else
- ex_invalid_usage "invalid format of headers \'Header' flag descriptor. expecting: \`name:[!|<|>|<=|>=]value'"
- fi
- ;;
- -Hr) let match_on_header+=1 # shortcut for -Fi References:...
- [[ $2 ]] || ex_miss_optarg $1 "header pattern"
- if is_compare_str "$2"; then
- arr_hsearch_int[idx++]="References:$2"
- shift
- else
- ex_invalid_usage "invalid format of references header descriptor. expecting: \`[!|<|>|<=|>=]value'"
- fi
- ;;
- -Hs) let match_on_header+=1 # shortcut for -Fi "Size in Memory:..."
- [[ $2 ]] || ex_miss_optarg $1 "header pattern"
- if is_compare_str "$2"; then
- arr_hsearch_int[idx++]="Size in memory:$2"
- shift
- else
- ex_invalid_usage "invalid format of memsize header descriptor. expecting: \`[!|<|>|<=|>=]value'"
- fi
- ;;
- -Ht) let match_on_header+=1 # shortcut for -Fh Type:x:y
- [[ $2 ]] || ex_miss_optarg $1 "header pattern"
- if [[ $2 = *:* ]]; then
- arr_hsearch[x++]="Type:$2"
- shift
- else
- ex_invalid_usage "invalid format of set type descriptor. expecting: \`*:*'."
- fi
- ;;
- -Hv) let match_on_header+=1 # shortcut for -Fi Revision:...
- [[ $2 ]] || ex_miss_optarg $1 "header pattern"
- if is_compare_str "$2"; then
- arr_hsearch_int[idx++]="Revision:$2"
- shift
- else
- ex_invalid_usage "invalid format of revision header descriptor. expecting: \`[!|<|>|<=|>=]value'"
- fi
- ;;
- -Mc) do_count=1 # match on the count of members
- [[ $2 ]] || ex_miss_optarg $1 "value pattern"
- if is_compare_str "$2"; then
- arr_match_on_msum[${#arr_match_on_msum[@]}]="$2"
- shift
- else
- ex_invalid_usage "invalid format of match on member count value. expecting: \`[!|<|>|<=|>=]value'"
- fi
- ;;
- -To) # set the timeout for read (limited to integer)
- [[ $2 ]] || ex_miss_optarg $1 "value"
- TMOUT=$2
- shift
- ;;
- -Tm) calc_mem=1 # caculate total memory usage of all matching sets
- ;;
- -Ts) sets_total=1 # caculate sum of all traversed sets
- ;;
- -Xh) exclude_header=1 # don't show certain headers
- [[ $2 ]] || ex_miss_optarg $1 "header pattern"
- if [[ $2 = *:* ]]; then
- arr_hxclude[${#arr_hxclude[@]}]="$2"
- shift
- else
- ex_invalid_usage "invalid format of header descriptor. expecting: \`*:*'"
- fi
- ;;
- -Xg) glob_xclude_element=1 # suppress printing of matching members using a globbing pattern
- [[ $2 ]] || ex_miss_optarg $1 "glob pattern"
- str_xclude="$2"
- shift
- ;;
- -Xr) regex_xclude_element=1 # suppress printing of matching members using a regex pattern
- [[ $2 ]] || ex_miss_optarg $1 "regex pattern"
- str_xclude="$2"
- shift
- ;;
- -Xo) xclude_member_opts=1 # don't show elements options
- ;;
- -Xs) exclude_set=1 # don't show certain sets
- [[ $2 ]] || ex_miss_optarg $1 "set name ([ext]glob pattern)"
- arr_sxclude[${#arr_sxclude[@]}]="$2"
- shift
- ;;
- -\!|-f) ex_invalid_usage "unsupported option: \`$1'"
- ;;
- -v) printf "%s version %s\n" "$me" "$version"
- exit 0
- ;;
- --) break
- ;;
- *) break
- esac
- shift
-done
-declare -i i=x=y=idx=0
+: ${PATH:=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin}
-# check for ipset program and version
-[[ -x ${ipset:=/sbin/ipset} ]] || {
- printf "ipset binary \`%s' does not exist, or is not executable. check \`ipset' variable\n" "$ipset" >&2
- exit 1
-}
-ips_version="$("$ipset" version)"
-ips_version="${ips_version#ipset v}"
-ips_version="${ips_version%%.*}"
-if ! is_int "$ips_version"; then
- printf "failed retrieving ipset version. expected digits, got: \`%s'\n" "$ips_version" >&2
- exit 1
-fi
-if ((ips_version < 6)); then
- printf "found version \`%s' - ipset versions from 6.x and upwards are supported\n" "$ips_version" >&2
- exit 1
+COMPREPLY=()
+
+# expecting _get_comp_words_by_ref() to exist from bash_completion
+if declare -f _get_comp_words_by_ref &>/dev/null; then got_bashcompl=1
+ _get_comp_words_by_ref -n : cur prev cword words || return
+else got_bashcompl=0 # not so neat, but a workaround
+ COMP_WORDBREAKS="${COMP_WORDBREAKS//:/}"
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+ cword=$COMP_CWORD
+ for i in ${!COMP_WORDS[@]}; do words[i]="${COMP_WORDS[i]}"; done
fi
-# validate TMOUT variable
-if [[ $TMOUT ]] && ! is_int "$TMOUT"; then
- ex_invalid_usage "timeout value \`$TMOUT' is not an integer"
+#_DEBUG_NF_COMPLETION=Y
+if [[ $_DEBUG_NF_COMPLETION ]]; then
+ printf "\nCOMP_WORDBREAKS: <%s>\n" "$COMP_WORDBREAKS"
+ printf "COMP_LINE: <%s>\n" "$COMP_LINE"
+ printf "COMP_TYPE: <%s>\n" "$COMP_TYPE"
+ printf "COMP_POINT: <%s>\n" "$COMP_POINT"
+ printf "COMP_KEY: <%s>\n" "$COMP_KEY"
+ printf "COMP_CWORD: <%s>\n" "$COMP_CWORD"
+ printf "\ncur: <%s> prev: <%s>\n" "$cur" "$prev"
+ printf "words:\n"
+ printf "<%s>\n" "${words[@]}"
fi
-# option logic
+# collect info of cmdline
+for ((i=1; i < ${#words[@]}-1; i++)); do
+ case "${words[i]}" in
+ -) ((set_index)) && break || iactive=1 ;;
+ -a) ((set_index)) && break || show_all=1 ;;
+ -i) ((set_index)) && break || isolate=1 Copts=(-Co) ;;
+ -m) ((set_index)) && break || show_members=1 ;;
+ -n) ((set_index)) && break || names_only=1 ;;
+ -r) ((set_index)) && break || resolve=1 ;;
+ -t) ((set_index)) && break || headers_only=1 Xopts=(-Xh -Xs) Fopts=(${Fopts[*]/-Oi/}) ;;
+ --) ((set_index)) && break || set_index=$((i+1)) ;;
+ -\?|-h|-v)
+ ((set_index)) || return 0
+ ;;
+ @(-Fh|-Fi|-Hi|-Xh)) ((set_index)) && break || header_operation=1 ;;
+ *)
+ ((set_index)) && break
+ # options expecting an opt arg
+ str_tmp="-@(d|Fg|Fh|Fi|Fr|Gp|Gs|Gx|Hi|Ht|Hr|Hs|Hv|Mc|Oi|T|To|Xg|Xh|Xr|Xs)"
+ if [[ ${words[i-1]} = $str_tmp ]]; then
+ continue
+ elif [[ ${words[i-1]} = @(-Gp|-Gs|-Gx) && ${words[i]} != -* ]]; then
+ continue
+ fi
+ # if not an option, register set index
+ str_tmp="-@(-|?|a|c|d|h|i|m|n|r|s|t|v|Ca|Cs|Co|Fg|Fh|Fi|Fr|Gp|Gs|Gx|Hi|Ht|Hr|Hs|Hv|Mc|Oi|T|To|Tm|Ts|Xg|Xh|Xo|Xr)"
+ if [[ ${words[i]} != $str_tmp ]]; then
+ for x in ${!sets[@]}; do
+ if [[ ${sets[x]} = ${words[i]} ]]; then
+ set_index=$i
+ break
+ fi
+ done
+ fi
+ esac
+done
+
+# invalid combinations of options
if ((names_only)); then
- if ((headers_only||show_members||show_all||isolate||\
- glob_xclude_element||regex_xclude_element||xclude_member_opts))
- then
- ex_invalid_usage "option -n does not allow this combination of options"
- fi
-fi
-if ((headers_only)); then
- if ((show_members || show_all || isolate)); then
- ex_invalid_usage "options -t and -a|-i|-m are mutually exclusive"
- fi
+ if ((headers_only)); then
+ return 0
+ fi
fi
-if ((headers_only)); then
- if ((xclude_member_opts||glob_xclude_element||regex_xclude_element)); then
- ex_invalid_usage "options -t and -Xg|-Xr|-Xo are mutually exclusive"
- fi
+if ((headers_only||names_only)); then
+ if ((show_all || show_members || isolate || resolve)); then
+ return 0
+ fi
+elif ((isolate)); then
+ if ((show_all || header_operation)); then
+ return 0
+ fi
fi
-if ((isolate)); then
- if ((show_count||show_all||calc_mem||count_sets||sets_total||exclude_set)); then
- ex_invalid_usage "options -i and -a|-c|-Ca|-Cs|-Tm|-Ts|-Xs are mutually exclusive"
- fi
- if ((match_on_header)); then
- ex_invalid_usage "option -i does not allow matching on header entries"
- fi
-fi
-if ((glob_search || regex_search)); then
- if ((glob_search && regex_search)); then
- ex_invalid_usage "options -Fg and -Fr are mutually exclusive"
- fi
-fi
-if ((exclude_header)); then
- if ! ((headers_only || show_all)); then
- ex_invalid_usage "option -Xh requires -a or -t"
- fi
-fi
-if ((glob_xclude_element || regex_xclude_element)); then
- if ! ((show_members || show_all || isolate)); then
- ex_invalid_usage "options -Xg|-Xr require any of -a|-i|-m"
- fi
-fi
-if ((colorize)); then
- if ! [[ -x ${cl:=/usr/local/bin/cl} ]]; then
- printf "\ncl program \`%s' does not exist, or is not executable.\ncheck \`cl' variable.\n\n" "$cl" >&2
- printf "If you do not have the program, you can download it from:\n"
- printf "%s\n" "http://sourceforge.net/projects/colorize-shell/" \
- "https://github.com/AllKind/cl" >&2
- printf "\n"
- exit 1
- fi
- # set color defaults if unset
- : ${col_fg:=white}
- : ${col_bg:=black}
- : ${col_headers:=cyan}
- : ${col_members:=yellow}
- : ${col_match:=red}
- : ${col_memsize:=green}
- : ${col_set_count:=magenta}
- : ${col_set_total:=blue}
- : ${col_highlight:=white}
- # check if color defines are valid
- for opt in col_fg col_bg col_headers col_members col_match col_memsize \
- col_set_count col_set_total col_highlight
- do
- ("$cl" ${!opt}) || ex_invalid_usage "variable \`$opt' has an invalid color value: \`${!opt}'"
- done
- [[ -t 1 ]] || colorize=0 # output is not a terminal
-fi
-
-# sets to work on (no arg means all sets)
-while IFS=$'\n' read -r; do
- arr_sets[idx++]="$REPLY"
-done < <("$ipset" list -n)
-if ! ((${#arr_sets[@]})); then
- printf "Cannot find any sets\n" >&2
- exit 1
-fi
-if [[ $1 ]]; then # there are remaining arg(s)
- for opt; do found_set=0 # check if the sets exist
- for idx in ${!arr_sets[@]}; do
- if [[ ${arr_sets[idx]} = $opt ]]; then found_set=1
- # match could be a glob, thus multiple matches possible
- # save to temp array
- arr_tmp[${#arr_tmp[@]}]="${arr_sets[idx]}"
- unset arr_sets[idx]
- fi
- done
- if ! ((found_set)); then
- ex_invalid_usage "\`$opt' is not a valid option nor an existing set name"
- fi
- done
- if ((isolate)); then
- if (($# != 1)); then
- ex_invalid_usage "option -i is only valid for a single set"
- fi
- fi
- arr_sets=("${arr_tmp[@]}") # reassign matched sets
- if ((isolate && ${#arr_sets[@]} > 1)); then
- ex_invalid_usage "option -i is only valid for a single set"
- fi
+# start setting compreply
+# all depends on $set_index
+if ((set_index)); then
+ if ((isolate && cword > set_index)); then
+ return 0 # allow only one set with isolate
+ fi
+ # dont' allow an option after the set name(s)
+ # allows to list sets which start with an hyphen
+ # and also handles those who have the name of ipset_list options
+ _ipset_list_show_sets
else
- if ((isolate)); then
- ex_invalid_usage "option -i is only valid for a single set"
+if [[ $prev = -@(\?|d|h|v|Fg|Fi|Fr|Hi|Oi|T|To|Xg|Xr) ]]; then
+ return 0
+elif [[ $prev = -Xs ]]; then
+ # list sets if user does not want to enter a glob
+ _ipset_list_show_sets
+elif [[ $prev = -Ht ]]; then i=0
+ # show supported set types
+ while read -r; do
+ [[ $REPLY = "Supported set types:"* ]] && ((!i)) && \
+ i=1 && continue
+ ((i)) || continue
+ if [[ $REPLY = *:* ]]; then
+ set -- $REPLY
+ arr_types[${#arr_types[@]}]="$1"
+ fi
+ done < <(ipset help)
+ for i in ${!arr_types[@]}; do # remove dupe entries
+ for x in ${!arr_tmp[@]}; do
+ [[ ${arr_tmp[x]} = ${arr_types[i]} ]] && continue 2
+ done
+ arr_tmp[${#arr_tmp[@]}]="${arr_types[i]}"
+ done
+ arr_types=( "${arr_tmp[@]}" )
+ COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) )
+elif [[ $prev = @(-Fh|-Xh) ]]; then
+ # retrieve list of headers
+ if ((${#sets[*]} > 0)); then
+ while read -r; do
+ [[ $REPLY = Name ]] && continue
+ COMPREPLY[${#COMPREPLY[@]}]="$REPLY"
+ done < <(command "$ipset_list" -t "${sets[0]}" 2>/dev/null|command awk -F: '{print $1}')
+ compopt -o nospace
+ local IFS=$'\n'
+ if [[ $prev = -Xh ]]; then
+ COMPREPLY=( $( compgen -P '"' -S ':*"' \
+ -W '${COMPREPLY[@]}' -- "$cur" ) )
+ elif [[ $prev = -Fh ]]; then
+ COMPREPLY=( $( compgen -P '"' -S ':"' \
+ -W '${COMPREPLY[@]}' -- "$cur" ) )
+ fi
+ fi
+elif [[ $prev = @(-@(Hr|Hs|Hv|Mc)) ]]; then
+ # options making use of arithmetic comparison
+ compopt -o nospace
+ COMPREPLY=( $( compgen -P '\' -W '\! \< \> \<= \>=' -- "$cur" ) )
+elif [[ $prev = @(-Gp|-Gs|-Gx) && $cur != -* ]]; then # fails on files starting with a dash. I don't care.
+ if ((got_bashcompl)); then
+ _filedir
+ COMPREPLY=( $( compgen -W 'auto none ${COMPREPLY[@]}' -- "$cur" ) )
+ else
+ COMPREPLY=( $( compgen -f -- "$cur" ) )
fi
+elif [[ $cur = -* ]]; then
+ # any option is requested
+ case "$prev" in
+ -@(-|\?|d|h|v|Fg|Fh|Fi|Fr|Hi|Ht|Hr|Hs|Hv|Mc|Oi|T|To|Xg|Xh|Xr))
+ # options that exclude any other option,
+ # or need a value we can't predict
+ return 0
+ ;;
+ esac
+ if ((${#words[@]} > 2)); then
+ # these options don't allow any other - remove them
+ opts=("${opts[@]/@(-v|-h|-\?)/}")
+ fi
+ # some options allow only a subset of other options
+ if ((iactive)); then
+ COMPREPLY=( $(compgen -W '${Iopts[@]} ${Gopts[@]}' -- $cur ) )
+ elif ((isolate)); then
+ COMPREPLY=( $(compgen -W '-- -Co -d -r -s -Fg -Fr ${Gopts[@]} -Oi -T -To -Xg -Xo -Xr' -- $cur ) )
+ elif ((names_only)); then
+ COMPREPLY=( $(compgen -W \
+ '-- -c ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} -Xs' \
+ -- $cur ) )
+ elif ((headers_only)); then
+ COMPREPLY=( $(compgen -W \
+ '-- -c ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} ${Xopts[@]}' \
+ -- $cur ) )
+ elif ((show_members)); then
+ COMPREPLY=( $(compgen -W \
+ '-- -c -d -r -s ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} -Xg -Xr -Xo' \
+ -- $cur ) )
+ elif ((show_all)); then
+ COMPREPLY=( $(compgen -W \
+ '-- -c -d -r -s ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} ${Xopts[@]}' \
+ -- $cur ) )
+ elif ((resolve)); then
+ COMPREPLY=( $(compgen -W \
+ '-- -a -c -d -s -m ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} ${Xopts[@]}' \
+ -- $cur ) )
+ elif ((header_operation)); then
+ COMPREPLY=( $(compgen -W \
+ '-- -a -c -d -s -m -t ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} ${Xopts[@]}' \
+ -- $cur ) )
+ else
+ COMPREPLY=( $(compgen -W \
+ '${opts[@]} ${Copts[@]} ${Fopts[@]} ${Gopts[@]} ${Hopts[@]} -Mc ${Topts[@]} ${Xopts[@]}' \
+ -- $cur ) )
+ fi
+ # post process the reply
+ if ((${#COMPREPLY[@]})); then
+ x=$((set_index ? set_index : ${#words[*]}-1))
+ # mutual exclusive options
+ for ((i=1; i < x; i++)); do
+ case "${words[i]}" in
+ -Fg) _ipset_list_remove_reply_entry "-Fr" ;;
+ -Fr) _ipset_list_remove_reply_entry "-Fg" ;;
+ -Xg) _ipset_list_remove_reply_entry "-Xr" ;;
+ -Xr) _ipset_list_remove_reply_entry "-Xg" ;;
+ esac
+ # options allowed multiple times
+ if [[ ${words[i]} = @(""|-|-@(Fh|Fi|Hi|Mc|Oi|T|Xh|Xs)) ]]; then
+ continue
+ else # remove dupe
+ _ipset_list_remove_reply_entry "${words[i]}"
+ fi
+ done
+ fi
+elif [[ $cur = * ]]; then
+ # non option request
+ # default to sets listing
+ # except we are in interactive mode
+ if ! ((iactive)); then
+ _ipset_list_show_sets
+ fi
+fi
fi
-# read sets
-for idx in "${!arr_sets[@]}"; do found_set=0 arr_hcache=() arr_mcache=()
- while read -r || {
- (($? > 128)) && \
- printf "timeout reached or signal received, while reading set \`%s'.\n" \
- "${arr_sets[idx]}" >&2 && continue 2;
- }; do
- case "$REPLY" in
- "") : ;;
- Name:*) # header opened (set found)
- if ((in_header)); then
- printf "unexpected entry: \`%s' - header not closed?\n" "$REPLY" >&2
- exit 1
- fi
- let sets_sum+=1
- if ((exclude_set)); then # don't show certain sets
- for y in ${!arr_sxclude[@]}; do
- if [[ ${arr_sets[idx]} = ${arr_sxclude[y]} ]]; then let found_sxclude+=1
- continue 3 # don't unset, as user could list sets multiple times
- fi
- done
- fi
- in_header=1 found_set=1 found_header=0 member_count=0 match_count=0 xclude_count=0 mem_tmp=0 i=0 x=0
- if ! ((isolate)); then # if showing members only, continue without saving any header data
- if ((names_only)); then
- if ((colorize)); then
- arr_hcache[x++]="$("$cl" bold $col_headers)${REPLY#*:+([[:blank:]])}$("$cl" normal $col_fg $col_bg)"
- else
- arr_hcache[x++]="${REPLY#*:+([[:blank:]])}"
- fi
- elif ! ((headers_only||show_members||show_all||show_count||match_on_header||do_count||calc_mem||glob_search||regex_search||opt_int_search))
- then
- in_header=0
- if ((colorize)); then
- arr_hcache[x++]="$("$cl" bold $col_headers)${REPLY}$("$cl" normal $col_fg $col_bg)"
- else
- arr_hcache[x++]="$REPLY"
- fi
- break # nothing to show but the names
- else
- if ((colorize)); then
- arr_hcache[x++]=$'\n'"$("$cl" bold $col_headers)${REPLY}$("$cl" normal $col_fg $col_bg)"
- else
- arr_hcache[x++]=$'\n'"$REPLY"
- fi
- fi
- fi
- ;;
- Members:*) # closes header (if not `ipset -t')
- if ! ((in_header)); then
- printf "unexpected entry: \`%s' - header not opened?\n" "$REPLY" >&2
- exit 1
- fi
- in_header=0 found_hxclude=0
- if ((match_on_header)); then
- if ((found_header != match_on_header)); then found_set=0
- break # set does not contain wanted header
- fi
- fi
- if ((exclude_header)); then # don't show certain headers
- for y in ${!arr_hxclude[@]}; do
- if [[ ${REPLY%%:*} = ${arr_hxclude[y]%%:*} && ${REPLY#*: } = ${arr_hxclude[y]#*:} ]]
- then found_hxclude=1
- break
- fi
- done
- fi
- if ((show_all && ! found_hxclude)); then
- if ((colorize)); then
- arr_hcache[x++]="$("$cl" bold $col_headers)${REPLY}$("$cl" normal $col_fg $col_bg)"
- else
- arr_hcache[x++]="$REPLY"
- fi
- fi
- ;;
- *) # either in-header, or member entry
- if ! ((found_set)); then
- printf "no set opened by \`Name:'. unexpected entry \`%s'.\n" "$REPLY" >&2
- exit 1
- fi
- if ((in_header)); then # we should be in the header
- if ((match_on_header && found_header < match_on_header)); then # match on an header entry
- for y in ${!arr_hsearch[@]}; do # string compare
- if [[ ${REPLY%%:*} = ${arr_hsearch[y]%%:*} && ${REPLY#*: } = ${arr_hsearch[y]#*:} ]]
- then let found_header+=1
- fi
- done
- for y in ${!arr_hsearch_int[@]}; do # int compare
- if [[ ${REPLY%%:*} = ${arr_hsearch_int[y]%%:*} ]]; then # header name matches
- if ! is_int "${REPLY#*: }"; then
- printf "header value \`%s' is not an integer.\n" "${REPLY#*: }" >&2
- exit 1
- fi
- str_val="${arr_hsearch_int[y]#*:}"
- str_op="${str_val//[[:digit:]]}" # compare operator defaults to `=='
- [[ ${str_op:===} = \! ]] && str_op='!='
- if ((${REPLY#*: } $str_op ${str_val//[[:punct:]]})); then
- let found_header+=1
- fi
- fi
- done
- # search and arithmetic compare values of the headers 'Header' flag
- if ((${#arr_hsearch_xint[@]})) && [[ ${REPLY%%:*} = Header ]]; then
- set -- ${REPLY#*:}
- while (($#)); do
- if is_digit_or_xigit "$1"; then
- shift
- continue
- fi
- for y in ${!arr_hsearch_xint[@]}; do
- str_name="${arr_hsearch_xint[y]%%:*}"
- str_val="${arr_hsearch_xint[y]#*:}"
- if [[ $str_val = ??0[xX]+([[:xdigit:]]) ]]; then
- str_op="${str_val%0[xX]*}"
- elif [[ $str_val = ??+([[:digit:]]) ]]; then
- str_op="${str_val//[[:digit:]]}"
- fi
- str_val="${str_val#"${str_op}"}"
- [[ ${str_op:===} = \! ]] && str_op='!='
- if [[ $1 = $str_name ]]; then
- if is_digit_or_xigit "$2"; then
- if (($2 $str_op $str_val)); then
- let found_header+=1
- shift
- break
- fi
- fi
- fi
- done
- shift
- done
- fi
- fi
- if ((calc_mem)); then
- if [[ ${REPLY%%:*} = "Size in memory" ]]; then
- if ! is_int "${REPLY#*: }"; then
- printf "header value \`%s' is not an integer.\n" "${REPLY#*: }" >&2
- exit 1
- fi
- # save to temp, in case we throw away the set, if it doesn't match other criteria
- mem_tmp=${REPLY#*: }
- fi
- fi
- if ((headers_only || show_all)); then found_hxclude=0
- if ((exclude_header)); then # don't show certain headers
- for y in ${!arr_hxclude[@]}; do
- if [[ ${REPLY%%:*} = ${arr_hxclude[y]%%:*} && ${REPLY#*: } = ${arr_hxclude[y]#*:} ]]
- then found_hxclude=1
- break
- fi
- done
- fi
- if ! ((found_hxclude)); then
- arr_hcache[x++]="$REPLY"
- fi
- fi
- else # this should be a member entry
- if ((show_members || show_all || isolate || glob_search || regex_search || opt_int_search)); then
- if ((glob_search)); then # show sets with glob pattern matching members
- if ! xclude_elem_search; then
- if [[ $REPLY = $str_search ]]; then
- if ((opt_int_search)); then
- arith_elem_opt_search
- else
- let match_count+=1
- add_search_to_member_cache
- fi
- fi
- fi
- elif ((regex_search)); then # show sets with regex pattern matching members
- if ! xclude_elem_search; then
- if [[ $REPLY =~ $str_search ]]; then
- if ((opt_int_search)); then
- arith_elem_opt_search
- else
- let match_count+=1
- add_search_to_member_cache
- fi
- else
- if (($? == 2)); then
- printf "Invalid regex pattern \`%s'.\n" "$str_search" >&2
- exit 1
- fi
- fi
- fi
- elif ((opt_int_search)); then # show sets with matching member options
- if ! xclude_elem_search; then
- arith_elem_opt_search
- fi
- else
- if ((glob_xclude_element)); then # exclude matching members
- if ! [[ $REPLY = $str_xclude ]]; then
- add_search_to_member_cache
- else let xclude_count+=1
- fi
- elif ((regex_xclude_element)); then # exclude matching members
- if [[ $REPLY =~ $str_xclude ]]; then
- let xclude_count+=1
- else
- if (($? == 2)); then
- printf "Invalid regex pattern \`%s'.\n" "$str_xclude" >&2
- exit 1
- fi
- add_search_to_member_cache
- fi
- else
- arr_mcache[i++]="$REPLY"
- fi
- fi
- else # nothing to show or search for, do we need to count members?
- if ! ((show_count || do_count)); then
- break # nothing more to do for this set
- fi
- fi
- let member_count+=1
- fi
- esac
- done < <("$ipset" list "${arr_sets[idx]}" "${arr_par[@]}")
- if ((found_set)); then # print gathered information
- if ((glob_search || regex_search || opt_int_search)) && ((match_count == 0)); then
- continue # glob, regex or option-integer search didn't match
- fi
- if ((${#arr_match_on_msum[@]} > 0)); then # match on member sum (do_count=1)
- for i in ${!arr_match_on_msum[@]}; do
- str_op="${arr_match_on_msum[i]//[[:digit:]]}"
- [[ ${str_op:===} = \! ]] && str_op='!='
- if ! (($member_count $str_op ${arr_match_on_msum[i]//[[:punct:]]})); then
- continue 2 # does not match
- fi
- done
- fi
- let set_count+=1 # count amount of matching sets
- if ((calc_mem)); then
- let mem_total+=$mem_tmp
- fi
- if ((${#arr_hcache[@]})); then # print header
- if ((colorize)); then
- printf "$("$cl" $col_headers)%b$("$cl" normal $col_fg $col_bg)\n" "${arr_hcache[@]}"
- else
- printf "%s\n" "${arr_hcache[@]}"
- fi
- fi
- if ((${#arr_mcache[@]})); then # print members
- if ((xclude_member_opts)); then
- arr_mcache=( "${arr_mcache[@]%% *}" )
- fi
- IFS="${delim:= }"
- if ((colorize)); then
- printf "$("$cl" $col_members)%s$("$cl" normal $col_fg $col_bg)" "${arr_mcache[*]}"
- else
- printf "%s" "${arr_mcache[*]}"
- fi
- IFS="$oIFS"
- printf "\n"
- fi
- if ((show_count)); then # print counters
- if ((glob_search || regex_search || opt_int_search)); then
- if ((colorize)); then
- printf "$("$cl" $col_match)Match count$("$cl" normal $col_fg $col_bg):\
- $("$cl" bold $col_match)%d$("$cl" normal $col_fg $col_bg)\n" $match_count
- else
- printf "Match count: %d\n" $match_count
- fi
- fi
- if ((glob_xclude_element || regex_xclude_element)); then
- if ((colorize)); then
- printf "$("$cl" $col_match)Exclude count$("$cl" normal $col_fg $col_bg):\
- $("$cl" bold $col_match)%d$("$cl" normal $col_fg $col_bg)\n" $xclude_count
- else
- printf "Exclude count: %d\n" $xclude_count
- fi
- fi
- if ((colorize)); then
- printf "$("$cl" bold $col_highlight)Member count$("$cl" normal $col_fg $col_bg):\
- $("$cl" bold $col_members)%d$("$cl" normal $col_fg $col_bg)\n" $member_count
- else
- printf "Member count: %d\n" $member_count
- fi
- fi
- fi
-done
+((got_bashcompl)) && __ltrim_colon_completions "$cur"
-# print global counters
-if ((count_sets || calc_mem || sets_total || exclude_set)); then
- printf "\n"
- if ((count_sets)); then
- if ((colorize)); then
- printf "$("$cl" bold $col_highlight)Count$("$cl" normal $col_fg $col_bg) of all\
- $("$cl" bold $col_set_count)matched sets$("$cl" normal $col_fg $col_bg):\
- $("$cl" bold $col_set_count)%d$("$cl" normal $col_fg $col_bg)\n" $set_count
- else
- printf "Count of all matched sets: %d\n" $set_count
- fi
- if ((exclude_set)); then
- if ((colorize)); then
- printf "$("$cl" bold $col_highlight)Count$("$cl" normal $col_fg $col_bg) of all\
- $("$cl" bold $col_match)excluded sets$("$cl" normal $col_fg $col_bg):\
- $("$cl" bold $col_match)%d$("$cl" normal $col_fg $col_bg)\n" $found_sxclude
- else
- printf "Count of all excluded sets: %d\n" $found_sxclude
- fi
- fi
- fi
- if ((sets_total)); then
- if ((colorize)); then
- printf "$("$cl" bold $col_highlight)Count$("$cl" normal $col_fg $col_bg) of all\
- $("$cl" bold $col_set_total)traversed sets$("$cl" normal $col_fg $col_bg):\
- $("$cl" bold $col_set_total)%d$("$cl" normal $col_fg $col_bg)\n" $sets_sum
- else
- printf "Count of all traversed sets: %d\n" $sets_sum
- fi
- fi
- if ((calc_mem)); then
- if ((colorize)); then
- printf "$("$cl" bold $col_memsize)Total memory size$("$cl" normal $col_fg $col_bg)\
- of all matched sets: $("$cl" bold $col_memsize)%d$("$cl" normal $col_fg $col_bg)\n" $mem_total
- else
- printf "Total memory size of all matched sets: %d\n" $mem_total
- fi
- fi
+if [[ $_DEBUG_NF_COMPLETION ]]; then
+ printf "COMPREPLY:\n"
+ printf "<%s>\n" "${COMPREPLY[@]}"
fi
+}
+complete -F _ipset_list_complete "${ipset_list:-ipset_list}"
+