]> granicus.if.org Git - ipset/commitdiff
ipset 2.4 release
author/C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu </C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu>
Mon, 20 Oct 2008 10:00:26 +0000 (10:00 +0000)
committer/C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu </C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu>
Mon, 20 Oct 2008 10:00:26 +0000 (10:00 +0000)
userspace changes:
  - Added KBUILD_OUTPUT support (Sven Wegener)
  - Fix memory leak in ipset_iptreemap (Sven Wegener)
  - Fix multiple compiler warnings (Sven Wegener)
  - ipportiphash, ipportnethash and setlist types added
  - binding marked as deprecated functionality
  - element separator token changed to ',' in anticipating
    IPv6 addresses, old separator tokens are still supported
  - unnecessary includes removed
  - ipset does not try to resolve IP addresses when listing
    the content of sets (default changed)
  - manpage updated
  - ChangeLog forked for kernel part

kernel part changes:
  - ipportiphash, ipportnethash and setlist types added
  - set type modules reworked to avoid code duplication
    as much as possible, code unification macros
  - expand_macros Makefile target added to help debugging
    code unification macros
  - ip_set_addip_kernel and ip_set_delip_kernel
    changed from void to int, __ip_set_get_byname and
    __ip_set_put_byid added for the sake of setlist type
  - unnecessary includes removed
  - compatibility fix for kernels >= 2.6.27:
    semaphore.h was moved from asm/ to linux/ (James King)
  - ChangeLog forked for kernel part

60 files changed:
ChangeLog
Makefile
ipset.8
ipset.c
ipset.h
ipset_iphash.c
ipset_ipmap.c
ipset_ipporthash.c
ipset_ipportiphash.c [new file with mode: 0644]
ipset_ipportnethash.c [new file with mode: 0644]
ipset_iptree.c
ipset_iptreemap.c
ipset_macipmap.c
ipset_nethash.c
ipset_portmap.c
ipset_setlist.c [new file with mode: 0644]
kernel/ChangeLog
kernel/Config.in.ipset
kernel/Kbuild
kernel/Kconfig.ipset
kernel/Makefile
kernel/Makefile.ipset
kernel/expand_macros.pl [new file with mode: 0755]
kernel/include/linux/netfilter_ipv4/ip_set.h
kernel/include/linux/netfilter_ipv4/ip_set_bitmaps.h [new file with mode: 0644]
kernel/include/linux/netfilter_ipv4/ip_set_getport.h [new file with mode: 0644]
kernel/include/linux/netfilter_ipv4/ip_set_hashes.h [new file with mode: 0644]
kernel/include/linux/netfilter_ipv4/ip_set_iphash.h
kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h
kernel/include/linux/netfilter_ipv4/ip_set_ipporthash.h
kernel/include/linux/netfilter_ipv4/ip_set_ipportiphash.h [new file with mode: 0644]
kernel/include/linux/netfilter_ipv4/ip_set_ipportnethash.h [new file with mode: 0644]
kernel/include/linux/netfilter_ipv4/ip_set_iptree.h
kernel/include/linux/netfilter_ipv4/ip_set_iptreemap.h
kernel/include/linux/netfilter_ipv4/ip_set_macipmap.h
kernel/include/linux/netfilter_ipv4/ip_set_malloc.h
kernel/include/linux/netfilter_ipv4/ip_set_nethash.h
kernel/include/linux/netfilter_ipv4/ip_set_portmap.h
kernel/include/linux/netfilter_ipv4/ip_set_setlist.h [new file with mode: 0644]
kernel/ip_set.c
kernel/ip_set_iphash.c
kernel/ip_set_ipmap.c
kernel/ip_set_ipporthash.c
kernel/ip_set_ipportiphash.c [new file with mode: 0644]
kernel/ip_set_ipportnethash.c [new file with mode: 0644]
kernel/ip_set_iptree.c
kernel/ip_set_iptreemap.c
kernel/ip_set_macipmap.c
kernel/ip_set_nethash.c
kernel/ip_set_portmap.c
kernel/ip_set_setlist.c [new file with mode: 0644]
tests/ipporthash.t
tests/ipportiphash.t [new file with mode: 0644]
tests/ipportnethash.t [new file with mode: 0644]
tests/iptree.t
tests/iptreemap.t
tests/macipmap.t
tests/nethash.t
tests/runtest.sh
tests/setlist.t [new file with mode: 0644]

index 7d66ebe66351fe0f1670ab0fbcd1b704d9769537..93b1f0103cacd03652a2d8f401c3947e8e2f5012 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
-Tue, 02 Sep 2008
-       - ChangeLog forked for kernel part
+
+2.4
+  - Added KBUILD_OUTPUT support (Sven Wegener)
+  - Fix memory leak in ipset_iptreemap (Sven Wegener)
+  - Fix multiple compiler warnings (Sven Wegener)
+  - ipportiphash, ipportnethash and setlist types added
+  - binding marked as deprecated functionality
+  - element separator token changed to ',' in anticipating
+    IPv6 addresses, old separator tokens are still supported
+  - unnecessary includes removed
+  - ipset does not try to resolve IP addresses when listing
+    the content of sets (default changed)
+  - manpage updated
+  - ChangeLog forked for kernel part
 
 2.3.3a
  - Fix to compile ipset with 2.4.26.x tree statically (bug reported by
index 80f6ec179fc8b04459581351f237c2259576de24..a19221642d828a280c2414f7e63b6238de7e6dc0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,14 +7,20 @@
 ifndef KERNEL_DIR
 KERNEL_DIR=/usr/src/linux
 endif
+ifndef KBUILD_OUTPUT
+KBUILD_OUTPUT=$(KERNEL_DIR)
+endif
 ifndef IP_NF_SET_MAX
 IP_NF_SET_MAX=256
 endif
 ifndef IP_NF_SET_HASHSIZE
 IP_NF_SET_HASHSIZE=1024
 endif
+ifndef V
+V=0
+endif
 
-IPSET_VERSION:=2.3.3
+IPSET_VERSION:=2.4
 
 PREFIX:=/usr/local
 LIBDIR:=$(PREFIX)/lib
@@ -29,7 +35,10 @@ RELEASE_DIR:=/tmp
 COPT_FLAGS:=-O2
 CFLAGS:=$(COPT_FLAGS) -Wall -Wunused -Ikernel/include -I. # -g -DIPSET_DEBUG #-pg # -DIPTC_DEBUG
 SH_CFLAGS:=$(CFLAGS) -fPIC
-SETTYPES:=ipmap portmap macipmap iphash nethash iptree iptreemap ipporthash
+SETTYPES:=ipmap portmap macipmap
+SETTYPES+=iptree iptreemap
+SETTYPES+=iphash nethash ipporthash ipportiphash ipportnethash
+SETTYPES+=setlist
 
 PROGRAMS=ipset
 SHARED_LIBS=$(foreach T, $(SETTYPES),libipset_$(T).so)
@@ -53,12 +62,12 @@ patch_kernel:
 modules:
        @[ ! -f $(KERNEL_DIR)/net/ipv4/netfilter/Config.in ] || (echo "Error: The directory '$(KERNEL_DIR)' looks like a Linux 2.4.x kernel source tree, you have to patch it by 'make patch_kernel'." && exit 1)
        @[ -f $(KERNEL_DIR)/net/ipv4/netfilter/Kconfig ] || (echo "Error: The directory '$(KERNEL_DIR)' doesn't look like a Linux 2.6.x kernel source tree." && exit 1)
-       @[ -f $(KERNEL_DIR)/.config ] || (echo "Error: The kernel source in '$(KERNEL_DIR)' must be configured" && exit 1)
-       @[ -f $(KERNEL_DIR)/Module.symvers ] || echo "Warning: You should run 'make modules' in '$(KERNEL_DIR)' beforehand"
-       cd kernel; make -C $(KERNEL_DIR) M=`pwd` IP_NF_SET_MAX=$(IP_NF_SET_MAX) IP_NF_SET_HASHSIZE=$(IP_NF_SET_HASHSIZE) modules
+       @[ -f $(KBUILD_OUTPUT)/.config ] || (echo "Error: The kernel source in '$(KERNEL_DIR)' must be configured" && exit 1)
+       @[ -f $(KBUILD_OUTPUT)/Module.symvers ] || echo "Warning: You should run 'make modules' in '$(KERNEL_DIR)' beforehand"
+       cd kernel; make -C $(KBUILD_OUTPUT) M=`pwd` V=$V IP_NF_SET_MAX=$(IP_NF_SET_MAX) IP_NF_SET_HASHSIZE=$(IP_NF_SET_HASHSIZE) modules
 
 modules_install: modules
-       cd kernel; make -C $(KERNEL_DIR) M=`pwd` modules_install
+       cd kernel; make -C $(KBUILD_OUTPUT) M=`pwd` modules_install
 
 install: binaries_install modules_install
 
@@ -67,14 +76,14 @@ clean: $(EXTRA_CLEANS)
        [ -f $(KERNEL_DIR)/net/ipv4/netfilter/Config.in ] || (cd kernel; make -C $(KERNEL_DIR) M=`pwd` clean)
 
 #The ipset(8) self
-ipset.o: ipset.c
+ipset.o: ipset.c ipset.h
        $(CC) $(CFLAGS) -DIPSET_VERSION=\"$(IPSET_VERSION)\" -DIPSET_LIB_DIR=\"$(IPSET_LIB_DIR)\" -c -o $@ $<
 
 ipset: ipset.o
-       $(CC) $(CFLAGS) -ldl -rdynamic -o $@ $^
+       $(CC) $(CFLAGS) -rdynamic -o $@ $^ -ldl
 
 #Pooltypes
-ipset_%.o: ipset_%.c
+ipset_%.o: ipset_%.c ipset.h
        $(CC) $(SH_CFLAGS) -o $@ -c $<
 
 libipset_%.so: ipset_%.o
diff --git a/ipset.8 b/ipset.8
index 2c4edcb25bfd1b73f56a941cbd25cab77ce10bbf..0d578699edcd04c18ec23133afc9039c0df37513 100644 (file)
--- a/ipset.8
+++ b/ipset.8
@@ -87,14 +87,9 @@ is given. Bindings are not affected by the flush operation.
 Rename a set. Set identified by to-setname must not exist.
 .TP
 .BI "-W, --swap " "\fIfrom-setname\fP \fIto-setname\fP"
-Swap two sets as they referenced in the Linux kernel.
-.B
-iptables
-rules or
-.B
-ipset
-bindings pointing to the content of from-setname will point to 
-the content of to-setname and vice versa. Both sets must exist.
+Swap the content of two sets, or in another words, 
+exchange the name of two sets. The referred sets must exist and
+identical type of sets can be swapped only.
 .TP
 .BI "-L, --list " "[\fIsetname\fP]"
 List the entries and bindings for the specified set, or for
@@ -203,12 +198,12 @@ ipset supports the following set types:
 The ipmap set type uses a memory range, where each bit represents
 one IP address. An ipmap set can store up to 65536 (B-class network)
 IP addresses. The ipmap set type is very fast and memory cheap, great
-for use when one want to match certain IPs in a range. Using the
+for use when one want to match certain IPs in a range. If the optional
 .B "--netmask"
-option with a CIDR netmask value between 0-32 when creating an ipmap
-set, you will be able to store and match network addresses: i.e an
-IP address will be in the set if the value resulted by masking the address
-with the specified netmask can be found in the set.
+parameter is specified with a CIDR netmask value between 1-31 then
+network addresses are stored in the given set: i.e an
+IP address will be in the set if the network address, which is resulted
+by masking the address with the specified netmask, can be found in the set.
 .P
 Options to use when creating an ipmap set:
 .TP
@@ -225,17 +220,16 @@ When the optional
 .B "--netmask"
 parameter specified, network addresses will be 
 stored in the set instead of IP addresses, and the from-IP parameter
-must be a network address.
+must be a network address. The CIDR-netmask value must be between 1-31.
 .SS macipmap
 The macipmap set type uses a memory range, where each 8 bytes
 represents one IP and a MAC addresses. A macipmap set type can store
 up to 65536 (B-class network) IP addresses with MAC.
 When adding an entry to a macipmap set, you must specify the entry as
-.I IP:MAC.
+.I IP,MAC.
 When deleting or testing macipmap entries, the
-.I :MAC
-part is not mandatory. (The old "%" separation token instead of ":", i.e
-IP%MAC is accepted as well.)
+.I ,MAC
+part is not mandatory.
 .P
 Options to use when creating an macipmap set:
 .TP
@@ -279,12 +273,12 @@ Create a portmap set from the specified range.
 The iphash set type uses a hash to store IP addresses.
 In order to avoid clashes in the hash double-hashing, and as a last
 resort, dynamic growing of the hash performed. The iphash set type is
-great to store random addresses. By supplyig the
+great to store random addresses. If the optional
 .B "--netmask"
-option with a CIDR netmask value between 0-32 at creating the set,
-you will be able to store and match network addresses instead: i.e 
-an IP address will be in the set if the value of the address
-masked with the specified netmask can be found in the set.
+parameter is specified with a CIDR netmask value between 1-31 then
+network addresses are stored in the given set: i.e an
+IP address will be in the set if the network address, which is resulted
+by masking the address with the specified netmask, can be found in the set.
 .P
 Options to use when creating an iphash set:
 .TP
@@ -306,21 +300,22 @@ number of double-hashing.
 When the optional
 .B "--netmask"
 parameter specified, network addresses will be 
-stored in the set instead of IP addresses.
+stored in the set instead of IP addresses. The CIDR-netmask value must
+be between 1-31.
 .P
 The iphash type of sets can store up to 65536 entries. If a set is full,
 no new entries can be added to it.
 .P
 Sets created by zero valued resize parameter won't be resized at all.
-The lookup time in an iphash type of set approximately linearly grows with
+The lookup time in an iphash type of set grows approximately linearly with
 the value of the 
 .B
 probes
-parameter. At the same time higher 
+parameter. In general higher 
 .B
-probes
-values result a better utilized hash while smaller values 
-produce a larger, sparse hash.
+probe
+value results better utilized hash while smaller value
+produces larger, sparser hash.
 .SS nethash
 The nethash set type uses a hash to store different size of
 network addresses. The
@@ -349,18 +344,18 @@ an IP to the hash could not be performed after
 The nethash type of sets can store up to 65536 entries. If a set is full,
 no new entries can be added to it.
 .P
-An IP address will be in a nethash type of set if it is in any of the
-netblocks added to the set and the matching always start from the smallest
-size of netblock (most specific netmask) to the biggest ones (least
+An IP address will be in a nethash type of set if it belongs to any of the
+netblocks added to the set. The matching always start from the smallest
+size of netblock (most specific netmask) to the largest ones (least
 specific netmasks). When adding/deleting IP addresses
 to a nethash set by the
 .I
 SET
 netfilter kernel module, it will be added/deleted by the smallest
-netblock size which can be found in the set.
+netblock size which can be found in the set, or by /31 if the set is empty.
 .P
-The lookup time in a nethash type of set is approximately linearly 
-grows with the times of the
+The lookup time in a nethash type of set grows approximately linearly 
+with the times of the
 .B
 probes
 parameter and the number of different mask parameters in the hash.
@@ -374,8 +369,7 @@ store up to 65536 (B-class network) IP addresses with all possible port
 values. When adding, deleting and testing values in an ipporthash type of
 set, the entries must be specified as
 .B
-"IP:port".
-(Old "IP%port" format accepted as well.)
+"IP,port".
 .P
 The ipporthash types of sets evaluates two src/dst parameters of the 
 .I
@@ -411,6 +405,94 @@ number of double-hashing.
 .P
 The same resizing, speed and memory efficiency comments applies here 
 as at the iphash type.
+.SS ipportiphash
+The ipportiphash set type uses a hash to store IP address,port and IP
+address triples. The first IP address must come form a maximum /16
+sized network or range while the port number and the second IP address
+parameters are arbitrary. When adding, deleting and testing values in an 
+ipportiphash type of set, the entries must be specified as
+.B
+"IP,port,IP".
+.P
+The ipportiphash types of sets evaluates three src/dst parameters of the 
+.I
+set
+match and 
+.I
+SET
+target. 
+.P
+Options to use when creating an ipportiphash set:
+.TP
+.BR "--from " from-IP
+.TP
+.BR "--to " to-IP
+Create an ipportiphash set from the specified range.
+.TP
+.BR "--network " IP/mask
+Create an ipportiphash set from the specified network.
+.TP
+.BR "--hashsize " hashsize
+The initial hash size (default 1024)
+.TP
+.BR "--probes " probes
+How many times try to resolve clashing at adding an IP to the hash 
+by double-hashing (default 8).
+.TP
+.BR "--resize " percent
+Increase the hash size by this many percent (default 50) when adding
+an IP to the hash could not be performed after
+.B
+probes
+number of double-hashing.
+.P
+The same resizing, speed and memory efficiency comments applies here 
+as at the iphash type.
+.SS ipportnethash
+The ipportnethash set type uses a hash to store IP address, port, and
+network address triples. The IP address must come form a maximum /16
+sized network or range while the port number and the network address
+parameters are arbitrary, but the size of the network address must be
+between /1-/31. When adding, deleting 
+and testing values in an ipportnethash type of set, the entries must be
+specified as
+.B
+"IP,port,IP/cidr-size".
+.P
+The ipportnethash types of sets evaluates three src/dst parameters of the 
+.I
+set
+match and 
+.I
+SET
+target. 
+.P
+Options to use when creating an ipportnethash set:
+.TP
+.BR "--from " from-IP
+.TP
+.BR "--to " to-IP
+Create an ipporthash set from the specified range.
+.TP
+.BR "--network " IP/mask
+Create an ipporthash set from the specified network.
+.TP
+.BR "--hashsize " hashsize
+The initial hash size (default 1024)
+.TP
+.BR "--probes " probes
+How many times try to resolve clashing at adding an IP to the hash 
+by double-hashing (default 8).
+.TP
+.BR "--resize " percent
+Increase the hash size by this many percent (default 50) when adding
+an IP to the hash could not be performed after
+.B
+probes
+number of double-hashing.
+.P
+The same resizing, speed and memory efficiency comments applies here 
+as at the iphash type.
 .SS iptree
 The iptree set type uses a tree to store IP addresses, optionally 
 with timeout values.
@@ -424,7 +506,7 @@ If a set was created with a nonzero valued
 .B "--timeout"
 parameter then one may add IP addresses to the set with a specific 
 timeout value using the syntax 
-.I IP:timeout-value.
+.I IP,timeout-value.
 Similarly to the hash types, the iptree type of sets can store up to 65536
 entries.
 .SS iptreemap
@@ -432,12 +514,67 @@ The iptreemap set type uses a tree to store IP addresses or networks,
 where the last octet of an IP address are stored in a bitmap.
 As input entry, you can add IP addresses, CIDR blocks or network ranges
 to the set. Network ranges can be specified in the format
-.I IP1:IP2
+.I IP1-IP2
 .P
 Options to use when creating an iptreemap set:
 .TP
 .BR "--gc " value
 How often the garbage collection should be called, in seconds (default 300)
+.SS setlist
+The setlist type uses a simple list in which you can store sets. By the
+.I
+ipset
+command you can add, delete and test sets in a setlist type of set.
+You can specify the sets as
+.B
+"setname[,after|before,setname]".
+By default new sets are added after (appended to) the existing
+elements. Setlist type of sets cannot be added to a setlist type of set.
+.P
+Options to use when creating a setlist type of set:
+.TP
+.BR "--size " size
+Create a setlist type of set with the given size (default 8).
+.P
+By the
+.I
+set
+match or
+.I
+SET
+target of
+.I
+iptables
+you can test, add or delete entries in the sets. The match
+will try to find a matching IP address/port in the sets and 
+the target will try to add the IP address/port to the first set
+to which it can be added. The number of src,dst options of
+the match and target are important: sets which eats more src,dst
+parameters than specified are skipped, while sets with equal
+or less parameters are checked, elements added. For example
+if
+.I
+a
+and
+.I
+b
+are setlist type of sets then in the command
+.TP
+iptables -m set --match-set a src,dst -j SET --add-set b src,dst
+the match and target will skip any set in
+.I a
+and
+.I b
+which stores 
+data triples, but will check all sets with single or double
+data storage in
+.I a
+set and add src to the first single or src,dst to the first double 
+data storage set in
+.I b.
+.P
+You can imagine a setlist type of set as an ordered union of
+the set elements. 
 .SH GENERAL RESTRICTIONS
 Setnames starting with colon (:) cannot be defined. Zero valued set 
 entries cannot be used with hash type of sets.
@@ -447,6 +584,8 @@ If you want to store same size subnets from a given network
 If you want to store random same size networks (say random /24 blocks), 
 use the iphash set type. If you have got random size of netblocks, 
 use nethash.
+.P
+Old separator tokens (':' and '%") are still accepted.
 .SH DIAGNOSTICS
 Various error messages are printed to standard error.  The exit code
 is 0 for correct functioning.  Errors which appear to be caused by
diff --git a/ipset.c b/ipset.c
index bd23758a0e9b417d1b4fbe894598876cd0d9efdb..d57318a6f77fcbf25d0a8e22242eb0125a54b385 100644 (file)
--- a/ipset.c
+++ b/ipset.c
 #include <string.h>
 #include <errno.h>
 #include <time.h>
-#include <ctype.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <sys/socket.h>
-#include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <arpa/inet.h>
@@ -23,7 +20,6 @@
 #include <netdb.h>
 #include <dlfcn.h>
 #include <fcntl.h>
-/* #include <asm/bitops.h> */
 
 #include "ipset.h"
 
@@ -75,9 +71,10 @@ static const char cmdflags[] = { ' ',                        /* CMD_NONE */
 #define OPT_QUIET              0x0004U         /* -q */
 #define OPT_DEBUG              0x0008U         /* -z */
 #define OPT_BINDING            0x0010U         /* -b */
-#define NUMBER_OF_OPT 5
+#define OPT_RESOLVE            0x0020U         /* -r */
+#define NUMBER_OF_OPT 6
 static const char optflags[] =
-    { 'n', 's', 'q', 'z', 'b' };
+    { 'n', 's', 'q', 'z', 'b', 'r' };
 
 static struct option opts_long[] = {
        /* set operations */
@@ -105,6 +102,7 @@ static struct option opts_long[] = {
        {"sorted",  0, 0, 's'},
        {"quiet",   0, 0, 'q'},
        {"binding", 1, 0, 'b'},
+       {"resolve", 0, 0, 'r'},
 
 #ifdef IPSET_DEBUG
        /* debug (if compiled with it) */
@@ -120,7 +118,7 @@ static struct option opts_long[] = {
 };
 
 static char opts_short[] =
-    "-N:X::F::E:W:L::S::RA:D:T:B:U:nsqzb:Vh::H::";
+    "-N:X::F::E:W:L::S::RA:D:T:B:U:nrsqzb:Vh::H::";
 
 /* Table of legal combinations of commands and options. If any of the
  * given commands make an option legal, that option is legal.
@@ -132,21 +130,21 @@ static char opts_short[] =
 
 static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = {
        /*            -n   -s   -q   -z   -b  */
-        /*CREATE*/  {'x', 'x', ' ', ' ', 'x'},
-        /*DESTROY*/ {'x', 'x', ' ', ' ', 'x'},
-        /*FLUSH*/   {'x', 'x', ' ', ' ', 'x'},
-        /*RENAME*/  {'x', 'x', ' ', ' ', 'x'},
-        /*SWAP*/    {'x', 'x', ' ', ' ', 'x'},
-        /*LIST*/    {' ', ' ', 'x', ' ', 'x'},
-        /*SAVE*/    {'x', 'x', ' ', ' ', 'x'},
-        /*RESTORE*/ {'x', 'x', ' ', ' ', 'x'},
-        /*ADD*/     {'x', 'x', ' ', ' ', 'x'},
-        /*DEL*/     {'x', 'x', ' ', ' ', 'x'},
-        /*TEST*/    {'x', 'x', ' ', ' ', ' '},
-        /*BIND*/    {'x', 'x', ' ', ' ', '+'},
-        /*UNBIND*/  {'x', 'x', ' ', ' ', 'x'},
-        /*HELP*/    {'x', 'x', 'x', ' ', 'x'},
-        /*VERSION*/ {'x', 'x', 'x', ' ', 'x'},
+        /*CREATE*/  {'x', 'x', ' ', ' ', 'x', 'x'},
+        /*DESTROY*/ {'x', 'x', ' ', ' ', 'x', 'x'},
+        /*FLUSH*/   {'x', 'x', ' ', ' ', 'x', 'x'},
+        /*RENAME*/  {'x', 'x', ' ', ' ', 'x', 'x'},
+        /*SWAP*/    {'x', 'x', ' ', ' ', 'x', 'x'},
+        /*LIST*/    {' ', ' ', 'x', ' ', 'x', ' '},
+        /*SAVE*/    {'x', 'x', ' ', ' ', 'x', 'x'},
+        /*RESTORE*/ {'x', 'x', ' ', ' ', 'x', 'x'},
+        /*ADD*/     {'x', 'x', ' ', ' ', 'x', 'x'},
+        /*DEL*/     {'x', 'x', ' ', ' ', 'x', 'x'},
+        /*TEST*/    {'x', 'x', ' ', ' ', ' ', 'x'},
+        /*BIND*/    {'x', 'x', ' ', ' ', '+', 'x'},
+        /*UNBIND*/  {'x', 'x', ' ', ' ', 'x', 'x'},
+        /*HELP*/    {'x', 'x', 'x', ' ', 'x', 'x'},
+        /*VERSION*/ {'x', 'x', 'x', ' ', 'x', 'x'},
 };
 
 /* Main parser function */
@@ -349,11 +347,12 @@ static void kernel_error(unsigned cmd, int err)
          { ENOENT, 0, "Unknown set" },
          { EAGAIN, 0, "Sets are busy, try again later" },
          { ERANGE, CMD_CREATE, "No free slot remained to add a new set" },
-         { ERANGE, 0, "IP/port is outside of the set" },
+         { ERANGE, 0, "IP/port/element is outside of the set or set is full" },
          { ENOEXEC, CMD_CREATE, "Invalid parameters to create a set" },
          { ENOEXEC, CMD_SWAP, "Sets with different types cannot be swapped" },
          { EEXIST, CMD_CREATE, "Set already exists" },
          { EEXIST, CMD_RENAME, "Set with new name already exists" },
+         { EEXIST, 0, "Set specified as element does not exist" },
          { EBUSY, 0, "Set is in use, operation not permitted" },
          };
        for (i = 0; i < sizeof(table)/sizeof(struct translate_error); i++) {
@@ -429,7 +428,7 @@ static void kernel_sendto(unsigned cmd, void *data, size_t size)
                kernel_error(cmd, errno);
 }
 
-static int kernel_getfrom_handleerrno(unsigned cmd, void *data, size_t * size)
+static int kernel_getfrom_handleerrno(unsigned cmd, void *data, socklen_t *size)
 {
        int res = wrapped_getsockopt(data, size);
 
@@ -856,7 +855,7 @@ void settype_register(struct settype *settype)
 }
 
 /* Find set functions */
-static struct set *set_find_byid(ip_set_id_t id)
+struct set *set_find_byid(ip_set_id_t id)
 {
        struct set *set = NULL;
        ip_set_id_t i;
@@ -873,7 +872,7 @@ static struct set *set_find_byid(ip_set_id_t id)
        return set;
 }
 
-static struct set *set_find_byname(const char *name)
+struct set *set_find_byname(const char *name)
 {
        struct set *set = NULL;
        ip_set_id_t i;
@@ -1134,6 +1133,11 @@ static size_t save_bindings(void *data, size_t offset, size_t len)
        if (!(set && set_list[hash->binding]))
                exit_error(OTHER_PROBLEM,
                           "Save binding failed, try again later.");
+       if (!set->settype->bindip_tostring)
+               exit_error(OTHER_PROBLEM,
+                          "Internal error, binding is not supported with set %s"
+                          " of settype %s\n",
+                          set->name, set->settype->typename);
        printf("-B %s %s -b %s\n",
                set->name,
                set->settype->bindip_tostring(set, hash->ip, OPT_NUMERIC),
@@ -1638,9 +1642,14 @@ static int set_bind(struct set *set, const char *adt,
        DP("(%s, %s) -> %s", set ? set->name : IPSET_TOKEN_ALL, adt, binding);
 
        /* Ugly */
-       if (set && strcmp(set->settype->typename, "iptreemap") == 0)
+       if (set != NULL
+           && ((strcmp(set->settype->typename, "iptreemap") == 0)
+               || (strcmp(set->settype->typename, "ipportiphash") == 0)
+               || (strcmp(set->settype->typename, "ipportnethash") == 0)
+               || (strcmp(set->settype->typename, "setlist") == 0)))
                exit_error(PARAMETER_PROBLEM,
-                       "iptreemap type of sets cannot be used at binding operations\n");
+                       "%s type of sets cannot be used at binding operations\n",
+                       set->settype->typename);
        /* Alloc memory for the data to send */
        size = sizeof(struct ip_set_req_bind);
        if (op != IP_SET_OP_UNBIND_SET && adt[0] == ':')
@@ -1714,8 +1723,14 @@ static void set_restore_bind(struct set *set,
        DP("%s -> %s", adt, binding);
        if (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0)
                hash_restore->ip = 0;
-       else
+       else {
+               if (!set->settype->bindip_parse)
+                       exit_error(OTHER_PROBLEM,
+                                  "Internal error, binding is not supported with set %s"
+                                  " of settype %s\n",
+                                  set->name, set->settype->typename);
                set->settype->bindip_parse(adt, &hash_restore->ip);
+       }
        hash_restore->id = set->index;                     
        hash_restore->binding = (set_find_byname(binding))->index;      
        DP("id %u, ip %u, binding %u",
@@ -1735,6 +1750,12 @@ static void print_bindings(struct set *set,
        size_t offset = 0;
        struct ip_set_hash_list *hash;
 
+       if (offset < size && !printip)
+               exit_error(OTHER_PROBLEM,
+                          "Internal error, binding is not supported with set %s"
+                          " of settype %s\n",
+                          set->name, set->settype->typename);
+
        while (offset < size) {
                hash = (struct ip_set_hash_list *) (data + offset);
                printf("%s -> %s\n", 
@@ -1747,7 +1768,7 @@ static void print_bindings(struct set *set,
 /* Help function to set_list() */
 static size_t print_set(void *data, unsigned options)
 {
-       struct ip_set_list *setlist = (struct ip_set_list *) data;
+       struct ip_set_list *setlist = data;
        struct set *set = set_list[setlist->index];
        struct settype *settype = set->settype;
        size_t offset;
@@ -1781,7 +1802,8 @@ static size_t print_set(void *data, unsigned options)
        /* Print bindings */
        printf("Bindings:\n");
        offset += setlist->members_size;
-       print_bindings(set,
+       if (set->settype->bindip_tostring)
+               print_bindings(set,
                       data + offset, setlist->bindings_size, options,
                       settype->bindip_tostring);
 
@@ -1798,6 +1820,10 @@ static int try_list_sets(const char name[IP_SET_MAXNAMELEN],
        socklen_t size, req_size;
        int res = 0;
 
+       /* Default is numeric listing */
+       if (!(options & (OPT_RESOLVE|OPT_NUMERIC)))
+               options |= OPT_NUMERIC;
+
        DP("%s", name);
        /* Load set_list from kernel */
        size = req_size = load_set_list(name, &idx,
@@ -1907,7 +1933,8 @@ static void set_help(const struct settype *settype)
               "                    Prints version information\n\n"
               "Options:\n"
               "  --sorted     -s   Numeric sort of the IPs in -L\n"
-              "  --numeric    -n   Numeric output of addresses in a -L\n"
+              "  --numeric    -n   Numeric output of addresses in a -L (default)\n"
+              "  --resolve    -r   Try to resolve addresses in a -L\n"
               "  --quiet      -q   Suppress any output to stdout and stderr.\n"
               "  --binding    -b   Specifies the binding for -B\n");
        printf(debughelp);
@@ -2143,6 +2170,11 @@ int parse_commandline(int argc, char *argv[])
                        add_option(&options, OPT_NUMERIC);
                        break;
 
+               case 'r':
+                       if (!(options & OPT_NUMERIC))
+                               add_option(&options, OPT_RESOLVE);
+                       break;
+
                case 's':
                        add_option(&options, OPT_SORTED);
                        break;
@@ -2269,6 +2301,8 @@ int parse_commandline(int argc, char *argv[])
                break;
 
        case CMD_BIND:
+               fprintf(stderr, "Warning: binding will be removed from the next release.\n"
+                               "Please replace bindigs with sets of ipportmap and ipportiphash types\n");
                if (restore)
                        set_restore_bind(set, adt, binding);
                else
diff --git a/ipset.h b/ipset.h
index ad43f65d22073b274de54cb0b079b6ab5ea66b8c..3e181c4a19f5223c711624143303b09741ed2b87 100644 (file)
--- a/ipset.h
+++ b/ipset.h
@@ -21,8 +21,6 @@
  */
 
 #include <getopt.h>
-#include <sys/types.h>
-#include <netdb.h>
 
 #include <linux/netfilter_ipv4/ip_set.h>
 
@@ -184,6 +182,9 @@ extern void *ipset_malloc(size_t size);
 extern char *ipset_strdup(const char *);
 extern void ipset_free(void **data);
 
+extern struct set *set_find_byname(const char *name);
+extern struct set *set_find_byid(ip_set_id_t id);
+
 #define BITSPERBYTE    (8*sizeof(char))
 #define ID2BYTE(id)    ((id)/BITSPERBYTE)
 #define ID2MASK(id)    (1 << ((id)%BITSPERBYTE))
index 573ad6357101e23d53754921f5213c984635f510..6dbb84b530fa8ee3d21c532e465d294136edffab 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#include <errno.h>
-#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/types.h>
 
 #include <linux/netfilter_ipv4/ip_set_iphash.h>
-#include <linux/netfilter_ipv4/ip_set_jhash.h>
-
 #include "ipset.h"
 
 #define BUFLEN 30;
@@ -44,8 +34,7 @@
 static void
 create_init(void *data)
 {
-       struct ip_set_req_iphash_create *mydata =
-           (struct ip_set_req_iphash_create *) data;
+       struct ip_set_req_iphash_create *mydata = data;
 
        DP("create INIT");
 
@@ -131,8 +120,7 @@ static void
 create_final(void *data, unsigned int flags)
 {
 #ifdef IPSET_DEBUG
-       struct ip_set_req_iphash_create *mydata =
-           (struct ip_set_req_iphash_create *) data;
+       struct ip_set_req_iphash_create *mydata = data;
 
        DP("hashsize %u probes %u resize %u",
           mydata->hashsize, mydata->probes, mydata->resize);
@@ -152,8 +140,7 @@ static const struct option create_opts[] = {
 static ip_set_ip_t
 adt_parser(unsigned cmd, const char *optarg, void *data)
 {
-       struct ip_set_req_iphash *mydata =
-           (struct ip_set_req_iphash *) data;
+       struct ip_set_req_iphash *mydata = data;
 
        parse_ip(optarg, &mydata->ip);
        if (!mydata->ip)
@@ -170,10 +157,8 @@ adt_parser(unsigned cmd, const char *optarg, void *data)
 static void
 initheader(struct set *set, const void *data)
 {
-       struct ip_set_req_iphash_create *header =
-           (struct ip_set_req_iphash_create *) data;
-       struct ip_set_iphash *map =
-               (struct ip_set_iphash *) set->settype->header;
+       const struct ip_set_req_iphash_create *header = data;
+       struct ip_set_iphash *map = set->settype->header;
 
        memset(map, 0, sizeof(struct ip_set_iphash));
        map->hashsize = header->hashsize;
@@ -201,8 +186,7 @@ mask_to_bits(ip_set_ip_t mask)
 static void
 printheader(struct set *set, unsigned options)
 {
-       struct ip_set_iphash *mysetdata =
-           (struct ip_set_iphash *) set->settype->header;
+       struct ip_set_iphash *mysetdata = set->settype->header;
 
        printf(" hashsize: %u", mysetdata->hashsize);
        printf(" probes: %u", mysetdata->probes);
@@ -230,8 +214,7 @@ printips(struct set *set, void *data, size_t len, unsigned options)
 static void
 saveheader(struct set *set, unsigned options)
 {
-       struct ip_set_iphash *mysetdata =
-           (struct ip_set_iphash *) set->settype->header;
+       struct ip_set_iphash *mysetdata = set->settype->header;
 
        printf("-N %s %s --hashsize %u --probes %u --resize %u",
               set->name, set->settype->typename,
index d628767647e647d384e27caf48b9e7c99c3c1a39..f1586bb51caef9fe5f1a0e0902c1fc879017475e 100644 (file)
 
 #include <stdio.h>
 #include <string.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
 #include <arpa/inet.h>
-/* #include <asm/bitops.h> */
 
 #include <linux/netfilter_ipv4/ip_set_ipmap.h>
 #include "ipset.h"
@@ -40,8 +37,7 @@
 static void
 create_init(void *data)
 {
-       struct ip_set_req_ipmap_create *mydata =
-           (struct ip_set_req_ipmap_create *) data;
+       struct ip_set_req_ipmap_create *mydata = data;
 
        DP("create INIT");
        mydata->netmask = 0xFFFFFFFF;
@@ -51,8 +47,7 @@ create_init(void *data)
 static int
 create_parse(int c, char *argv[], void *data, unsigned *flags)
 {
-       struct ip_set_req_ipmap_create *mydata =
-           (struct ip_set_req_ipmap_create *) data;
+       struct ip_set_req_ipmap_create *mydata = data;
        unsigned int bits;
 
        DP("create_parse");
@@ -118,16 +113,12 @@ create_parse(int c, char *argv[], void *data, unsigned *flags)
        return 1;
 }
 
-#define ERRSTRLEN      256
-
 /* Final check; exit if not ok. */
 static void
 create_final(void *data, unsigned int flags)
 {
-       struct ip_set_req_ipmap_create *mydata =
-           (struct ip_set_req_ipmap_create *) data;
+       struct ip_set_req_ipmap_create *mydata = data;
        ip_set_ip_t range;
-       char errstr[ERRSTRLEN];
 
        if (flags == 0)
                exit_error(PARAMETER_PROBLEM,
@@ -157,7 +148,7 @@ create_final(void *data, unsigned int flags)
        if (flags & OPT_CREATE_NETMASK) {
                unsigned int mask_bits, netmask_bits;
                ip_set_ip_t mask;
-               
+
                if ((mydata->from & mydata->netmask) != mydata->from)
                        exit_error(PARAMETER_PROBLEM,
                                   "%s is not a network address according to netmask %d\n",
@@ -167,26 +158,14 @@ create_final(void *data, unsigned int flags)
                mask = range_to_mask(mydata->from, mydata->to, &mask_bits);
                if (!mask
                    && (mydata->from || mydata->to != 0xFFFFFFFF)) {
-                       strncpy(errstr, ip_tostring_numeric(mydata->from),
-                               ERRSTRLEN-2);
-                       errstr[ERRSTRLEN-1] = '\0';
                        exit_error(PARAMETER_PROBLEM,
-                                  "%s-%s is not a full network (%x)\n",
-                                  errstr,
-                                  ip_tostring_numeric(mydata->to), mask);
+                                  "You have to define a full network with --from"
+                                  " and --to if you specify the --network option\n");
                }
                netmask_bits = mask_to_bits(mydata->netmask);
-               
                if (netmask_bits <= mask_bits) {
-                       strncpy(errstr, ip_tostring_numeric(mydata->from),
-                               ERRSTRLEN-2);
-                       errstr[ERRSTRLEN-1] = '\0';
                        exit_error(PARAMETER_PROBLEM,
-                                  "%d netmask specifies larger or equal netblock than %s-%s (%d)\n",
-                                  netmask_bits,
-                                  errstr,
-                                  ip_tostring_numeric(mydata->to),
-                                  mask_bits);
+                                  "%d netmask specifies larger or equal netblock than the network itself\n");
                }
                range = (1<<(netmask_bits - mask_bits)) - 1;
        } else {
@@ -211,8 +190,7 @@ static const struct option create_opts[] = {
 static ip_set_ip_t
 adt_parser(unsigned cmd, const char *optarg, void *data)
 {
-       struct ip_set_req_ipmap *mydata =
-           (struct ip_set_req_ipmap *) data;
+       struct ip_set_req_ipmap *mydata = data;
 
        DP("ipmap: %p %p", optarg, data);
 
@@ -229,10 +207,8 @@ adt_parser(unsigned cmd, const char *optarg, void *data)
 static void
 initheader(struct set *set, const void *data)
 {
-       struct ip_set_req_ipmap_create *header =
-           (struct ip_set_req_ipmap_create *) data;
-       struct ip_set_ipmap *map =
-               (struct ip_set_ipmap *) set->settype->header;
+       const struct ip_set_req_ipmap_create *header = data;
+       struct ip_set_ipmap *map = set->settype->header;
                
        memset(map, 0, sizeof(struct ip_set_ipmap));
        map->first_ip = header->from;
@@ -260,8 +236,7 @@ initheader(struct set *set, const void *data)
 static void
 printheader(struct set *set, unsigned options)
 {
-       struct ip_set_ipmap *mysetdata =
-           (struct ip_set_ipmap *) set->settype->header;
+       struct ip_set_ipmap *mysetdata = set->settype->header;
 
        printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
        printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
@@ -274,8 +249,7 @@ printheader(struct set *set, unsigned options)
 static void
 printips_sorted(struct set *set, void *data, size_t len, unsigned options)
 {
-       struct ip_set_ipmap *mysetdata =
-           (struct ip_set_ipmap *) set->settype->header;
+       struct ip_set_ipmap *mysetdata = set->settype->header;
        ip_set_ip_t id;
 
        for (id = 0; id < mysetdata->sizeid; id++)
@@ -289,8 +263,7 @@ printips_sorted(struct set *set, void *data, size_t len, unsigned options)
 static void
 saveheader(struct set *set, unsigned options)
 {
-       struct ip_set_ipmap *mysetdata =
-           (struct ip_set_ipmap *) set->settype->header;
+       struct ip_set_ipmap *mysetdata = set->settype->header;
 
        printf("-N %s %s --from %s",
               set->name, set->settype->typename,
@@ -307,8 +280,7 @@ saveheader(struct set *set, unsigned options)
 static void
 saveips(struct set *set, void *data, size_t len, unsigned options)
 {
-       struct ip_set_ipmap *mysetdata =
-           (struct ip_set_ipmap *) set->settype->header;
+       struct ip_set_ipmap *mysetdata = set->settype->header;
        ip_set_ip_t id;
 
        DP("%s", set->name);
index c090744234cf90a35d55cb3f213b8d98e0e30dfe..1b92979699d1cf855d6f988ca313ec07ede07127 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#include <errno.h>
-#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/types.h>
 
 #include <linux/netfilter_ipv4/ip_set_ipporthash.h>
-#include <linux/netfilter_ipv4/ip_set_jhash.h>
 
 #include "ipset.h"
 
@@ -44,8 +35,7 @@
 static void
 create_init(void *data)
 {
-       struct ip_set_req_ipporthash_create *mydata =
-           (struct ip_set_req_ipporthash_create *) data;
+       struct ip_set_req_ipporthash_create *mydata = data;
 
        DP("create INIT");
 
@@ -59,8 +49,7 @@ create_init(void *data)
 static int
 create_parse(int c, char *argv[], void *data, unsigned *flags)
 {
-       struct ip_set_req_ipporthash_create *mydata =
-           (struct ip_set_req_ipporthash_create *) data;
+       struct ip_set_req_ipporthash_create *mydata = data;
        ip_set_ip_t value;
 
        DP("create_parse");
@@ -151,8 +140,7 @@ create_parse(int c, char *argv[], void *data, unsigned *flags)
 static void
 create_final(void *data, unsigned int flags)
 {
-       struct ip_set_req_ipporthash_create *mydata =
-           (struct ip_set_req_ipporthash_create *) data;
+       struct ip_set_req_ipporthash_create *mydata = data;
 
 #ifdef IPSET_DEBUG
        DP("hashsize %u probes %u resize %u",
@@ -204,21 +192,25 @@ static const struct option create_opts[] = {
 static ip_set_ip_t
 adt_parser(unsigned cmd, const char *optarg, void *data)
 {
-       struct ip_set_req_ipporthash *mydata =
-           (struct ip_set_req_ipporthash *) data;
+       struct ip_set_req_ipporthash *mydata = data;
        char *saved = ipset_strdup(optarg);
        char *ptr, *tmp = saved;
 
        DP("ipporthash: %p %p", optarg, data);
 
-       ptr = strsep(&tmp, ":%");
+       if ((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%')))
+               fprintf(stderr, "Warning: please replace old separator character '%s.1' with ','.\n"
+                               "Next release won't support it.\n",
+                       ptr);
+
+       ptr = strsep(&tmp, ":%,");
        parse_ip(ptr, &mydata->ip);
 
        if (tmp)
                parse_port(tmp, &mydata->port);
        else
                exit_error(PARAMETER_PROBLEM,
-                          "IP address and port must be specified: ip%%port");
+                          "IP address and port must be specified: ip,port");
        free(saved);
        return 1;       
 };
@@ -230,10 +222,8 @@ adt_parser(unsigned cmd, const char *optarg, void *data)
 static void
 initheader(struct set *set, const void *data)
 {
-       struct ip_set_req_ipporthash_create *header =
-           (struct ip_set_req_ipporthash_create *) data;
-       struct ip_set_ipporthash *map =
-               (struct ip_set_ipporthash *) set->settype->header;
+       const struct ip_set_req_ipporthash_create *header = data;
+       struct ip_set_ipporthash *map = set->settype->header;
 
        memset(map, 0, sizeof(struct ip_set_ipporthash));
        map->hashsize = header->hashsize;
@@ -246,8 +236,7 @@ initheader(struct set *set, const void *data)
 static void
 printheader(struct set *set, unsigned options)
 {
-       struct ip_set_ipporthash *mysetdata =
-           (struct ip_set_ipporthash *) set->settype->header;
+       struct ip_set_ipporthash *mysetdata = set->settype->header;
 
        printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
        printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
@@ -259,8 +248,7 @@ printheader(struct set *set, unsigned options)
 static void
 printips(struct set *set, void *data, size_t len, unsigned options)
 {
-       struct ip_set_ipporthash *mysetdata =
-           (struct ip_set_ipporthash *) set->settype->header;
+       struct ip_set_ipporthash *mysetdata = set->settype->header;
        size_t offset = 0;
        ip_set_ip_t *ipptr, ip;
        uint16_t port;
@@ -270,7 +258,7 @@ printips(struct set *set, void *data, size_t len, unsigned options)
                if (*ipptr) {
                        ip = (*ipptr>>16) + mysetdata->first_ip;
                        port = (uint16_t) *ipptr;
-                       printf("%s:%s\n", 
+                       printf("%s,%s\n", 
                               ip_tostring(ip, options),
                               port_tostring(port, options));
                }
@@ -281,8 +269,7 @@ printips(struct set *set, void *data, size_t len, unsigned options)
 static void
 saveheader(struct set *set, unsigned options)
 {
-       struct ip_set_ipporthash *mysetdata =
-           (struct ip_set_ipporthash *) set->settype->header;
+       struct ip_set_ipporthash *mysetdata = set->settype->header;
 
        printf("-N %s %s --from %s",
               set->name, set->settype->typename,
@@ -297,8 +284,7 @@ saveheader(struct set *set, unsigned options)
 static void
 saveips(struct set *set, void *data, size_t len, unsigned options)
 {
-       struct ip_set_ipporthash *mysetdata =
-           (struct ip_set_ipporthash *) set->settype->header;
+       struct ip_set_ipporthash *mysetdata = set->settype->header;
        size_t offset = 0;
        ip_set_ip_t *ipptr, ip;
        uint16_t port;
@@ -308,7 +294,7 @@ saveips(struct set *set, void *data, size_t len, unsigned options)
                if (*ipptr) {
                        ip = (*ipptr>>16) + mysetdata->first_ip;
                        port = (uint16_t) *ipptr;
-                       printf("-A %s %s:%s\n", set->name, 
+                       printf("-A %s %s,%s\n", set->name, 
                               ip_tostring(ip, options),
                               port_tostring(port, options));
                }
@@ -321,13 +307,12 @@ static char buffer[22];
 static char *
 unpack_ipport_tostring(struct set *set, ip_set_ip_t bip, unsigned options)
 {
-       struct ip_set_ipporthash *mysetdata =
-           (struct ip_set_ipporthash *) set->settype->header;
+       struct ip_set_ipporthash *mysetdata = set->settype->header;
        ip_set_ip_t ip, port;
        
        ip = (bip>>16) + mysetdata->first_ip;
        port = (uint16_t) bip;
-       sprintf(buffer, "%s:%s", 
+       sprintf(buffer, "%s,%s", 
                ip_tostring(ip, options), port_tostring(port, options));
                
        return buffer;
@@ -340,9 +325,9 @@ static void usage(void)
             "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
             "-N set ipporthash --network IP/mask\n"
             "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
-            "-A set IP:port\n"
-            "-D set IP:port\n"
-            "-T set IP:port\n");
+            "-A set IP,port\n"
+            "-D set IP,port\n"
+            "-T set IP,port\n");
 }
 
 static struct settype settype_ipporthash = {
diff --git a/ipset_ipportiphash.c b/ipset_ipportiphash.c
new file mode 100644 (file)
index 0000000..0bd2e9f
--- /dev/null
@@ -0,0 +1,360 @@
+/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+ *
+ * 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   
+ * the Free Software Foundation; either version 2 of the License, or      
+ * (at your option) any later version.                                    
+ *                                                                         
+ * This program 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 program; if not, write to the Free Software            
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include <linux/netfilter_ipv4/ip_set_ipportiphash.h>
+
+#include "ipset.h"
+
+#define OPT_CREATE_HASHSIZE    0x01U
+#define OPT_CREATE_PROBES      0x02U
+#define OPT_CREATE_RESIZE      0x04U
+#define OPT_CREATE_NETWORK     0x08U
+#define OPT_CREATE_FROM                0x10U
+#define OPT_CREATE_TO          0x20U
+
+/* Initialize the create. */
+static void
+create_init(void *data)
+{
+       struct ip_set_req_ipportiphash_create *mydata = data;
+
+       DP("create INIT");
+
+       /* Default create parameters */ 
+       mydata->hashsize = 1024;
+       mydata->probes = 8;
+       mydata->resize = 50;
+}
+
+/* Function which parses command options; returns true if it ate an option */
+static int
+create_parse(int c, char *argv[], void *data, unsigned *flags)
+{
+       struct ip_set_req_ipportiphash_create *mydata = data;
+       ip_set_ip_t value;
+
+       DP("create_parse");
+
+       switch (c) {
+       case '1':
+
+               if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
+                       exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
+
+               *flags |= OPT_CREATE_HASHSIZE;
+
+               DP("--hashsize %u", mydata->hashsize);
+               
+               break;
+
+       case '2':
+
+               if (string_to_number(optarg, 1, 65535, &value))
+                       exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
+
+               mydata->probes = value;
+               *flags |= OPT_CREATE_PROBES;
+
+               DP("--probes %u", mydata->probes);
+               
+               break;
+
+       case '3':
+
+               if (string_to_number(optarg, 0, 65535, &value))
+                       exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
+
+               mydata->resize = value;
+               *flags |= OPT_CREATE_RESIZE;
+
+               DP("--resize %u", mydata->resize);
+               
+               break;
+
+       case '4':
+               parse_ip(optarg, &mydata->from);
+
+               *flags |= OPT_CREATE_FROM;
+
+               DP("--from %x (%s)", mydata->from,
+                  ip_tostring_numeric(mydata->from));
+
+               break;
+
+       case '5':
+               parse_ip(optarg, &mydata->to);
+
+               *flags |= OPT_CREATE_TO;
+
+               DP("--to %x (%s)", mydata->to,
+                  ip_tostring_numeric(mydata->to));
+
+               break;
+
+       case '6':
+               parse_ipandmask(optarg, &mydata->from, &mydata->to);
+
+               /* Make to the last of from + mask */
+               if (mydata->to)
+                       mydata->to = mydata->from | ~(mydata->to);
+               else {
+                       mydata->from = 0x00000000;
+                       mydata->to = 0xFFFFFFFF;
+               }
+               *flags |= OPT_CREATE_NETWORK;
+
+               DP("--network from %x (%s)", 
+                  mydata->from, ip_tostring_numeric(mydata->from));
+               DP("--network to %x (%s)", 
+                  mydata->to, ip_tostring_numeric(mydata->to));
+
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+/* Final check; exit if not ok. */
+static void
+create_final(void *data, unsigned int flags)
+{
+       struct ip_set_req_ipportiphash_create *mydata = data;
+
+#ifdef IPSET_DEBUG
+       DP("hashsize %u probes %u resize %u",
+          mydata->hashsize, mydata->probes, mydata->resize);
+#endif
+
+       if (flags & OPT_CREATE_NETWORK) {
+               /* --network */
+               if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Can't specify --from or --to with --network\n");
+       } else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
+               /* --from --to */
+               if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Need to specify both --from and --to\n");
+       } else {
+               exit_error(PARAMETER_PROBLEM,
+                          "Need to specify --from and --to, or --network\n");
+
+       }
+
+       DP("from : %x to: %x diff: %x", 
+          mydata->from, mydata->to,
+          mydata->to - mydata->from);
+
+       if (mydata->from > mydata->to)
+               exit_error(PARAMETER_PROBLEM,
+                          "From can't be higher than to.\n");
+
+       if (mydata->to - mydata->from > MAX_RANGE)
+               exit_error(PARAMETER_PROBLEM,
+                          "Range too large. Max is %d IPs in range\n",
+                          MAX_RANGE+1);
+}
+
+/* Create commandline options */
+static const struct option create_opts[] = {
+       {.name = "hashsize",    .has_arg = required_argument,   .val = '1'},
+       {.name = "probes",      .has_arg = required_argument,   .val = '2'},
+       {.name = "resize",      .has_arg = required_argument,   .val = '3'},
+       {.name = "from",        .has_arg = required_argument,   .val = '4'},
+       {.name = "to",          .has_arg = required_argument,   .val = '5'},
+       {.name = "network",     .has_arg = required_argument,   .val = '6'},
+       {NULL},
+};
+
+/* Add, del, test parser */
+static ip_set_ip_t
+adt_parser(unsigned cmd, const char *optarg, void *data)
+{
+       struct ip_set_req_ipportiphash *mydata = data;
+       char *saved = ipset_strdup(optarg);
+       char *ptr, *tmp = saved;
+
+       DP("ipportiphash: %p %p", optarg, data);
+
+       if ((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%')))
+               fprintf(stderr, "Warning: please replace old separator character '%s.1' with ','.\n"
+                               "Next release won't support it.\n",
+                       ptr);
+
+       ptr = strsep(&tmp, ":%,");
+       parse_ip(ptr, &mydata->ip);
+
+       if (!tmp)
+               exit_error(PARAMETER_PROBLEM,
+                          "IP address, port and IP address must be specified: ip,port,ip");
+
+       ptr = strsep(&tmp, ":%,");
+       parse_port(ptr, &mydata->port);
+       if (tmp)
+               parse_ip(tmp, &mydata->ip1);
+       else
+               exit_error(PARAMETER_PROBLEM,
+                          "IP address, port and IP address must be specified: ip,port,ip");
+       free(saved);
+       return 1;       
+};
+
+/*
+ * Print and save
+ */
+
+static void
+initheader(struct set *set, const void *data)
+{
+       const struct ip_set_req_ipportiphash_create *header = data;
+       struct ip_set_ipportiphash *map = set->settype->header;
+
+       memset(map, 0, sizeof(struct ip_set_ipportiphash));
+       map->hashsize = header->hashsize;
+       map->probes = header->probes;
+       map->resize = header->resize;
+       map->first_ip = header->from;
+       map->last_ip = header->to;
+}
+
+static void
+printheader(struct set *set, unsigned options)
+{
+       struct ip_set_ipportiphash *mysetdata = set->settype->header;
+
+       printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
+       printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
+       printf(" hashsize: %u", mysetdata->hashsize);
+       printf(" probes: %u", mysetdata->probes);
+       printf(" resize: %u\n", mysetdata->resize);
+}
+
+static void
+printips(struct set *set, void *data, size_t len, unsigned options)
+{
+       struct ip_set_ipportiphash *mysetdata = set->settype->header;
+       size_t offset = 0;
+       struct ipportip *ipptr;
+       ip_set_ip_t ip;
+       uint16_t port;
+
+       while (offset < len) {
+               ipptr = data + offset;
+               if (ipptr->ip && ipptr->ip1) {
+                       ip = (ipptr->ip>>16) + mysetdata->first_ip;
+                       port = (uint16_t) ipptr->ip;
+                       printf("%s,%s,", 
+                              ip_tostring(ip, options),
+                              port_tostring(port, options));
+                       printf("%s\n", 
+                              ip_tostring(ipptr->ip1, options));
+               }
+               offset += sizeof(struct ipportip);
+       }
+}
+
+static void
+saveheader(struct set *set, unsigned options)
+{
+       struct ip_set_ipportiphash *mysetdata = set->settype->header;
+
+       printf("-N %s %s --from %s",
+              set->name, set->settype->typename,
+              ip_tostring(mysetdata->first_ip, options));
+       printf(" --to %s",
+              ip_tostring(mysetdata->last_ip, options));
+       printf(" --hashsize %u --probes %u --resize %u\n",
+              mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
+}
+
+/* Print save for an IP */
+static void
+saveips(struct set *set, void *data, size_t len, unsigned options)
+{
+       struct ip_set_ipportiphash *mysetdata = set->settype->header;
+       size_t offset = 0;
+       struct ipportip *ipptr;
+       ip_set_ip_t ip;
+       uint16_t port;
+
+       while (offset < len) {
+               ipptr = data + offset;
+               if (ipptr->ip && ipptr->ip1) {
+                       ip = (ipptr->ip>>16) + mysetdata->first_ip;
+                       port = (uint16_t) ipptr->ip;
+                       printf("-A %s %s,%s,", set->name, 
+                              ip_tostring(ip, options),
+                              port_tostring(port, options));
+                       printf("%s\n",
+                              ip_tostring(ipptr->ip1, options));
+               }
+               offset += sizeof(struct ipportip);
+       }
+}
+
+static void usage(void)
+{
+       printf
+           ("-N set ipportiphash --from IP --to IP\n"
+            "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
+            "-N set ipportiphash --network IP/mask\n"
+            "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
+            "-A set IP,port,IP\n"
+            "-D set IP,port,IP\n"
+            "-T set IP,port,IP\n");
+}
+
+static struct settype settype_ipportiphash = {
+       .typename = SETTYPE_NAME,
+       .protocol_version = IP_SET_PROTOCOL_VERSION,
+
+       /* Create */
+       .create_size = sizeof(struct ip_set_req_ipportiphash_create),
+       .create_init = &create_init,
+       .create_parse = &create_parse,
+       .create_final = &create_final,
+       .create_opts = create_opts,
+
+       /* Add/del/test */
+       .adt_size = sizeof(struct ip_set_req_ipportiphash),
+       .adt_parser = &adt_parser,
+
+       /* Printing */
+       .header_size = sizeof(struct ip_set_ipportiphash),
+       .initheader = &initheader,
+       .printheader = &printheader,
+       .printips = &printips,          /* We only have the unsorted version */
+       .printips_sorted = &printips,
+       .saveheader = &saveheader,
+       .saveips = &saveips,
+       
+       .usage = &usage,
+};
+
+void _init(void)
+{
+       settype_register(&settype_ipportiphash);
+
+}
diff --git a/ipset_ipportnethash.c b/ipset_ipportnethash.c
new file mode 100644 (file)
index 0000000..51297ff
--- /dev/null
@@ -0,0 +1,428 @@
+/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+ *
+ * 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   
+ * the Free Software Foundation; either version 2 of the License, or      
+ * (at your option) any later version.                                    
+ *                                                                         
+ * This program 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 program; if not, write to the Free Software            
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include <linux/netfilter_ipv4/ip_set_ipportnethash.h>
+
+#include "ipset.h"
+
+#define OPT_CREATE_HASHSIZE    0x01U
+#define OPT_CREATE_PROBES      0x02U
+#define OPT_CREATE_RESIZE      0x04U
+#define OPT_CREATE_NETWORK     0x08U
+#define OPT_CREATE_FROM                0x10U
+#define OPT_CREATE_TO          0x20U
+
+/* Initialize the create. */
+static void
+create_init(void *data)
+{
+       struct ip_set_req_ipportnethash_create *mydata = data;
+
+       DP("create INIT");
+
+       /* Default create parameters */ 
+       mydata->hashsize = 1024;
+       mydata->probes = 8;
+       mydata->resize = 50;
+}
+
+/* Function which parses command options; returns true if it ate an option */
+static int
+create_parse(int c, char *argv[], void *data, unsigned *flags)
+{
+       struct ip_set_req_ipportnethash_create *mydata = data;
+       ip_set_ip_t value;
+
+       DP("create_parse");
+
+       switch (c) {
+       case '1':
+
+               if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
+                       exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
+
+               *flags |= OPT_CREATE_HASHSIZE;
+
+               DP("--hashsize %u", mydata->hashsize);
+               
+               break;
+
+       case '2':
+
+               if (string_to_number(optarg, 1, 65535, &value))
+                       exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
+
+               mydata->probes = value;
+               *flags |= OPT_CREATE_PROBES;
+
+               DP("--probes %u", mydata->probes);
+               
+               break;
+
+       case '3':
+
+               if (string_to_number(optarg, 0, 65535, &value))
+                       exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
+
+               mydata->resize = value;
+               *flags |= OPT_CREATE_RESIZE;
+
+               DP("--resize %u", mydata->resize);
+               
+               break;
+
+       case '4':
+               parse_ip(optarg, &mydata->from);
+
+               *flags |= OPT_CREATE_FROM;
+
+               DP("--from %x (%s)", mydata->from,
+                  ip_tostring_numeric(mydata->from));
+
+               break;
+
+       case '5':
+               parse_ip(optarg, &mydata->to);
+
+               *flags |= OPT_CREATE_TO;
+
+               DP("--to %x (%s)", mydata->to,
+                  ip_tostring_numeric(mydata->to));
+
+               break;
+
+       case '6':
+               parse_ipandmask(optarg, &mydata->from, &mydata->to);
+
+               /* Make to the last of from + mask */
+               if (mydata->to)
+                       mydata->to = mydata->from | ~(mydata->to);
+               else {
+                       mydata->from = 0x00000000;
+                       mydata->to = 0xFFFFFFFF;
+               }
+               *flags |= OPT_CREATE_NETWORK;
+
+               DP("--network from %x (%s)", 
+                  mydata->from, ip_tostring_numeric(mydata->from));
+               DP("--network to %x (%s)", 
+                  mydata->to, ip_tostring_numeric(mydata->to));
+
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+/* Final check; exit if not ok. */
+static void
+create_final(void *data, unsigned int flags)
+{
+       struct ip_set_req_ipportnethash_create *mydata = data;
+
+#ifdef IPSET_DEBUG
+       DP("hashsize %u probes %u resize %u",
+          mydata->hashsize, mydata->probes, mydata->resize);
+#endif
+
+       if (flags & OPT_CREATE_NETWORK) {
+               /* --network */
+               if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Can't specify --from or --to with --network\n");
+       } else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
+               /* --from --to */
+               if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Need to specify both --from and --to\n");
+       } else {
+               exit_error(PARAMETER_PROBLEM,
+                          "Need to specify --from and --to, or --network\n");
+
+       }
+
+       DP("from : %x to: %x diff: %x", 
+          mydata->from, mydata->to,
+          mydata->to - mydata->from);
+
+       if (mydata->from > mydata->to)
+               exit_error(PARAMETER_PROBLEM,
+                          "From can't be higher than to.\n");
+
+       if (mydata->to - mydata->from > MAX_RANGE)
+               exit_error(PARAMETER_PROBLEM,
+                          "Range too large. Max is %d IPs in range\n",
+                          MAX_RANGE+1);
+}
+
+/* Create commandline options */
+static const struct option create_opts[] = {
+       {.name = "hashsize",    .has_arg = required_argument,   .val = '1'},
+       {.name = "probes",      .has_arg = required_argument,   .val = '2'},
+       {.name = "resize",      .has_arg = required_argument,   .val = '3'},
+       {.name = "from",        .has_arg = required_argument,   .val = '4'},
+       {.name = "to",          .has_arg = required_argument,   .val = '5'},
+       {.name = "network",     .has_arg = required_argument,   .val = '6'},
+       {NULL},
+};
+
+/* Add, del, test parser */
+static ip_set_ip_t
+adt_parser(unsigned cmd, const char *optarg, void *data)
+{
+       struct ip_set_req_ipportnethash *mydata = data;
+       char *saved = ipset_strdup(optarg);
+       char *ptr, *tmp = saved;
+       ip_set_ip_t cidr;
+
+       DP("ipportnethash: %p %p", optarg, data);
+
+       if ((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%')))
+               fprintf(stderr, "Warning: please replace old separator character '%s.1' with ','.\n"
+                               "Next release won't support it.\n",
+                       ptr);
+
+       ptr = strsep(&tmp, ":%,");
+       parse_ip(ptr, &mydata->ip);
+       if (!tmp)
+               exit_error(PARAMETER_PROBLEM,
+                          "IP address, port and network address must be specified: ip,port,net");
+
+       ptr = strsep(&tmp, ":%,");
+       parse_port(ptr, &mydata->port);
+       if (!tmp)
+               exit_error(PARAMETER_PROBLEM,
+                          "IP address, port and network address must be specified: ip,port,net");
+
+       ptr = strsep(&tmp, "/");
+       if (tmp == NULL)
+               if (cmd == CMD_TEST)
+                       cidr = 32;
+               else
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Missing /cidr from `%s'", optarg);
+       else
+               if (string_to_number(tmp, 1, 31, &cidr))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Out of range cidr `%s' specified", optarg);
+       
+       mydata->cidr = cidr;
+
+       parse_ip(ptr, &mydata->ip1);
+       free(saved);
+       return 1;       
+};
+
+/*
+ * Print and save
+ */
+
+static void
+initheader(struct set *set, const void *data)
+{
+       const struct ip_set_req_ipportnethash_create *header = data;
+       struct ip_set_ipportnethash *map = set->settype->header;
+
+       memset(map, 0, sizeof(struct ip_set_ipportnethash));
+       map->hashsize = header->hashsize;
+       map->probes = header->probes;
+       map->resize = header->resize;
+       map->first_ip = header->from;
+       map->last_ip = header->to;
+}
+
+static void
+printheader(struct set *set, unsigned options)
+{
+       struct ip_set_ipportnethash *mysetdata = set->settype->header;
+
+       printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
+       printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
+       printf(" hashsize: %u", mysetdata->hashsize);
+       printf(" probes: %u", mysetdata->probes);
+       printf(" resize: %u\n", mysetdata->resize);
+}
+
+static char buf[20];
+
+static char *
+unpack_ip_tostring(ip_set_ip_t ip, unsigned options)
+{
+       int i, j = 3;
+       unsigned char a, b;
+
+       ip = htonl(ip); 
+       for (i = 3; i >= 0; i--)
+               if (((unsigned char *)&ip)[i] != 0) {
+                       j = i;
+                       break;
+               }
+                       
+       a = ((unsigned char *)&ip)[j];
+       if (a <= 128) {
+               a = (a - 1) * 2;
+               b = 7;
+       } else if (a <= 192) {
+               a = (a - 129) * 4;
+               b = 6;
+       } else if (a <= 224) {
+               a = (a - 193) * 8;
+               b = 5;
+       } else if (a <= 240) {
+               a = (a - 225) * 16;
+               b = 4;
+       } else if (a <= 248) {
+               a = (a - 241) * 32;
+               b = 3;
+       } else if (a <= 252) {
+               a = (a - 249) * 64;
+               b = 2;
+       } else if (a <= 254) {
+               a = (a - 253) * 128;
+               b = 1;
+       } else {
+               a = b = 0;
+       }
+       ((unsigned char *)&ip)[j] = a;
+       b += j * 8;
+       
+       sprintf(buf, "%u.%u.%u.%u/%u",
+               ((unsigned char *)&ip)[0],
+               ((unsigned char *)&ip)[1],
+               ((unsigned char *)&ip)[2],
+               ((unsigned char *)&ip)[3],
+               b);
+
+       DP("%s %s", ip_tostring(ntohl(ip), options), buf);
+       return buf;
+}
+
+static void
+printips(struct set *set, void *data, size_t len, unsigned options)
+{
+       struct ip_set_ipportnethash *mysetdata = set->settype->header;
+       size_t offset = 0;
+       struct ipportip *ipptr;
+       ip_set_ip_t ip;
+       uint16_t port;
+
+       while (offset < len) {
+               ipptr = data + offset;
+               if (ipptr->ip || ipptr->ip1) {
+                       ip = (ipptr->ip>>16) + mysetdata->first_ip;
+                       port = (uint16_t) ipptr->ip;
+                       printf("%s,%s,", 
+                              ip_tostring(ip, options),
+                              port_tostring(port, options));
+                       printf("%s\n", 
+                              unpack_ip_tostring(ipptr->ip1, options));
+               }
+               offset += sizeof(struct ipportip);
+       }
+}
+
+static void
+saveheader(struct set *set, unsigned options)
+{
+       struct ip_set_ipportnethash *mysetdata = set->settype->header;
+
+       printf("-N %s %s --from %s",
+              set->name, set->settype->typename,
+              ip_tostring(mysetdata->first_ip, options));
+       printf(" --to %s",
+              ip_tostring(mysetdata->last_ip, options));
+       printf(" --hashsize %u --probes %u --resize %u\n",
+              mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
+}
+
+/* Print save for an IP */
+static void
+saveips(struct set *set, void *data, size_t len, unsigned options)
+{
+       struct ip_set_ipportnethash *mysetdata = set->settype->header;
+       size_t offset = 0;
+       struct ipportip *ipptr;
+       ip_set_ip_t ip;
+       uint16_t port;
+
+       while (offset < len) {
+               ipptr = data + offset;
+               if (ipptr) {
+                       ip = (ipptr->ip>>16) + mysetdata->first_ip;
+                       port = (uint16_t) ipptr->ip;
+                       printf("-A %s %s,%s,", set->name, 
+                              ip_tostring(ip, options),
+                              port_tostring(port, options));
+                       printf("%s\n",
+                              unpack_ip_tostring(ipptr->ip, options));
+               }
+               offset += sizeof(struct ipportip);
+       }
+}
+
+static void usage(void)
+{
+       printf
+           ("-N set ipportnethash --from IP --to IP\n"
+            "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
+            "-N set ipportnethash --network IP/mask\n"
+            "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
+            "-A set IP,port,IP/net\n"
+            "-D set IP,port,IP/net\n"
+            "-T set IP,port,IP[/net]\n");
+}
+
+static struct settype settype_ipportnethash = {
+       .typename = SETTYPE_NAME,
+       .protocol_version = IP_SET_PROTOCOL_VERSION,
+
+       /* Create */
+       .create_size = sizeof(struct ip_set_req_ipportnethash_create),
+       .create_init = &create_init,
+       .create_parse = &create_parse,
+       .create_final = &create_final,
+       .create_opts = create_opts,
+
+       /* Add/del/test */
+       .adt_size = sizeof(struct ip_set_req_ipportnethash),
+       .adt_parser = &adt_parser,
+
+       /* Printing */
+       .header_size = sizeof(struct ip_set_ipportnethash),
+       .initheader = &initheader,
+       .printheader = &printheader,
+       .printips = &printips,          /* We only have the unsorted version */
+       .printips_sorted = &printips,
+       .saveheader = &saveheader,
+       .saveips = &saveips,
+       
+       .usage = &usage,
+};
+
+void _init(void)
+{
+       settype_register(&settype_ipportnethash);
+
+}
index 379c113c2a7387f69247e89806c022c728719630..0c23c993165875202ff38121901f10cd513390e8 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
 #include <arpa/inet.h>
 
 #include <linux/netfilter_ipv4/ip_set_iptree.h>
@@ -34,8 +31,7 @@
 static void
 create_init(void *data)
 {
-       struct ip_set_req_iptree_create *mydata =
-           (struct ip_set_req_iptree_create *) data;
+       struct ip_set_req_iptree_create *mydata = data;
 
        DP("create INIT");
        mydata->timeout = 0;
@@ -45,8 +41,7 @@ create_init(void *data)
 static int
 create_parse(int c, char *argv[], void *data, unsigned *flags)
 {
-       struct ip_set_req_iptree_create *mydata =
-           (struct ip_set_req_iptree_create *) data;
+       struct ip_set_req_iptree_create *mydata = data;
 
        DP("create_parse");
 
@@ -82,14 +77,18 @@ static const struct option create_opts[] = {
 static ip_set_ip_t
 adt_parser(unsigned cmd, const char *optarg, void *data)
 {
-       struct ip_set_req_iptree *mydata =
-           (struct ip_set_req_iptree *) data;
+       struct ip_set_req_iptree *mydata = data;
        char *saved = ipset_strdup(optarg);
        char *ptr, *tmp = saved;
 
        DP("iptree: %p %p", optarg, data);
 
-       ptr = strsep(&tmp, ":%");
+       if ((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%')))
+               fprintf(stderr, "Warning: please replace old separator character '%s.1' with ','.\n"
+                               "Next release won't support it.\n",
+                       ptr);
+
+       ptr = strsep(&tmp, ":%,");
        parse_ip(ptr, &mydata->ip);
 
        if (tmp)
@@ -108,10 +107,8 @@ adt_parser(unsigned cmd, const char *optarg, void *data)
 static void
 initheader(struct set *set, const void *data)
 {
-       struct ip_set_req_iptree_create *header =
-           (struct ip_set_req_iptree_create *) data;
-       struct ip_set_iptree *map =
-               (struct ip_set_iptree *) set->settype->header;
+       const struct ip_set_req_iptree_create *header = data;
+       struct ip_set_iptree *map = set->settype->header;
                
        map->timeout = header->timeout;
 }
@@ -119,8 +116,7 @@ initheader(struct set *set, const void *data)
 static void
 printheader(struct set *set, unsigned options)
 {
-       struct ip_set_iptree *mysetdata =
-           (struct ip_set_iptree *) set->settype->header;
+       struct ip_set_iptree *mysetdata = set->settype->header;
 
        if (mysetdata->timeout)
                printf(" timeout: %u", mysetdata->timeout);
@@ -130,15 +126,14 @@ printheader(struct set *set, unsigned options)
 static void
 printips_sorted(struct set *set, void *data, size_t len, unsigned options)
 {
-       struct ip_set_iptree *mysetdata =
-           (struct ip_set_iptree *) set->settype->header;
+       struct ip_set_iptree *mysetdata = set->settype->header;
        struct ip_set_req_iptree *req;
        size_t offset = 0;
 
        while (len >= offset + sizeof(struct ip_set_req_iptree)) {
                req = (struct ip_set_req_iptree *)(data + offset);
                if (mysetdata->timeout)
-                       printf("%s:%u\n", ip_tostring(req->ip, options),
+                       printf("%s,%u\n", ip_tostring(req->ip, options),
                                          req->timeout);
                else
                        printf("%s\n", ip_tostring(req->ip, options));
@@ -149,8 +144,7 @@ printips_sorted(struct set *set, void *data, size_t len, unsigned options)
 static void
 saveheader(struct set *set, unsigned options)
 {
-       struct ip_set_iptree *mysetdata =
-           (struct ip_set_iptree *) set->settype->header;
+       struct ip_set_iptree *mysetdata = set->settype->header;
 
        if (mysetdata->timeout)
                printf("-N %s %s --timeout %u\n",
@@ -164,8 +158,7 @@ saveheader(struct set *set, unsigned options)
 static void
 saveips(struct set *set, void *data, size_t len, unsigned options)
 {
-       struct ip_set_iptree *mysetdata =
-           (struct ip_set_iptree *) set->settype->header;
+       struct ip_set_iptree *mysetdata = set->settype->header;
        struct ip_set_req_iptree *req;
        size_t offset = 0;
 
@@ -174,7 +167,7 @@ saveips(struct set *set, void *data, size_t len, unsigned options)
        while (len >= offset + sizeof(struct ip_set_req_iptree)) {
                req = (struct ip_set_req_iptree *)(data + offset);
                if (mysetdata->timeout)
-                       printf("-A %s %s:%u\n",
+                       printf("-A %s %s,%u\n",
                                set->name, 
                                ip_tostring(req->ip, options),
                                req->timeout);
@@ -190,7 +183,7 @@ static void usage(void)
 {
        printf
            ("-N set iptree [--timeout value]\n"
-            "-A set IP[:timeout]\n"
+            "-A set IP[,timeout]\n"
             "-D set IP\n"
             "-T set IP\n");
 }
index 9448339814ecbf38693977686843b6dadf1bbe50..141210f9132956d331013573663d6720e8345a04 100644 (file)
  * Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#include <limits.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
 #include <arpa/inet.h>
 
 #include <linux/netfilter_ipv4/ip_set_iptreemap.h>
@@ -75,19 +73,25 @@ adt_parser(unsigned int cmd, const char *optarg, void *data)
        char *ptr, *tmp = saved;
 
        if (strchr(tmp, '/')) {
-               parse_ipandmask(tmp, &mydata->start, &mask);
-               mydata->end = mydata->start | ~mask;
+               parse_ipandmask(tmp, &mydata->ip, &mask);
+               mydata->end = mydata->ip | ~mask;
        } else {
-               ptr = strsep(&tmp, ":");
-               parse_ip(ptr, &mydata->start);
+               if ((ptr = strchr(tmp, ':')) != NULL)
+                       fprintf(stderr, "Warning: please replace old separator character '%s.1' with ','.\n"
+                               "Next release won't support it.\n",
+                               ptr);
+               ptr = strsep(&tmp, "-:");
+               parse_ip(ptr, &mydata->ip);
 
                if (tmp) {
                        parse_ip(tmp, &mydata->end);
                } else {
-                       mydata->end = mydata->start;
+                       mydata->end = mydata->ip;
                }
        }
 
+       free(saved);
+
        return 1;
 }
 
@@ -120,9 +124,9 @@ printips_sorted(struct set *set, void *data, size_t len, unsigned int options)
        while (len >= offset + sizeof(struct ip_set_req_iptreemap)) {
                req = data + offset;
 
-               printf("%s", ip_tostring(req->start, options));
-               if (req->start != req->end)
-                       printf(":%s", ip_tostring(req->end, options));
+               printf("%s", ip_tostring(req->ip, options));
+               if (req->ip != req->end)
+                       printf("-%s", ip_tostring(req->end, options));
                printf("\n");
 
                offset += sizeof(struct ip_set_req_iptreemap);
@@ -151,10 +155,10 @@ saveips(struct set *set, void *data, size_t len, unsigned int options)
        while (len >= offset + sizeof(struct ip_set_req_iptreemap)) {
                req = data + offset;
 
-               printf("-A %s %s", set->name, ip_tostring(req->start, options));
+               printf("-A %s %s", set->name, ip_tostring(req->ip, options));
 
-               if (req->start != req->end)
-                       printf(":%s", ip_tostring(req->end, options));
+               if (req->ip != req->end)
+                       printf("-%s", ip_tostring(req->end, options));
 
                printf("\n");
 
index a243dc4b934d4b8efbdea4e24e1cb5ec11b9df10..7345f8bb72bd7e62f89c87c9121e6ff2b1ab1239 100644 (file)
@@ -21,8 +21,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
 #include <arpa/inet.h>
 #include <linux/if_ether.h>
 
@@ -51,8 +49,7 @@ create_init(void *data)
 static int
 create_parse(int c, char *argv[], void *data, unsigned *flags)
 {
-       struct ip_set_req_macipmap_create *mydata =
-           (struct ip_set_req_macipmap_create *) data;
+       struct ip_set_req_macipmap_create *mydata = data;
 
        DP("create_parse");
 
@@ -112,8 +109,7 @@ create_parse(int c, char *argv[], void *data, unsigned *flags)
 static void
 create_final(void *data, unsigned int flags)
 {
-       struct ip_set_req_macipmap_create *mydata =
-           (struct ip_set_req_macipmap_create *) data;
+       struct ip_set_req_macipmap_create *mydata = data;
 
        if (flags == 0)
                exit_error(PARAMETER_PROBLEM,
@@ -182,14 +178,18 @@ parse_mac(const char *mac, unsigned char *ethernet)
 static ip_set_ip_t
 adt_parser(unsigned cmd, const char *optarg, void *data)
 {
-       struct ip_set_req_macipmap *mydata =
-           (struct ip_set_req_macipmap *) data;
+       struct ip_set_req_macipmap *mydata = data;
        char *saved = ipset_strdup(optarg);
        char *ptr, *tmp = saved;
 
        DP("macipmap: %p %p", optarg, data);
+       
+       if ((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%')))
+               fprintf(stderr, "Warning: please replace old separator character '%s.1' with ','.\n"
+                               "Next release won't support it.\n",
+                       ptr);
 
-       ptr = strsep(&tmp, ":%");
+       ptr = strsep(&tmp, ":%,");
        parse_ip(ptr, &mydata->ip);
 
        if (tmp)
@@ -208,10 +208,8 @@ adt_parser(unsigned cmd, const char *optarg, void *data)
 static void
 initheader(struct set *set, const void *data)
 {
-       struct ip_set_req_macipmap_create *header =
-           (struct ip_set_req_macipmap_create *) data;
-       struct ip_set_macipmap *map =
-               (struct ip_set_macipmap *) set->settype->header;
+       const struct ip_set_req_macipmap_create *header = data;
+       struct ip_set_macipmap *map = set->settype->header;
 
        memset(map, 0, sizeof(struct ip_set_macipmap));
        map->first_ip = header->from;
@@ -222,8 +220,7 @@ initheader(struct set *set, const void *data)
 static void
 printheader(struct set *set, unsigned options)
 {
-       struct ip_set_macipmap *mysetdata =
-           (struct ip_set_macipmap *) set->settype->header;
+       struct ip_set_macipmap *mysetdata = set->settype->header;
 
        printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
        printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
@@ -246,10 +243,8 @@ print_mac(unsigned char macaddress[ETH_ALEN])
 static void
 printips_sorted(struct set *set, void *data, size_t len, unsigned options)
 {
-       struct ip_set_macipmap *mysetdata =
-           (struct ip_set_macipmap *) set->settype->header;
-       struct ip_set_macip *table =
-           (struct ip_set_macip *) data;
+       struct ip_set_macipmap *mysetdata = set->settype->header;
+       struct ip_set_macip *table = data;
        u_int32_t addr = mysetdata->first_ip;
 
        while (addr <= mysetdata->last_ip) {
@@ -267,8 +262,7 @@ printips_sorted(struct set *set, void *data, size_t len, unsigned options)
 static void
 saveheader(struct set *set, unsigned options)
 {
-       struct ip_set_macipmap *mysetdata =
-           (struct ip_set_macipmap *) set->settype->header;
+       struct ip_set_macipmap *mysetdata = set->settype->header;
 
        printf("-N %s %s --from %s",
               set->name, set->settype->typename,
@@ -283,16 +277,14 @@ saveheader(struct set *set, unsigned options)
 static void
 saveips(struct set *set, void *data, size_t len, unsigned options)
 {
-       struct ip_set_macipmap *mysetdata =
-           (struct ip_set_macipmap *) set->settype->header;
-       struct ip_set_macip *table =
-           (struct ip_set_macip *) data;
+       struct ip_set_macipmap *mysetdata = set->settype->header;
+       struct ip_set_macip *table = data;
        u_int32_t addr = mysetdata->first_ip;
 
        while (addr <= mysetdata->last_ip) {
                if (test_bit(IPSET_MACIP_ISSET,
                             (void *)&table[addr - mysetdata->first_ip].flags)) {
-                       printf("-A %s %s:",
+                       printf("-A %s %s,",
                               set->name, ip_tostring(addr, options));
                        print_mac(table[addr - mysetdata->first_ip].
                                  ethernet);
@@ -307,9 +299,9 @@ static void usage(void)
        printf
            ("-N set macipmap --from IP --to IP [--matchunset]\n"
             "-N set macipmap --network IP/mask [--matchunset]\n"
-            "-A set IP:MAC\n"
-            "-D set IP[:MAC]\n"
-            "-T set IP[:MAC]\n");
+            "-A set IP[,MAC]\n"
+            "-D set IP[,MAC]\n"
+            "-T set IP[,MAC]\n");
 }
 
 static struct settype settype_macipmap = {
index 1e7aa4118230873d04b5251af84f7635e6ccc7a4..d1f3344e9e0a524f0a2c3ac966432da43b111883 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#include <errno.h>
-#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/types.h>
 
 #include <linux/netfilter_ipv4/ip_set_nethash.h>
-#include <linux/netfilter_ipv4/ip_set_jhash.h>
+#include <linux/netfilter_ipv4/ip_set_hashes.h>
 
 #include "ipset.h"
 
@@ -43,8 +35,7 @@
 static void
 create_init(void *data)
 {
-       struct ip_set_req_nethash_create *mydata =
-           (struct ip_set_req_nethash_create *) data;
+       struct ip_set_req_nethash_create *mydata = data;
 
        DP("create INIT");
 
@@ -58,8 +49,7 @@ create_init(void *data)
 static int
 create_parse(int c, char *argv[], void *data, unsigned *flags)
 {
-       struct ip_set_req_nethash_create *mydata =
-           (struct ip_set_req_nethash_create *) data;
+       struct ip_set_req_nethash_create *mydata = data;
        ip_set_ip_t value;
 
        DP("create_parse");
@@ -112,8 +102,7 @@ static void
 create_final(void *data, unsigned int flags)
 {
 #ifdef IPSET_DEBUG
-       struct ip_set_req_nethash_create *mydata =
-           (struct ip_set_req_nethash_create *) data;
+       struct ip_set_req_nethash_create *mydata = data;
 
        DP("hashsize %u probes %u resize %u",
           mydata->hashsize, mydata->probes, mydata->resize);
@@ -132,8 +121,7 @@ static const struct option create_opts[] = {
 static ip_set_ip_t
 adt_parser(unsigned cmd, const char *optarg, void *data)
 {
-       struct ip_set_req_nethash *mydata =
-           (struct ip_set_req_nethash *) data;
+       struct ip_set_req_nethash *mydata = data;
        char *saved = ipset_strdup(optarg);
        char *ptr, *tmp = saved;
        ip_set_ip_t cidr;
@@ -168,10 +156,8 @@ adt_parser(unsigned cmd, const char *optarg, void *data)
 static void
 initheader(struct set *set, const void *data)
 {
-       struct ip_set_req_nethash_create *header =
-           (struct ip_set_req_nethash_create *) data;
-       struct ip_set_nethash *map =
-               (struct ip_set_nethash *) set->settype->header;
+       const struct ip_set_req_nethash_create *header = data;
+       struct ip_set_nethash *map = set->settype->header;
 
        memset(map, 0, sizeof(struct ip_set_nethash));
        map->hashsize = header->hashsize;
@@ -182,8 +168,7 @@ initheader(struct set *set, const void *data)
 static void
 printheader(struct set *set, unsigned options)
 {
-       struct ip_set_nethash *mysetdata =
-           (struct ip_set_nethash *) set->settype->header;
+       struct ip_set_nethash *mysetdata = set->settype->header;
 
        printf(" hashsize: %u", mysetdata->hashsize);
        printf(" probes: %u", mysetdata->probes);
@@ -261,8 +246,7 @@ printips(struct set *set, void *data, size_t len, unsigned options)
 static void
 saveheader(struct set *set, unsigned options)
 {
-       struct ip_set_nethash *mysetdata =
-           (struct ip_set_nethash *) set->settype->header;
+       struct ip_set_nethash *mysetdata = set->settype->header;
 
        printf("-N %s %s --hashsize %u --probes %u --resize %u\n",
               set->name, set->settype->typename,
@@ -311,7 +295,7 @@ parse_net(const char *str, ip_set_ip_t *ip)
        parse_ip(ptr, ip);
        free(saved);
        
-       *ip = pack(*ip, cidr);
+       *ip = pack_ip_cidr(*ip, cidr);
 }
 
 static void usage(void)
index 1237e52c8a406119159d7a40372a98b45142ade7..d13cdb163674b53875e7c7cf2bfd5a0af17399b4 100644 (file)
@@ -18,8 +18,6 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
 #include <arpa/inet.h>
 
 #include <linux/netfilter_ipv4/ip_set_portmap.h>
@@ -45,8 +43,7 @@ create_init(void *data)
 static int
 create_parse(int c, char *argv[], void *data, unsigned *flags)
 {
-       struct ip_set_req_portmap_create *mydata =
-           (struct ip_set_req_portmap_create *) data;
+       struct ip_set_req_portmap_create *mydata = data;
 
        DP("create_parse");
 
@@ -82,8 +79,7 @@ create_parse(int c, char *argv[], void *data, unsigned *flags)
 static void
 create_final(void *data, unsigned int flags)
 {
-       struct ip_set_req_portmap_create *mydata =
-           (struct ip_set_req_portmap_create *) data;
+       struct ip_set_req_portmap_create *mydata = data;
 
        if (flags == 0) {
                exit_error(PARAMETER_PROBLEM,
@@ -120,11 +116,10 @@ static const struct option create_opts[] = {
 static ip_set_ip_t
 adt_parser(unsigned cmd, const char *optarg, void *data)
 {
-       struct ip_set_req_portmap *mydata =
-           (struct ip_set_req_portmap *) data;
+       struct ip_set_req_portmap *mydata = data;
 
-       parse_port(optarg, &mydata->port);
-       DP("%s", port_tostring(mydata->port, 0));
+       parse_port(optarg, &mydata->ip);
+       DP("%s", port_tostring(mydata->ip, 0));
 
        return 1;       
 }
@@ -136,36 +131,32 @@ adt_parser(unsigned cmd, const char *optarg, void *data)
 static void
 initheader(struct set *set, const void *data)
 {
-       struct ip_set_req_portmap_create *header =
-           (struct ip_set_req_portmap_create *) data;
-       struct ip_set_portmap *map =
-               (struct ip_set_portmap *) set->settype->header;
+       const struct ip_set_req_portmap_create *header = data;
+       struct ip_set_portmap *map = set->settype->header;
 
        memset(map, 0, sizeof(struct ip_set_portmap));
-       map->first_port = header->from;
-       map->last_port = header->to;
+       map->first_ip = header->from;
+       map->last_ip = header->to;
 }
 
 static void
 printheader(struct set *set, unsigned options)
 {
-       struct ip_set_portmap *mysetdata =
-           (struct ip_set_portmap *) set->settype->header;
+       struct ip_set_portmap *mysetdata = set->settype->header;
 
-       printf(" from: %s", port_tostring(mysetdata->first_port, options));
-       printf(" to: %s\n", port_tostring(mysetdata->last_port, options));
+       printf(" from: %s", port_tostring(mysetdata->first_ip, options));
+       printf(" to: %s\n", port_tostring(mysetdata->last_ip, options));
 }
 
 static void
 printports_sorted(struct set *set, void *data, size_t len, unsigned options)
 {
-       struct ip_set_portmap *mysetdata =
-           (struct ip_set_portmap *) set->settype->header;
-       u_int32_t addr = mysetdata->first_port;
+       struct ip_set_portmap *mysetdata = set->settype->header;
+       u_int32_t addr = mysetdata->first_ip;
 
-       DP("%u -- %u", mysetdata->first_port, mysetdata->last_port);
-       while (addr <= mysetdata->last_port) {
-               if (test_bit(addr - mysetdata->first_port, data))
+       DP("%u -- %u", mysetdata->first_ip, mysetdata->last_ip);
+       while (addr <= mysetdata->last_ip) {
+               if (test_bit(addr - mysetdata->first_ip, data))
                        printf("%s\n", port_tostring(addr, options));
                addr++;
        }
@@ -180,26 +171,24 @@ binding_port_tostring(struct set *set, ip_set_ip_t ip, unsigned options)
 static void
 saveheader(struct set *set, unsigned options)
 {
-       struct ip_set_portmap *mysetdata =
-           (struct ip_set_portmap *) set->settype->header;
+       struct ip_set_portmap *mysetdata = set->settype->header;
 
        printf("-N %s %s --from %s", 
               set->name,
               set->settype->typename,
-              port_tostring(mysetdata->first_port, options));
+              port_tostring(mysetdata->first_ip, options));
        printf(" --to %s\n", 
-              port_tostring(mysetdata->last_port, options));
+              port_tostring(mysetdata->last_ip, options));
 }
 
 static void
 saveports(struct set *set, void *data, size_t len, unsigned options)
 {
-       struct ip_set_portmap *mysetdata =
-           (struct ip_set_portmap *) set->settype->header;
-       u_int32_t addr = mysetdata->first_port;
+       struct ip_set_portmap *mysetdata = set->settype->header;
+       u_int32_t addr = mysetdata->first_ip;
 
-       while (addr <= mysetdata->last_port) {
-               if (test_bit(addr - mysetdata->first_port, data))
+       while (addr <= mysetdata->last_ip) {
+               if (test_bit(addr - mysetdata->first_ip, data))
                        printf("-A %s %s\n",
                               set->name,
                               port_tostring(addr, options));
diff --git a/ipset_setlist.c b/ipset_setlist.c
new file mode 100644 (file)
index 0000000..b82cd6c
--- /dev/null
@@ -0,0 +1,219 @@
+/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+ *
+ * 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   
+ * the Free Software Foundation; either version 2 of the License, or      
+ * (at your option) any later version.                                    
+ *                                                                         
+ * This program 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 program; if not, write to the Free Software            
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <linux/netfilter_ipv4/ip_set_setlist.h>
+#include "ipset.h"
+
+/* Initialize the create. */
+static void
+create_init(void *data)
+{
+       struct ip_set_req_setlist_create *mydata = data;
+       
+       mydata->size = 8;
+}
+
+/* Function which parses command options; returns true if it ate an option */
+static int
+create_parse(int c, char *argv[], void *data, unsigned *flags)
+{
+       struct ip_set_req_setlist_create *mydata = data;
+       unsigned int size;
+       
+       switch (c) {
+       case '1':
+               if (string_to_number(optarg, 1, 255, &size))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Invalid size '%s specified: must be "
+                                  "between 1-255", optarg);
+               mydata->size = size;
+               break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+/* Final check; exit if not ok. */
+static void
+create_final(void *data, unsigned int flags)
+{
+}
+
+/* Create commandline options */
+static const struct option create_opts[] = {
+       {.name = "size",        .has_arg = required_argument,   .val = '1'},
+       {NULL},
+};
+
+static void check_setname(const char *name)
+{
+       if (strlen(name) > IP_SET_MAXNAMELEN - 1)
+               exit_error(PARAMETER_PROBLEM,
+                       "Setname %s is longer than %d characters.",
+                       name, IP_SET_MAXNAMELEN - 1);
+}
+
+/* Add, del, test parser */
+static ip_set_ip_t
+adt_parser(unsigned cmd, const char *optarg, void *data)
+{
+       struct ip_set_req_setlist *mydata = data;
+       char *saved = ipset_strdup(optarg);
+       char *ptr, *tmp = saved;
+       
+       DP("setlist: %p %p", optarg, data);
+
+       ptr = strsep(&tmp, ",");
+       check_setname(ptr);
+       strcpy(mydata->name, ptr);
+       
+       if (!tmp) {
+               mydata->before = 0;
+               mydata->ref[0] = '\0';
+               return 1;
+       }
+       
+       ptr = strsep(&tmp, ",");
+       
+       if (tmp == NULL || !(strcmp(ptr, "before") == 0 || strcmp(ptr, "after") == 0))
+               exit_error(PARAMETER_PROBLEM,
+                       "Syntax error, you must specify elements as setname,[before|after],setname");
+
+       check_setname(tmp);
+       strcpy(mydata->ref, tmp);
+       mydata->before = !strcmp(ptr, "before");
+
+       free(saved);
+
+       return 1;       
+}
+
+/*
+ * Print and save
+ */
+
+static void
+initheader(struct set *set, const void *data)
+{
+       const struct ip_set_req_setlist_create *header = data;
+       struct ip_set_setlist *map = set->settype->header;
+               
+       memset(map, 0, sizeof(struct ip_set_setlist));
+       map->size = header->size;
+}
+
+static void
+printheader(struct set *set, unsigned options)
+{
+       struct ip_set_setlist *mysetdata = set->settype->header;
+
+       printf(" size: %u\n", mysetdata->size);
+}
+
+static void
+printips_sorted(struct set *set, void *data, size_t len, unsigned options)
+{
+       struct ip_set_setlist *mysetdata = set->settype->header;
+       int i;
+       ip_set_id_t id;
+       struct set *elem;
+
+       for (i = 0; i < mysetdata->size; i++ ) {
+               id = *((ip_set_id_t *)data + i);
+               if (id == IP_SET_INVALID_ID)
+                       return;
+               elem = set_find_byid(id);
+               printf("%s\n", elem->name);
+       }
+}
+
+static void
+saveheader(struct set *set, unsigned options)
+{
+       struct ip_set_setlist *mysetdata = set->settype->header;
+
+       printf("-N %s %s --size %u\n",
+              set->name, set->settype->typename,
+              mysetdata->size);
+}
+
+static void
+saveips(struct set *set, void *data, size_t len, unsigned options)
+{
+       struct ip_set_setlist *mysetdata = set->settype->header;
+       int i;
+       ip_set_id_t id;
+       struct set *elem;
+
+       for (i = 0; i < mysetdata->size; i++ ) {
+               id = *((ip_set_id_t *)data + i);
+               if (id == IP_SET_INVALID_ID)
+                       return;
+               elem = set_find_byid(id);
+               printf("-A %s %s\n", set->name, elem->name);
+       }
+}
+
+static void usage(void)
+{
+       printf
+           ("-N set setlist --size size\n"
+            "-A set setname[,before|after,setname]\n"
+            "-D set setname\n"
+            "-T set setname\n");
+}
+
+static struct settype settype_setlist = {
+       .typename = SETTYPE_NAME,
+       .protocol_version = IP_SET_PROTOCOL_VERSION,
+
+       /* Create */
+       .create_size = sizeof(struct ip_set_req_setlist_create),
+       .create_init = &create_init,
+       .create_parse = &create_parse,
+       .create_final = &create_final,
+       .create_opts = create_opts,
+
+       /* Add/del/test */
+       .adt_size = sizeof(struct ip_set_req_setlist),
+       .adt_parser = &adt_parser,
+
+       /* Printing */
+       .header_size = sizeof(struct ip_set_setlist),
+       .initheader = &initheader,
+       .printheader = &printheader,
+       .printips = &printips_sorted,   /* We only have sorted version */
+       .printips_sorted = &printips_sorted,
+       .saveheader = &saveheader,
+       .saveips = &saveips,
+       
+       .usage = &usage,
+};
+
+void _init(void)
+{
+       settype_register(&settype_setlist);
+
+}
index c0207139feea0bf85a131ebd05c2a05e737be59c..d034b34d74bce9bb26a28ee01d23aba4bf45a342 100644 (file)
@@ -1,4 +1,13 @@
-Tue, 02 Sep 2008
-       - ChangeLog forked for kernel part
-       - Compatibility fix for kernels >= 2.6.27:
-         semaphore.h was moved from asm/ to linux/ (James King)
+2.4
+  - ipportiphash, ipportnethash and setlist types added
+  - set type modules reworked to avoid code duplication
+    as much as possible, code unification macros 
+  - expand_macros Makefile target added to help debugging
+    code unification macros
+  - ip_set_addip_kernel and ip_set_delip_kernel
+    changed from void to int, __ip_set_get_byname and
+    __ip_set_put_byid added for the sake of setlist type
+  - unnecessary includes removed
+  - compatibility fix for kernels >= 2.6.27:
+    semaphore.h was moved from asm/ to linux/ (James King)
+  - ChangeLog forked for kernel part
index 0758f0aae23c01c265355dfbb7235ffb30c56db3..0f442e7d92332c7091824c76e7ee4441edb035ef 100644 (file)
@@ -10,6 +10,9 @@
     dep_tristate '    iphash set type support' CONFIG_IP_NF_SET_IPHASH $CONFIG_IP_NF_SET
     dep_tristate '    nethash set type support' CONFIG_IP_NF_SET_NETHASH $CONFIG_IP_NF_SET
     dep_tristate '    ipporthash set type support' CONFIG_IP_NF_SET_IPPORTHASH $CONFIG_IP_NF_SET
+    dep_tristate '    ipportiphash set type support' CONFIG_IP_NF_SET_IPPORTIPHASH $CONFIG_IP_NF_SET
+    dep_tristate '    ipportnethash set type support' CONFIG_IP_NF_SET_IPPORTNETHASH $CONFIG_IP_NF_SET
     dep_tristate '    iptree set type support' CONFIG_IP_NF_SET_IPTREE $CONFIG_IP_NF_SET
     dep_tristate '    iptreemap set type support' CONFIG_IP_NF_SET_IPTREEMAP $CONFIG_IP_NF_SET
+    dep_tristate '    setlist set type support' CONFIG_IP_NF_SET_SETLIST $CONFIG_IP_NF_SET
   fi
index c7cb727e9b2bbe95c818c157942b57354a70bd27..9757a4a21f6c902fde22f070d1d498427fb6f54c 100644 (file)
@@ -4,9 +4,11 @@ EXTRA_CFLAGS := -I$(M)/include \
 
 obj-m += ip_set.o ipt_set.o ipt_SET.o
 obj-m += ip_set_ipmap.o ip_set_macipmap.o ip_set_portmap.o
-obj-m += ip_set_iphash.o ip_set_ipporthash.o ip_set_nethash.o
+obj-m += ip_set_iphash.o ip_set_nethash.o ip_set_ipporthash.o
+obj-m += ip_set_ipportiphash.o ip_set_ipportnethash.o
 obj-m += ip_set_iptree.o ip_set_iptreemap.o
+obj-m += ip_set_setlist.o
 
 # It's for me...
 incdirs := $(M) $(M)/include/linux/netfilter_ipv4
-clean-files := $(foreach dir,$(incdirs),$(wildcard $(dir)/*~))
+clean-files := $(foreach dir,$(incdirs),$(wildcard $(dir)/*~)) *.m.c
index 2c6022ae3cc2d611df36c8271cabe625a73ec2d3..8b27517fae5a8aad7f9fe5aaef17d3bf66cee3bc 100644 (file)
@@ -79,6 +79,22 @@ config IP_NF_SET_IPPORTHASH
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_SET_IPPORTIPHASH
+       tristate "ipportiphash set support"
+       depends on IP_NF_SET
+       help
+         This option adds the ipportiphash set type support.
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_NF_SET_IPPORTNETHASH
+       tristate "ipportnethash set support"
+       depends on IP_NF_SET
+       help
+         This option adds the ipportnethash set type support.
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_NF_SET_IPTREE
        tristate "iptree set support"
        depends on IP_NF_SET
@@ -95,6 +111,14 @@ config IP_NF_SET_IPTREEMAP
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_SET_SETLIST
+       tristate "setlist set support"
+       depends on IP_NF_SET
+       help
+         This option adds the setlist set type support.
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_NF_MATCH_SET
        tristate "set match support"
        depends on IP_NF_SET
index 60e53621b500fbd7051712a13c0bc2dd6ea4f8c2..9ec91f6f235c75a75545d689c920fce583b6d249 100644 (file)
@@ -4,4 +4,13 @@ else
 KERNELDIR := /lib/modules/`uname -r`/build
 all::
        $(MAKE) -C $KERNELDIR M=`pwd` $@
+
+expand_macros: $(patsubst %.c, %.m.c, $(filter-out %.mod.c %.m.c, $(wildcard ip_set_*.c)))
+
+%.m.c: %.c
+       ./expand_macros.pl < $< > $@
+
+clean:
+       rm -rf *.m.c
+
 endif
index bb3c1315599515365ed3fafac9837a0c483d82d4..fe42cc1020bf67c87217ae447103844cec18e302 100644 (file)
@@ -6,8 +6,11 @@ obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o
 obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o
 obj-$(CONFIG_IP_NF_SET_NETHASH) += ip_set_nethash.o
 obj-$(CONFIG_IP_NF_SET_IPPORTHASH) += ip_set_ipporthash.o
+obj-$(CONFIG_IP_NF_SET_IPPORTIPHASH) += ip_set_ipportiphash.o
+obj-$(CONFIG_IP_NF_SET_IPPORTNETHASH) += ip_set_ipportnethash.o
 obj-$(CONFIG_IP_NF_SET_IPTREE) += ip_set_iptree.o
 obj-$(CONFIG_IP_NF_SET_IPTREEMAP) += ip_set_iptreemap.o
+obj-$(CONFIG_IP_NF_SET_SETLIST) += ip_set_setlist.o
 
 # match and target
 obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set.o
diff --git a/kernel/expand_macros.pl b/kernel/expand_macros.pl
new file mode 100755 (executable)
index 0000000..ea0f4b6
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+my $expand = 0;
+
+while (<STDIN>) {
+  if ($expand) {
+    print C;
+  } elsif (m,include \<(linux/netfilter_ipv4/ip_set\.h)\>,) {
+      $expand = 1;
+      open(C, "|gcc -D__KERNEL__ -Iinclude -E - 2>/dev/null| indent -kr -i8") || die "Can't run gcc: $!\n";
+      print C;
+  } else {
+    print;
+  }
+}
+close C;
\ No newline at end of file
index b8c72024e2085c35f674b4e20168669664c351be..c29a46039dc737ddc2cb7c7d96076a334bdd0f49 100644 (file)
@@ -87,6 +87,9 @@ typedef uint16_t ip_set_id_t;
 #define IPSET_TYPE_PORT                0x02    /* Port type of set */
 #define IPSET_DATA_SINGLE      0x04    /* Single data storage */
 #define IPSET_DATA_DOUBLE      0x08    /* Double data storage */
+#define IPSET_DATA_TRIPLE      0x10    /* Triple data storage */
+#define IPSET_TYPE_IP1         0x20    /* IP address type of set */
+#define IPSET_TYPE_SETNAME     0x40    /* setname type of set */
 
 /* Reserved keywords */
 #define IPSET_TOKEN_DEFAULT    ":default:"
@@ -296,8 +299,12 @@ static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b)
        return 4 * ((((b - a + 8) / 8) + 3) / 4);
 }
 
+/* General limit for the elements in a set */
+#define MAX_RANGE 0x0000FFFF
+
 #ifdef __KERNEL__
 #include <linux/netfilter_ipv4/ip_set_compat.h>
+#include <linux/netfilter_ipv4/ip_set_malloc.h>
 
 #define ip_set_printk(format, args...)                         \
        do {                                                    \
@@ -482,18 +489,85 @@ struct ip_set_hash {
 extern ip_set_id_t ip_set_get_byname(const char name[IP_SET_MAXNAMELEN]);
 extern ip_set_id_t ip_set_get_byindex(ip_set_id_t id);
 extern void ip_set_put(ip_set_id_t id);
+extern ip_set_id_t __ip_set_get_byname(const char name[IP_SET_MAXNAMELEN],
+                                      struct ip_set **set);
+extern void __ip_set_put_byid(ip_set_id_t id);
 
 /* API for iptables set match, and SET target */
-extern void ip_set_addip_kernel(ip_set_id_t id,
-                               const struct sk_buff *skb,
-                               const u_int32_t *flags);
-extern void ip_set_delip_kernel(ip_set_id_t id,
-                               const struct sk_buff *skb,
-                               const u_int32_t *flags);
+extern int ip_set_addip_kernel(ip_set_id_t id,
+                              const struct sk_buff *skb,
+                              const u_int32_t *flags);
+extern int ip_set_delip_kernel(ip_set_id_t id,
+                              const struct sk_buff *skb,
+                              const u_int32_t *flags);
 extern int ip_set_testip_kernel(ip_set_id_t id,
                                const struct sk_buff *skb,
                                const u_int32_t *flags);
 
+/* Macros to generate functions */
+
+#define STRUCT(pre, type)      CONCAT2(pre, type)
+#define CONCAT2(pre, type)     struct pre##type
+
+#define FNAME(pre, mid, post)  CONCAT3(pre, mid, post)
+#define CONCAT3(pre, mid, post)        pre##mid##post
+
+#define UADT0(type, adt, args...)                                      \
+static int                                                             \
+FNAME(type,_u,adt)(struct ip_set *set, const void *data, size_t size,  \
+            ip_set_ip_t *hash_ip)                                      \
+{                                                                      \
+       const STRUCT(ip_set_req_,type) *req = data;                     \
+                                                                       \
+       return FNAME(type,_,adt)(set, hash_ip , ## args);               \
+}
+
+#define UADT(type, adt, args...)                                       \
+       UADT0(type, adt, req->ip , ## args)
+
+#define KADT(type, adt, getfn, args...)                                        \
+static int                                                             \
+FNAME(type,_k,adt)(struct ip_set *set,                                 \
+            const struct sk_buff *skb,                                 \
+            ip_set_ip_t *hash_ip,                                      \
+            const u_int32_t *flags,                                    \
+            unsigned char index)                                       \
+{                                                                      \
+       ip_set_ip_t ip = getfn(skb, flags[index]);                      \
+                                                                       \
+       KADT_CONDITION                                                  \
+       return FNAME(type,_,adt)(set, hash_ip, ip , ##args);            \
+}
+
+#define REGISTER_MODULE(type)                                          \
+static int __init ip_set_##type##_init(void)                           \
+{                                                                      \
+       init_max_page_size();                                           \
+       return ip_set_register_set_type(&ip_set_##type);                \
+}                                                                      \
+                                                                       \
+static void __exit ip_set_##type##_fini(void)                          \
+{                                                                      \
+       /* FIXME: possible race with ip_set_create() */                 \
+       ip_set_unregister_set_type(&ip_set_##type);                     \
+}                                                                      \
+                                                                       \
+module_init(ip_set_##type##_init);                                     \
+module_exit(ip_set_##type##_fini);
+
+/* Common functions */
+
+static inline ip_set_ip_t
+ipaddr(const struct sk_buff *skb, u_int32_t flag)
+{
+       return ntohl(flag & IPSET_SRC ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr);
+}
+
+#define jhash_ip(map, i, ip)   jhash_1word(ip, *(map->initval + i))
+
+#define pack_ip_port(map, ip, port) \
+       (port + ((ip - ((map)->first_ip)) << 16))
+
 #endif                         /* __KERNEL__ */
 
 #endif /*_IP_SET_H*/
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_bitmaps.h b/kernel/include/linux/netfilter_ipv4/ip_set_bitmaps.h
new file mode 100644 (file)
index 0000000..916cb80
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef __IP_SET_BITMAPS_H
+#define __IP_SET_BITMAPS_H
+
+/* Macros to generate functions */
+
+#define BITMAP_CREATE(type)                                            \
+static int                                                             \
+type##_create(struct ip_set *set, const void *data, size_t size)       \
+{                                                                      \
+       int newbytes;                                                   \
+       const struct ip_set_req_##type##_create *req = data;            \
+       struct ip_set_##type *map;                                      \
+                                                                       \
+       if (req->from > req->to) {                                      \
+               DP("bad range");                                        \
+               return -ENOEXEC;                                        \
+       }                                                               \
+                                                                       \
+       map = kmalloc(sizeof(struct ip_set_##type), GFP_KERNEL);        \
+       if (!map) {                                                     \
+               DP("out of memory for %d bytes",                        \
+                  sizeof(struct ip_set_#type));                        \
+               return -ENOMEM;                                         \
+       }                                                               \
+       map->first_ip = req->from;                                      \
+       map->last_ip = req->to;                                         \
+                                                                       \
+       newbytes = __##type##_create(req, map);                         \
+       if (newbytes < 0) {                                             \
+               kfree(map);                                             \
+               return newbytes;                                        \
+       }                                                               \
+                                                                       \
+       map->size = newbytes;                                           \
+       map->members = ip_set_malloc(newbytes);                         \
+       if (!map->members) {                                            \
+               DP("out of memory for %d bytes", newbytes);             \
+               kfree(map);                                             \
+               return -ENOMEM;                                         \
+       }                                                               \
+       memset(map->members, 0, newbytes);                              \
+                                                                       \
+       set->data = map;                                                \
+       return 0;                                                       \
+}
+
+#define BITMAP_DESTROY(type)                                           \
+static void                                                            \
+type##_destroy(struct ip_set *set)                                     \
+{                                                                      \
+       struct ip_set_##type *map = set->data;                          \
+                                                                       \
+       ip_set_free(map->members, map->size);                           \
+       kfree(map);                                                     \
+                                                                       \
+       set->data = NULL;                                               \
+}
+
+#define BITMAP_FLUSH(type)                                             \
+static void                                                            \
+type##_flush(struct ip_set *set)                                       \
+{                                                                      \
+       struct ip_set_##type *map = set->data;                          \
+       memset(map->members, 0, map->size);                             \
+}
+
+#define BITMAP_LIST_HEADER(type)                                       \
+static void                                                            \
+type##_list_header(const struct ip_set *set, void *data)               \
+{                                                                      \
+       const struct ip_set_##type *map = set->data;                    \
+       struct ip_set_req_##type##_create *header = data;               \
+                                                                       \
+       header->from = map->first_ip;                                   \
+       header->to = map->last_ip;                                      \
+       __##type##_list_header(map, header);                            \
+}
+
+#define BITMAP_LIST_MEMBERS_SIZE(type)                                 \
+static int                                                             \
+type##_list_members_size(const struct ip_set *set)                     \
+{                                                                      \
+       const struct ip_set_##type *map = set->data;                    \
+                                                                       \
+       return map->size;                                               \
+}
+
+#define BITMAP_LIST_MEMBERS(type)                                      \
+static void                                                            \
+type##_list_members(const struct ip_set *set, void *data)              \
+{                                                                      \
+       const struct ip_set_##type *map = set->data;                    \
+                                                                       \
+       memcpy(data, map->members, map->size);                          \
+}
+
+#define IP_SET_TYPE(type, __features)                                  \
+struct ip_set_type ip_set_##type = {                                   \
+       .typename               = #type,                                \
+       .features               = __features,                           \
+       .protocol_version       = IP_SET_PROTOCOL_VERSION,              \
+       .create                 = &type##_create,                       \
+       .destroy                = &type##_destroy,                      \
+       .flush                  = &type##_flush,                        \
+       .reqsize                = sizeof(struct ip_set_req_##type),     \
+       .addip                  = &type##_uadd,                         \
+       .addip_kernel           = &type##_kadd,                         \
+       .delip                  = &type##_udel,                         \
+       .delip_kernel           = &type##_kdel,                         \
+       .testip                 = &type##_utest,                        \
+       .testip_kernel          = &type##_ktest,                        \
+       .header_size            = sizeof(struct ip_set_req_##type##_create),\
+       .list_header            = &type##_list_header,                  \
+       .list_members_size      = &type##_list_members_size,            \
+       .list_members           = &type##_list_members,                 \
+       .me                     = THIS_MODULE,                          \
+};
+
+#endif /* __IP_SET_BITMAPS_H */
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_getport.h b/kernel/include/linux/netfilter_ipv4/ip_set_getport.h
new file mode 100644 (file)
index 0000000..9e322bf
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef _IP_SET_GETPORT_H
+#define _IP_SET_GETPORT_H
+
+#ifdef __KERNEL__
+
+#define INVALID_PORT   (MAX_RANGE + 1)
+
+/* We must handle non-linear skbs */
+static inline ip_set_ip_t
+get_port(const struct sk_buff *skb, u_int32_t flags)
+{
+       struct iphdr *iph = ip_hdr(skb);
+       u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
+       switch (iph->protocol) {
+       case IPPROTO_TCP: {
+               struct tcphdr tcph;
+               
+               /* See comments at tcp_match in ip_tables.c */
+               if (offset)
+                       return INVALID_PORT;
+
+               if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
+                       /* No choice either */
+                       return INVALID_PORT;
+               
+               return ntohs(flags & IPSET_SRC ?
+                            tcph.source : tcph.dest);
+           }
+       case IPPROTO_UDP: {
+               struct udphdr udph;
+
+               if (offset)
+                       return INVALID_PORT;
+
+               if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
+                       /* No choice either */
+                       return INVALID_PORT;
+               
+               return ntohs(flags & IPSET_SRC ?
+                            udph.source : udph.dest);
+           }
+       default:
+               return INVALID_PORT;
+       }
+}
+#endif                         /* __KERNEL__ */
+
+#endif /*_IP_SET_GETPORT_H*/
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_hashes.h b/kernel/include/linux/netfilter_ipv4/ip_set_hashes.h
new file mode 100644 (file)
index 0000000..405784a
--- /dev/null
@@ -0,0 +1,300 @@
+#ifndef __IP_SET_HASHES_H
+#define __IP_SET_HASHES_H
+
+/* Macros to generate functions */
+
+#ifdef __KERNEL__
+#define HASH_RETRY0(type, dtype, cond)                                 \
+static int                                                             \
+type##_retry(struct ip_set *set)                                       \
+{                                                                      \
+       struct ip_set_##type *map = set->data, *tmp;                    \
+       dtype *elem;                                                    \
+       void *members;                                                  \
+       u_int32_t i, hashsize = map->hashsize;                          \
+       int res;                                                        \
+                                                                       \
+       if (map->resize == 0)                                           \
+               return -ERANGE;                                         \
+                                                                       \
+    again:                                                             \
+       res = 0;                                                        \
+                                                                       \
+       /* Calculate new hash size */                                   \
+       hashsize += (hashsize * map->resize)/100;                       \
+       if (hashsize == map->hashsize)                                  \
+               hashsize++;                                             \
+                                                                       \
+       ip_set_printk("rehashing of set %s triggered: "                 \
+                     "hashsize grows from %u to %u",                   \
+                     set->name, map->hashsize, hashsize);              \
+                                                                       \
+       tmp = kmalloc(sizeof(struct ip_set_##type)                      \
+                     + map->probes * sizeof(uint32_t), GFP_ATOMIC);    \
+       if (!tmp) {                                                     \
+               DP("out of memory for %d bytes",                        \
+                  sizeof(struct ip_set_##type)                         \
+                  + map->probes * sizeof(uint32_t));                   \
+               return -ENOMEM;                                         \
+       }                                                               \
+       tmp->members = harray_malloc(hashsize, sizeof(dtype), GFP_ATOMIC);\
+       if (!tmp->members) {                                            \
+               DP("out of memory for %d bytes", hashsize * sizeof(dtype));\
+               kfree(tmp);                                             \
+               return -ENOMEM;                                         \
+       }                                                               \
+       tmp->hashsize = hashsize;                                       \
+       tmp->elements = 0;                                              \
+       tmp->probes = map->probes;                                      \
+       tmp->resize = map->resize;                                      \
+       memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));\
+       __##type##_retry(tmp, map);                                     \
+                                                                       \
+       write_lock_bh(&set->lock);                                      \
+       map = set->data; /* Play safe */                                \
+       for (i = 0; i < map->hashsize && res == 0; i++) {               \
+               elem = HARRAY_ELEM(map->members, dtype *, i);           \
+               if (cond)                                               \
+                       res = __##type##_add(tmp, elem);                \
+       }                                                               \
+       if (res) {                                                      \
+               /* Failure, try again */                                \
+               write_unlock_bh(&set->lock);                            \
+               harray_free(tmp->members);                              \
+               kfree(tmp);                                             \
+               goto again;                                             \
+       }                                                               \
+                                                                       \
+       /* Success at resizing! */                                      \
+       members = map->members;                                         \
+                                                                       \
+       map->hashsize = tmp->hashsize;                                  \
+       map->members = tmp->members;                                    \
+       write_unlock_bh(&set->lock);                                    \
+                                                                       \
+       harray_free(members);                                           \
+       kfree(tmp);                                                     \
+                                                                       \
+       return 0;                                                       \
+}
+
+#define HASH_RETRY(type, dtype)                                                \
+       HASH_RETRY0(type, dtype, *elem)
+
+#define HASH_RETRY2(type, dtype)                                               \
+       HASH_RETRY0(type, dtype, elem->ip || elem->ip1)
+
+#define HASH_CREATE(type, dtype)                                       \
+static int                                                             \
+type##_create(struct ip_set *set, const void *data, size_t size)       \
+{                                                                      \
+       const struct ip_set_req_##type##_create *req = data;            \
+       struct ip_set_##type *map;                                      \
+       uint16_t i;                                                     \
+                                                                       \
+       if (req->hashsize < 1) {                                        \
+               ip_set_printk("hashsize too small");                    \
+               return -ENOEXEC;                                        \
+       }                                                               \
+                                                                       \
+       if (req->probes < 1) {                                          \
+               ip_set_printk("probes too small");                      \
+               return -ENOEXEC;                                        \
+       }                                                               \
+                                                                       \
+       map = kmalloc(sizeof(struct ip_set_##type)                      \
+                     + req->probes * sizeof(uint32_t), GFP_KERNEL);    \
+       if (!map) {                                                     \
+               DP("out of memory for %d bytes",                        \
+                  sizeof(struct ip_set_##type)                         \
+                  + req->probes * sizeof(uint32_t));                   \
+               return -ENOMEM;                                         \
+       }                                                               \
+       for (i = 0; i < req->probes; i++)                               \
+               get_random_bytes(((uint32_t *) map->initval)+i, 4);     \
+       map->elements = 0;                                              \
+       map->hashsize = req->hashsize;                                  \
+       map->probes = req->probes;                                      \
+       map->resize = req->resize;                                      \
+       if (__##type##_create(req, map)) {                              \
+               kfree(map);                                             \
+               return -ENOEXEC;                                        \
+       }                                                               \
+       map->members = harray_malloc(map->hashsize, sizeof(dtype), GFP_KERNEL);\
+       if (!map->members) {                                            \
+               DP("out of memory for %d bytes", map->hashsize * sizeof(dtype));\
+               kfree(map);                                             \
+               return -ENOMEM;                                         \
+       }                                                               \
+                                                                       \
+       set->data = map;                                                \
+       return 0;                                                       \
+}
+
+#define HASH_DESTROY(type)                                             \
+static void                                                            \
+type##_destroy(struct ip_set *set)                                     \
+{                                                                      \
+       struct ip_set_##type *map = set->data;                          \
+                                                                       \
+       harray_free(map->members);                                      \
+       kfree(map);                                                     \
+                                                                       \
+       set->data = NULL;                                               \
+}
+
+#define HASH_FLUSH(type, dtype)                                                \
+static void                                                            \
+type##_flush(struct ip_set *set)                                       \
+{                                                                      \
+       struct ip_set_##type *map = set->data;                          \
+       harray_flush(map->members, map->hashsize, sizeof(dtype));       \
+       map->elements = 0;                                              \
+}
+
+#define HASH_FLUSH_CIDR(type, dtype)                                   \
+static void                                                            \
+type##_flush(struct ip_set *set)                                       \
+{                                                                      \
+       struct ip_set_##type *map = set->data;                          \
+       harray_flush(map->members, map->hashsize, sizeof(dtype));       \
+       memset(map->cidr, 0, 30 * sizeof(uint8_t));                     \
+       memset(map->nets, 0, 30 * sizeof(uint32_t));                    \
+       map->elements = 0;                                              \
+}
+
+#define HASH_LIST_HEADER(type)                                         \
+static void                                                            \
+type##_list_header(const struct ip_set *set, void *data)               \
+{                                                                      \
+       const struct ip_set_##type *map = set->data;                    \
+       struct ip_set_req_##type##_create *header = data;               \
+                                                                       \
+       header->hashsize = map->hashsize;                               \
+       header->probes = map->probes;                                   \
+       header->resize = map->resize;                                   \
+       __##type##_list_header(map, header);                            \
+}
+
+#define HASH_LIST_MEMBERS_SIZE(type, dtype)                            \
+static int                                                             \
+type##_list_members_size(const struct ip_set *set)                     \
+{                                                                      \
+       const struct ip_set_##type *map = set->data;                    \
+                                                                       \
+       return (map->hashsize * sizeof(dtype));                         \
+}
+
+#define HASH_LIST_MEMBERS(type, dtype)                                 \
+static void                                                            \
+type##_list_members(const struct ip_set *set, void *data)              \
+{                                                                      \
+       const struct ip_set_##type *map = set->data;                    \
+       dtype *elem;                                                    \
+       uint32_t i;                                                     \
+                                                                       \
+       for (i = 0; i < map->hashsize; i++) {                           \
+               elem = HARRAY_ELEM(map->members, dtype *, i);           \
+               ((dtype *)data)[i] = *elem;                             \
+       }                                                               \
+}
+
+#define HASH_LIST_MEMBERS_MEMCPY(type, dtype)                          \
+static void                                                            \
+type##_list_members(const struct ip_set *set, void *data)              \
+{                                                                      \
+       const struct ip_set_##type *map = set->data;                    \
+       dtype *elem;                                                    \
+       uint32_t i;                                                     \
+                                                                       \
+       for (i = 0; i < map->hashsize; i++) {                           \
+               elem = HARRAY_ELEM(map->members, dtype *, i);           \
+               memcpy((((dtype *)data)+i), elem, sizeof(dtype));       \
+       }                                                               \
+}
+
+#define IP_SET_RTYPE(type, __features)                                 \
+struct ip_set_type ip_set_##type = {                                   \
+       .typename               = #type,                                \
+       .features               = __features,                           \
+       .protocol_version       = IP_SET_PROTOCOL_VERSION,              \
+       .create                 = &type##_create,                       \
+       .retry                  = &type##_retry,                        \
+       .destroy                = &type##_destroy,                      \
+       .flush                  = &type##_flush,                        \
+       .reqsize                = sizeof(struct ip_set_req_##type),     \
+       .addip                  = &type##_uadd,                         \
+       .addip_kernel           = &type##_kadd,                         \
+       .delip                  = &type##_udel,                         \
+       .delip_kernel           = &type##_kdel,                         \
+       .testip                 = &type##_utest,                        \
+       .testip_kernel          = &type##_ktest,                        \
+       .header_size            = sizeof(struct ip_set_req_##type##_create),\
+       .list_header            = &type##_list_header,                  \
+       .list_members_size      = &type##_list_members_size,            \
+       .list_members           = &type##_list_members,                 \
+       .me                     = THIS_MODULE,                          \
+};
+
+/* Helper functions */
+static inline void
+add_cidr_size(uint8_t *cidr, uint8_t size)
+{
+       uint8_t next;
+       int i;
+       
+       for (i = 0; i < 30 && cidr[i]; i++) {
+               if (cidr[i] < size) {
+                       next = cidr[i];
+                       cidr[i] = size;
+                       size = next;
+               }
+       }
+       if (i < 30)
+               cidr[i] = size;
+}
+
+static inline void
+del_cidr_size(uint8_t *cidr, uint8_t size)
+{
+       int i;
+       
+       for (i = 0; i < 29 && cidr[i]; i++) {
+               if (cidr[i] == size)
+                       cidr[i] = size = cidr[i+1];
+       }
+       cidr[29] = 0;
+}
+#endif /* __KERNEL */
+
+#ifndef UINT16_MAX
+#define UINT16_MAX 65535
+#endif
+
+static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};
+
+static inline ip_set_ip_t 
+pack_ip_cidr(ip_set_ip_t ip, unsigned char cidr)
+{
+       ip_set_ip_t addr, *paddr = &addr;
+       unsigned char n, t, *a;
+
+       addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
+#ifdef __KERNEL__
+       DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
+#endif
+       n = cidr / 8;
+       t = cidr % 8;   
+       a = &((unsigned char *)paddr)[n];
+       *a = *a /(1 << (8 - t)) + shifts[t];
+#ifdef __KERNEL__
+       DP("n: %u, t: %u, a: %u", n, t, *a);
+       DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
+          HIPQUAD(ip), cidr, NIPQUAD(addr));
+#endif
+
+       return ntohl(addr);
+}
+
+
+#endif /* __IP_SET_HASHES_H */
index 7de854b4ad57a5a1266a61dafd4e36690ccbe793..7551cb2eb3c525d45f8053e48cb44d91df695a73 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/netfilter_ipv4/ip_set.h>
 
 #define SETTYPE_NAME "iphash"
-#define MAX_RANGE 0x0000FFFF
 
 struct ip_set_iphash {
        ip_set_ip_t *members;           /* the iphash proper */
@@ -13,7 +12,7 @@ struct ip_set_iphash {
        uint16_t probes;                /* max number of probes  */
        uint16_t resize;                /* resize factor in percent */
        ip_set_ip_t netmask;            /* netmask */
-       void *initval[0];               /* initvals for jhash_1word */
+       uint32_t initval[0];            /* initvals for jhash_1word */
 };
 
 struct ip_set_req_iphash_create {
index e3390be40d8862d3e3035d42f6a7e505238a0a3c..2f409d970f4979e08ab4c23ea5f595f7ae33352a 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/netfilter_ipv4/ip_set.h>
 
 #define SETTYPE_NAME "ipmap"
-#define MAX_RANGE 0x0000FFFF
 
 struct ip_set_ipmap {
        void *members;                  /* the ipmap proper */
@@ -13,6 +12,7 @@ struct ip_set_ipmap {
        ip_set_ip_t netmask;            /* subnet netmask */
        ip_set_ip_t sizeid;             /* size of set in IPs */
        ip_set_ip_t hosts;              /* number of hosts in a subnet */
+       size_t size;                    /* size of the ipmap proper */
 };
 
 struct ip_set_req_ipmap_create {
@@ -25,7 +25,7 @@ struct ip_set_req_ipmap {
        ip_set_ip_t ip;
 };
 
-static unsigned int
+static inline unsigned int
 mask_to_bits(ip_set_ip_t mask)
 {
        unsigned int bits = 32;
@@ -41,7 +41,7 @@ mask_to_bits(ip_set_ip_t mask)
        return bits;
 }
 
-static ip_set_ip_t
+static inline ip_set_ip_t
 range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits)
 {
        ip_set_ip_t mask = 0xFFFFFFFE;
index b715c56c2a83a8b01fa23f8a82165e58f796d786..ccec14e82c7a46aeed5d968ae3271cca0412f158 100644 (file)
@@ -4,8 +4,6 @@
 #include <linux/netfilter_ipv4/ip_set.h>
 
 #define SETTYPE_NAME "ipporthash"
-#define MAX_RANGE 0x0000FFFF
-#define INVALID_PORT   (MAX_RANGE + 1)
 
 struct ip_set_ipporthash {
        ip_set_ip_t *members;           /* the ipporthash proper */
@@ -15,7 +13,7 @@ struct ip_set_ipporthash {
        uint16_t resize;                /* resize factor in percent */
        ip_set_ip_t first_ip;           /* host byte order, included in range */
        ip_set_ip_t last_ip;            /* host byte order, included in range */
-       void *initval[0];               /* initvals for jhash_1word */
+       uint32_t initval[0];            /* initvals for jhash_1word */
 };
 
 struct ip_set_req_ipporthash_create {
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_ipportiphash.h b/kernel/include/linux/netfilter_ipv4/ip_set_ipportiphash.h
new file mode 100644 (file)
index 0000000..4d794bf
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __IP_SET_IPPORTIPHASH_H
+#define __IP_SET_IPPORTIPHASH_H
+
+#include <linux/netfilter_ipv4/ip_set.h>
+
+#define SETTYPE_NAME "ipportiphash"
+
+struct ipportip {
+       ip_set_ip_t ip;
+       ip_set_ip_t ip1;
+};
+
+struct ip_set_ipportiphash {
+       struct ipportip *members;       /* the ipportip proper */
+       uint32_t elements;              /* number of elements */
+       uint32_t hashsize;              /* hash size */
+       uint16_t probes;                /* max number of probes  */
+       uint16_t resize;                /* resize factor in percent */
+       ip_set_ip_t first_ip;           /* host byte order, included in range */
+       ip_set_ip_t last_ip;            /* host byte order, included in range */
+       uint32_t initval[0];            /* initvals for jhash_1word */
+};
+
+struct ip_set_req_ipportiphash_create {
+       uint32_t hashsize;
+       uint16_t probes;
+       uint16_t resize;
+       ip_set_ip_t from;
+       ip_set_ip_t to;
+};
+
+struct ip_set_req_ipportiphash {
+       ip_set_ip_t ip;
+       ip_set_ip_t port;
+       ip_set_ip_t ip1;
+};
+
+#endif /* __IP_SET_IPPORTIPHASH_H */
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_ipportnethash.h b/kernel/include/linux/netfilter_ipv4/ip_set_ipportnethash.h
new file mode 100644 (file)
index 0000000..9c78a68
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __IP_SET_IPPORTNETHASH_H
+#define __IP_SET_IPPORTNETHASH_H
+
+#include <linux/netfilter_ipv4/ip_set.h>
+
+#define SETTYPE_NAME "ipportnethash"
+
+struct ipportip {
+       ip_set_ip_t ip;
+       ip_set_ip_t ip1;
+};
+
+struct ip_set_ipportnethash {
+       struct ipportip *members;       /* the ipportip proper */
+       uint32_t elements;              /* number of elements */
+       uint32_t hashsize;              /* hash size */
+       uint16_t probes;                /* max number of probes  */
+       uint16_t resize;                /* resize factor in percent */
+       ip_set_ip_t first_ip;           /* host byte order, included in range */
+       ip_set_ip_t last_ip;            /* host byte order, included in range */
+       uint8_t cidr[30];               /* CIDR sizes */
+       uint16_t nets[30];              /* nr of nets by CIDR sizes */
+       uint32_t initval[0];            /* initvals for jhash_1word */
+};
+
+struct ip_set_req_ipportnethash_create {
+       uint32_t hashsize;
+       uint16_t probes;
+       uint16_t resize;
+       ip_set_ip_t from;
+       ip_set_ip_t to;
+};
+
+struct ip_set_req_ipportnethash {
+       ip_set_ip_t ip;
+       ip_set_ip_t port;
+       ip_set_ip_t ip1;
+       uint8_t cidr;
+};
+
+#endif /* __IP_SET_IPPORTNETHASH_H */
index 64e716b0342c710b0bccbe4dbd10d6227ed1951c..de5cf471bd7c64e80b95807035f09b669c0f586e 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/netfilter_ipv4/ip_set.h>
 
 #define SETTYPE_NAME "iptree"
-#define MAX_RANGE 0x0000FFFF
 
 struct ip_set_iptreed {
        unsigned long expires[256];             /* x.x.x.ADDR */
index bef576ac47412ee5b47691a4f553e1a0bfbb041e..a58bc4efd260344b0291d4a4b22b0bee7925710e 100644 (file)
@@ -33,7 +33,7 @@ struct ip_set_req_iptreemap_create {
 };
 
 struct ip_set_req_iptreemap {
-       ip_set_ip_t start;
+       ip_set_ip_t ip;
        ip_set_ip_t end;
 };
 
index ee34c9b3990152d4e7cce1f7df7da4ae3393ce46..82ea96d64156d39476b5d6e82ad42cebd37f6fec 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/netfilter_ipv4/ip_set.h>
 
 #define SETTYPE_NAME "macipmap"
-#define MAX_RANGE 0x0000FFFF
 
 /* general flags */
 #define IPSET_MACIP_MATCHUNSET 1
@@ -17,6 +16,7 @@ struct ip_set_macipmap {
        ip_set_ip_t first_ip;           /* host byte order, included in range */
        ip_set_ip_t last_ip;            /* host byte order, included in range */
        u_int32_t flags;
+       size_t size;                    /* size of the ipmap proper */
 };
 
 struct ip_set_req_macipmap_create {
index d22bed7699960c39e00bf6e4de678ce235e3d1d0..8bce6675e2678978952c1b829fdc0a825bfc2a02 100644 (file)
@@ -2,8 +2,10 @@
 #define _IP_SET_MALLOC_H
 
 #ifdef __KERNEL__
+#include <linux/vmalloc.h> 
 
 static size_t max_malloc_size = 0, max_page_size = 0;
+static size_t default_max_malloc_size = 131072;                        /* Guaranteed: slab.c */
 
 static inline int init_max_page_size(void)
 {
@@ -12,7 +14,7 @@ static inline int init_max_page_size(void)
 #define __GFP_NOWARN           0
 
        /* Guaranteed: slab.c */
-       max_malloc_size = max_page_size = 131072;
+       max_malloc_size = max_page_size = default_max_malloc_size;
 #else
        size_t page_size = 0;
 
@@ -130,7 +132,7 @@ static inline void * ip_set_malloc(size_t bytes)
 {
        BUG_ON(max_malloc_size == 0);
 
-       if (bytes > max_malloc_size)
+       if (bytes > default_max_malloc_size)
                return vmalloc(bytes);
        else
                return kmalloc(bytes, GFP_KERNEL | __GFP_NOWARN);
@@ -140,7 +142,7 @@ static inline void ip_set_free(void * data, size_t bytes)
 {
        BUG_ON(max_malloc_size == 0);
 
-       if (bytes > max_malloc_size)
+       if (bytes > default_max_malloc_size)
                vfree(data);
        else
                kfree(data);
index 172ef02d8e244b313a626e2f744c97e1063764c6..eecd68b79b64541a29a0302c6cbb94786d91c000 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/netfilter_ipv4/ip_set.h>
 
 #define SETTYPE_NAME "nethash"
-#define MAX_RANGE 0x0000FFFF
 
 struct ip_set_nethash {
        ip_set_ip_t *members;           /* the nethash proper */
@@ -12,8 +11,9 @@ struct ip_set_nethash {
        uint32_t hashsize;              /* hash size */
        uint16_t probes;                /* max number of probes  */
        uint16_t resize;                /* resize factor in percent */
-       unsigned char cidr[30];         /* CIDR sizes */
-       void *initval[0];               /* initvals for jhash_1word */
+       uint8_t cidr[30];               /* CIDR sizes */
+       uint16_t nets[30];              /* nr of nets by CIDR sizes */
+       uint32_t initval[0];            /* initvals for jhash_1word */
 };
 
 struct ip_set_req_nethash_create {
@@ -24,32 +24,7 @@ struct ip_set_req_nethash_create {
 
 struct ip_set_req_nethash {
        ip_set_ip_t ip;
-       unsigned char cidr;
+       uint8_t cidr;
 };
 
-static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};
-
-static inline ip_set_ip_t 
-pack(ip_set_ip_t ip, unsigned char cidr)
-{
-       ip_set_ip_t addr, *paddr = &addr;
-       unsigned char n, t, *a;
-
-       addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
-#ifdef __KERNEL__
-       DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
-#endif
-       n = cidr / 8;
-       t = cidr % 8;   
-       a = &((unsigned char *)paddr)[n];
-       *a = *a /(1 << (8 - t)) + shifts[t];
-#ifdef __KERNEL__
-       DP("n: %u, t: %u, a: %u", n, t, *a);
-       DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
-          HIPQUAD(ip), cidr, NIPQUAD(addr));
-#endif
-
-       return ntohl(addr);
-}
-
 #endif /* __IP_SET_NETHASH_H */
index c17165ca62eb17a3182c70f49616c1398bd2d422..1a1538055582bf31ea75f0f974b9f762bf08855b 100644 (file)
@@ -4,13 +4,12 @@
 #include <linux/netfilter_ipv4/ip_set.h>
 
 #define SETTYPE_NAME   "portmap"
-#define MAX_RANGE      0x0000FFFF
-#define INVALID_PORT   (MAX_RANGE + 1)
 
 struct ip_set_portmap {
        void *members;                  /* the portmap proper */
-       ip_set_ip_t first_port;         /* host byte order, included in range */
-       ip_set_ip_t last_port;          /* host byte order, included in range */
+       ip_set_ip_t first_ip;           /* host byte order, included in range */
+       ip_set_ip_t last_ip;            /* host byte order, included in range */
+       size_t size;                    /* size of the ipmap proper */
 };
 
 struct ip_set_req_portmap_create {
@@ -19,7 +18,7 @@ struct ip_set_req_portmap_create {
 };
 
 struct ip_set_req_portmap {
-       ip_set_ip_t port;
+       ip_set_ip_t ip;
 };
 
 #endif /* __IP_SET_PORTMAP_H */
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_setlist.h b/kernel/include/linux/netfilter_ipv4/ip_set_setlist.h
new file mode 100644 (file)
index 0000000..55f0afb
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __IP_SET_SETLIST_H
+#define __IP_SET_SETLIST_H
+
+#include <linux/netfilter_ipv4/ip_set.h>
+
+#define SETTYPE_NAME "setlist"
+
+#define IP_SET_SETLIST_ADD_AFTER       0
+#define IP_SET_SETLIST_ADD_BEFORE      1
+
+struct ip_set_setlist {
+       uint8_t size;
+       ip_set_id_t id[0];
+};
+
+struct ip_set_req_setlist_create {
+       uint8_t size;
+};
+
+struct ip_set_req_setlist {
+       char name[IP_SET_MAXNAMELEN];
+       char ref[IP_SET_MAXNAMELEN];
+       uint8_t before;
+};
+
+#endif /* __IP_SET_SETLIST_H */
index a525518f963add14b7b3180cfef80b68880c0f3b..c4fcc6940aa2599a506b081265c52e0ea88b45e6 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/skbuff.h>
 #include <linux/random.h>
 #include <linux/jhash.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <linux/semaphore.h>
 #endif
 #include <linux/spinlock.h>
-#include <linux/vmalloc.h>
 
 #define ASSERT_READ_LOCK(x)
 #define ASSERT_WRITE_LOCK(x)
+#include <linux/netfilter.h>
 #include <linux/netfilter_ipv4/ip_set.h>
 
 static struct list_head set_type_list;         /* all registered sets */
@@ -235,10 +234,10 @@ ip_set_testip_kernel(ip_set_id_t index,
                 && follow_bindings(index, set, ip));
        read_unlock_bh(&ip_set_lock);
 
-       return res;
+       return (res < 0 ? 0 : res);
 }
 
-void
+int
 ip_set_addip_kernel(ip_set_id_t index,
                    const struct sk_buff *skb,
                    const u_int32_t *flags)
@@ -268,9 +267,11 @@ ip_set_addip_kernel(ip_set_id_t index,
            && set->type->retry
            && (res = set->type->retry(set)) == 0)
                goto retry;
+       
+       return res;
 }
 
-void
+int
 ip_set_delip_kernel(ip_set_id_t index,
                    const struct sk_buff *skb,
                    const u_int32_t *flags)
@@ -294,6 +295,8 @@ ip_set_delip_kernel(ip_set_id_t index,
                 && flags[i]
                 && follow_bindings(index, set, ip));
        read_unlock_bh(&ip_set_lock);
+       
+       return res;
 }
 
 /* Register and deregister settype */
@@ -358,6 +361,29 @@ ip_set_unregister_set_type(struct ip_set_type *set_type)
 
 }
 
+ip_set_id_t
+__ip_set_get_byname(const char *name, struct ip_set **set)
+{
+       ip_set_id_t i, index = IP_SET_INVALID_ID;
+       
+       for (i = 0; i < ip_set_max; i++) {
+               if (ip_set_list[i] != NULL
+                   && SETNAME_EQ(ip_set_list[i]->name, name)) {
+                       __ip_set_get(i);
+                       index = i;
+                       *set = ip_set_list[i];
+                       break;
+               }
+       }
+       return index;
+}
+
+void __ip_set_put_byid(ip_set_id_t index)
+{
+       if (ip_set_list[index])
+               __ip_set_put(index);
+}
+
 /*
  * Userspace routines
  */
@@ -490,7 +516,16 @@ ip_set_addip(ip_set_id_t index,
             const void *data,
             size_t size)
 {
+       struct ip_set *set = ip_set_list[index];
+
+       IP_SET_ASSERT(set);
 
+       if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) {
+               ip_set_printk("data length wrong (want %zu, have %zu)",
+                             set->type->reqsize,
+                             size - sizeof(struct ip_set_req_adt));
+               return -EINVAL;
+       }
        return __ip_set_addip(index,
                              data + sizeof(struct ip_set_req_adt),
                              size - sizeof(struct ip_set_req_adt));
@@ -506,6 +541,13 @@ ip_set_delip(ip_set_id_t index,
        int res;
        
        IP_SET_ASSERT(set);
+
+       if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) {
+               ip_set_printk("data length wrong (want %zu, have %zu)",
+                             set->type->reqsize,
+                             size - sizeof(struct ip_set_req_adt));
+               return -EINVAL;
+       }
        write_lock_bh(&set->lock);
        res = set->type->delip(set,
                               data + sizeof(struct ip_set_req_adt),
@@ -526,6 +568,13 @@ ip_set_testip(ip_set_id_t index,
        int res;
 
        IP_SET_ASSERT(set);
+       
+       if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) {
+               ip_set_printk("data length wrong (want %zu, have %zu)",
+                             set->type->reqsize,
+                             size - sizeof(struct ip_set_req_adt));
+               return -EINVAL;
+       }
        res = __ip_set_testip(set,
                              data + sizeof(struct ip_set_req_adt),
                              size - sizeof(struct ip_set_req_adt),
@@ -805,6 +854,7 @@ ip_set_create(const char *name,
        int res = 0;
 
        DP("setname: %s, typename: %s, id: %u", name, typename, restore);
+
        /*
         * First, and without any locks, allocate and initialize
         * a normal base set structure.
@@ -848,6 +898,14 @@ ip_set_create(const char *name,
        }
        read_unlock_bh(&ip_set_lock);
 
+       /* Check request size */
+       if (size != set->type->header_size) {
+               ip_set_printk("data length wrong (want %zu, have %zu)",
+                             set->type->header_size,
+                             size);
+               goto put_out;
+       }
+
        /*
         * Without holding any locks, create private part.
         */
@@ -1007,7 +1065,9 @@ ip_set_swap(ip_set_id_t from_index, ip_set_id_t to_index)
        u_int32_t from_ref;
 
        DP("set: %s to %s",  from->name, to->name);
-       /* Features must not change. Artifical restriction. */
+       /* Features must not change. 
+        * Not an artifical restriction anymore, as we must prevent
+        * possible loops created by swapping in setlist type of sets. */
        if (from->type->features != to->type->features)
                return -ENOEXEC;
 
@@ -1916,6 +1976,7 @@ static struct nf_sockopt_ops so_set = {
 };
 
 static int max_sets, hash_size;
+
 module_param(max_sets, int, 0600);
 MODULE_PARM_DESC(max_sets, "maximal number of sets");
 module_param(hash_size, int, 0600);
@@ -1958,6 +2019,7 @@ static int __init ip_set_init(void)
                vfree(ip_set_hash);
                return res;
        }
+       
        return 0;
 }
 
@@ -1976,6 +2038,8 @@ EXPORT_SYMBOL(ip_set_unregister_set_type);
 EXPORT_SYMBOL(ip_set_get_byname);
 EXPORT_SYMBOL(ip_set_get_byindex);
 EXPORT_SYMBOL(ip_set_put);
+EXPORT_SYMBOL(__ip_set_get_byname);
+EXPORT_SYMBOL(__ip_set_put_byid);
 
 EXPORT_SYMBOL(ip_set_addip_kernel);
 EXPORT_SYMBOL(ip_set_delip_kernel);
index 2ac6066d3021e829a196acad4a74c27396647a3a..38b83ed5b80a5a75205f9ac6da346636992c9e15 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  *
  * 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
 #include <linux/moduleparam.h>
 #include <linux/ip.h>
 #include <linux/skbuff.h>
-#include <linux/version.h>
 #include <linux/jhash.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <linux/spinlock.h>
-#include <linux/vmalloc.h>
 #include <linux/random.h>
 
 #include <net/ip.h>
 
-#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_hashes.h>
 #include <linux/netfilter_ipv4/ip_set_iphash.h>
 
 static int limit = MAX_RANGE;
 
 static inline __u32
-jhash_ip(const struct ip_set_iphash *map, uint16_t i, ip_set_ip_t ip)
-{
-       return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
-}
-
-static inline __u32
-hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+iphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
        struct ip_set_iphash *map = set->data;
        __u32 id;
@@ -60,59 +51,30 @@ hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
 }
 
 static inline int
-__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+iphash_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
-       return (ip && hash_id(set, ip, hash_ip) != UINT_MAX);
+       return (ip && iphash_id(set, hash_ip, ip) != UINT_MAX);
 }
 
-static int
-testip(struct ip_set *set, const void *data, size_t size,
-       ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_iphash *req = data;
+#define KADT_CONDITION
 
-       if (size != sizeof(struct ip_set_req_iphash)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_iphash),
-                             size);
-               return -EINVAL;
-       }
-       return __testip(set, req->ip, hash_ip);
-}
-
-static int
-testip_kernel(struct ip_set *set,
-             const struct sk_buff *skb,
-             ip_set_ip_t *hash_ip,
-             const u_int32_t *flags,
-             unsigned char index)
-{
-       return __testip(set,
-                       ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                       hash_ip);
-}
+UADT(iphash, test)
+KADT(iphash, test, ipaddr)
 
 static inline int
-__addip(struct ip_set_iphash *map, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+__iphash_add(struct ip_set_iphash *map, ip_set_ip_t *ip)
 {
        __u32 probe;
        u_int16_t i;
        ip_set_ip_t *elem;
        
-       if (!ip || map->elements >= limit)
-               return -ERANGE;
-
-       *hash_ip = ip & map->netmask;
-       
        for (i = 0; i < map->probes; i++) {
-               probe = jhash_ip(map, i, *hash_ip) % map->hashsize;
+               probe = jhash_ip(map, i, *ip) % map->hashsize;
                elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
-               if (*elem == *hash_ip)
+               if (*elem == *ip)
                        return -EEXIST;
                if (!*elem) {
-                       *elem = *hash_ip;
+                       *elem = *ip;
                        map->elements++;
                        return 0;
                }
@@ -121,110 +83,32 @@ __addip(struct ip_set_iphash *map, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
        return -EAGAIN;
 }
 
-static int
-addip(struct ip_set *set, const void *data, size_t size,
-        ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_iphash *req = data;
-
-       if (size != sizeof(struct ip_set_req_iphash)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_iphash),
-                             size);
-               return -EINVAL;
-       }
-       return __addip(set->data, req->ip, hash_ip);
-}
-
-static int
-addip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       return __addip((struct ip_set_iphash *) set->data,
-                      ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                      hash_ip);
-}
-
-static int retry(struct ip_set *set)
+static inline int
+iphash_add(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
        struct ip_set_iphash *map = set->data;
-       ip_set_ip_t hash_ip, *elem;
-       void *members;
-       u_int32_t i, hashsize = map->hashsize;
-       int res;
-       struct ip_set_iphash *tmp;
        
-       if (map->resize == 0)
+       if (!ip || map->elements >= limit)
                return -ERANGE;
 
-    again:
-       res = 0;
-       
-       /* Calculate new hash size */
-       hashsize += (hashsize * map->resize)/100;
-       if (hashsize == map->hashsize)
-               hashsize++;
-       
-       ip_set_printk("rehashing of set %s triggered: "
-                     "hashsize grows from %u to %u",
-                     set->name, map->hashsize, hashsize);
-
-       tmp = kmalloc(sizeof(struct ip_set_iphash)
-                     + map->probes * sizeof(uint32_t), GFP_ATOMIC);
-       if (!tmp) {
-               DP("out of memory for %d bytes",
-                  sizeof(struct ip_set_iphash)
-                  + map->probes * sizeof(uint32_t));
-               return -ENOMEM;
-       }
-       tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
-       if (!tmp->members) {
-               DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
-               kfree(tmp);
-               return -ENOMEM;
-       }
-       tmp->hashsize = hashsize;
-       tmp->elements = 0;
-       tmp->probes = map->probes;
-       tmp->resize = map->resize;
-       tmp->netmask = map->netmask;
-       memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
-       
-       write_lock_bh(&set->lock);
-       map = set->data; /* Play safe */
-       for (i = 0; i < map->hashsize && res == 0; i++) {
-               elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);     
-               if (*elem)
-                       res = __addip(tmp, *elem, &hash_ip);
-       }
-       if (res) {
-               /* Failure, try again */
-               write_unlock_bh(&set->lock);
-               harray_free(tmp->members);
-               kfree(tmp);
-               goto again;
-       }
+       *hash_ip = ip & map->netmask;
        
-       /* Success at resizing! */
-       members = map->members;
-
-       map->hashsize = tmp->hashsize;
-       map->members = tmp->members;
-       write_unlock_bh(&set->lock);
+       return __iphash_add(map, hash_ip);
+}
 
-       harray_free(members);
-       kfree(tmp);
+UADT(iphash, add)
+KADT(iphash, add, ipaddr)
 
-       return 0;
+static inline void
+__iphash_retry(struct ip_set_iphash *tmp, struct ip_set_iphash *map)
+{
+       tmp->netmask = map->netmask;
 }
 
+HASH_RETRY(iphash, ip_set_ip_t)
+
 static inline int
-__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+iphash_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
        struct ip_set_iphash *map = set->data;
        ip_set_ip_t id, *elem;
@@ -232,7 +116,7 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
        if (!ip)
                return -ERANGE;
 
-       id = hash_id(set, ip, hash_ip);
+       id = iphash_id(set, hash_ip, ip);
        if (id == UINT_MAX)
                return -EEXIST;
                
@@ -243,151 +127,35 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
        return 0;
 }
 
-static int
-delip(struct ip_set *set, const void *data, size_t size,
-        ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_iphash *req = data;
+UADT(iphash, del)
+KADT(iphash, del, ipaddr)
 
-       if (size != sizeof(struct ip_set_req_iphash)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_iphash),
-                             size);
-               return -EINVAL;
-       }
-       return __delip(set, req->ip, hash_ip);
-}
-
-static int
-delip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       return __delip(set,
-                      ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                      hash_ip);
-}
-
-static int create(struct ip_set *set, const void *data, size_t size)
+static inline int
+__iphash_create(const struct ip_set_req_iphash_create *req,
+               struct ip_set_iphash *map)
 {
-       const struct ip_set_req_iphash_create *req = data;
-       struct ip_set_iphash *map;
-       uint16_t i;
-
-       if (size != sizeof(struct ip_set_req_iphash_create)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                              sizeof(struct ip_set_req_iphash_create),
-                              size);
-               return -EINVAL;
-       }
-
-       if (req->hashsize < 1) {
-               ip_set_printk("hashsize too small");
-               return -ENOEXEC;
-       }
-
-       if (req->probes < 1) {
-               ip_set_printk("probes too small");
-               return -ENOEXEC;
-       }
-
-       map = kmalloc(sizeof(struct ip_set_iphash)
-                     + req->probes * sizeof(uint32_t), GFP_KERNEL);
-       if (!map) {
-               DP("out of memory for %d bytes",
-                  sizeof(struct ip_set_iphash)
-                  + req->probes * sizeof(uint32_t));
-               return -ENOMEM;
-       }
-       for (i = 0; i < req->probes; i++)
-               get_random_bytes(((uint32_t *) map->initval)+i, 4);
-       map->elements = 0;
-       map->hashsize = req->hashsize;
-       map->probes = req->probes;
-       map->resize = req->resize;
        map->netmask = req->netmask;
-       map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
-       if (!map->members) {
-               DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
-               kfree(map);
-               return -ENOMEM;
-       }
-
-       set->data = map;
+       
        return 0;
 }
 
-static void destroy(struct ip_set *set)
-{
-       struct ip_set_iphash *map = set->data;
+HASH_CREATE(iphash, ip_set_ip_t)
+HASH_DESTROY(iphash)
 
-       harray_free(map->members);
-       kfree(map);
-
-       set->data = NULL;
-}
+HASH_FLUSH(iphash, ip_set_ip_t)
 
-static void flush(struct ip_set *set)
-{
-       struct ip_set_iphash *map = set->data;
-       harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
-       map->elements = 0;
-}
-
-static void list_header(const struct ip_set *set, void *data)
-{
-       struct ip_set_iphash *map = set->data;
-       struct ip_set_req_iphash_create *header = data;
-
-       header->hashsize = map->hashsize;
-       header->probes = map->probes;
-       header->resize = map->resize;
+static inline void
+__iphash_list_header(const struct ip_set_iphash *map,
+                    struct ip_set_req_iphash_create *header)
+{    
        header->netmask = map->netmask;
 }
 
-static int list_members_size(const struct ip_set *set)
-{
-       const struct ip_set_iphash *map = set->data;
+HASH_LIST_HEADER(iphash)
+HASH_LIST_MEMBERS_SIZE(iphash, ip_set_ip_t)
+HASH_LIST_MEMBERS(iphash, ip_set_ip_t)
 
-       return (map->hashsize * sizeof(ip_set_ip_t));
-}
-
-static void list_members(const struct ip_set *set, void *data)
-{
-       const struct ip_set_iphash *map = set->data;
-       ip_set_ip_t i, *elem;
-
-       for (i = 0; i < map->hashsize; i++) {
-               elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);     
-               ((ip_set_ip_t *)data)[i] = *elem;
-       }
-}
-
-static struct ip_set_type ip_set_iphash = {
-       .typename               = SETTYPE_NAME,
-       .features               = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
-       .protocol_version       = IP_SET_PROTOCOL_VERSION,
-       .create                 = &create,
-       .destroy                = &destroy,
-       .flush                  = &flush,
-       .reqsize                = sizeof(struct ip_set_req_iphash),
-       .addip                  = &addip,
-       .addip_kernel           = &addip_kernel,
-       .retry                  = &retry,
-       .delip                  = &delip,
-       .delip_kernel           = &delip_kernel,
-       .testip                 = &testip,
-       .testip_kernel          = &testip_kernel,
-       .header_size            = sizeof(struct ip_set_req_iphash_create),
-       .list_header            = &list_header,
-       .list_members_size      = &list_members_size,
-       .list_members           = &list_members,
-       .me                     = THIS_MODULE,
-};
+IP_SET_RTYPE(iphash, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -395,17 +163,4 @@ MODULE_DESCRIPTION("iphash type of IP sets");
 module_param(limit, int, 0600);
 MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
 
-static int __init ip_set_iphash_init(void)
-{
-       init_max_page_size();
-       return ip_set_register_set_type(&ip_set_iphash);
-}
-
-static void __exit ip_set_iphash_fini(void)
-{
-       /* FIXME: possible race with ip_set_create() */
-       ip_set_unregister_set_type(&ip_set_iphash);
-}
-
-module_init(ip_set_iphash_init);
-module_exit(ip_set_iphash_fini);
+REGISTER_MODULE(iphash)
index aeead3beb67ddcd95a11dc2d120f2272a3727c77..e1a16637efa861ac89e5f67866b1eaf0ff34ab2e 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
  *                         Patrick Schaaf <bof@bof.de>
- * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ * Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  *
  * 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
 #include <linux/module.h>
 #include <linux/ip.h>
 #include <linux/skbuff.h>
-#include <linux/version.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <linux/spinlock.h>
 
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_bitmaps.h>
 #include <linux/netfilter_ipv4/ip_set_ipmap.h>
 
 static inline ip_set_ip_t
@@ -29,9 +28,9 @@ ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip)
 }
 
 static inline int
-__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+ipmap_test(const struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
-       struct ip_set_ipmap *map = set->data;
+       const struct ip_set_ipmap *map = set->data;
        
        if (ip < map->first_ip || ip > map->last_ip)
                return -ERANGE;
@@ -42,38 +41,13 @@ __testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
        return !!test_bit(ip_to_id(map, *hash_ip), map->members);
 }
 
-static int
-testip(struct ip_set *set, const void *data, size_t size,
-       ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_ipmap *req = data;
+#define KADT_CONDITION
 
-       if (size != sizeof(struct ip_set_req_ipmap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_ipmap),
-                             size);
-               return -EINVAL;
-       }
-       return __testip(set, req->ip, hash_ip);
-}
-
-static int
-testip_kernel(struct ip_set *set,
-             const struct sk_buff *skb,
-             ip_set_ip_t *hash_ip,
-             const u_int32_t *flags,
-             unsigned char index)
-{
-       int res =  __testip(set,
-                       ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                       hash_ip);
-       return (res < 0 ? 0 : res);
-}
+UADT(ipmap, test)
+KADT(ipmap, test, ipaddr)
 
 static inline int
-__addip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+ipmap_add(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
        struct ip_set_ipmap *map = set->data;
 
@@ -88,38 +62,11 @@ __addip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
        return 0;
 }
 
-static int
-addip(struct ip_set *set, const void *data, size_t size,
-      ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_ipmap *req = data;
-
-       if (size != sizeof(struct ip_set_req_ipmap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_ipmap),
-                             size);
-               return -EINVAL;
-       }
-       DP("%u.%u.%u.%u", HIPQUAD(req->ip));
-       return __addip(set, req->ip, hash_ip);
-}
-
-static int
-addip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       return __addip(set,
-                      ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                      hash_ip);
-}
+UADT(ipmap, add)
+KADT(ipmap, add, ipaddr)
 
 static inline int
-__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+ipmap_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
        struct ip_set_ipmap *map = set->data;
 
@@ -134,64 +81,13 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
        return 0;
 }
 
-static int
-delip(struct ip_set *set, const void *data, size_t size,
-      ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_ipmap *req = data;
+UADT(ipmap, del)
+KADT(ipmap, del, ipaddr)
 
-       if (size != sizeof(struct ip_set_req_ipmap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_ipmap),
-                             size);
-               return -EINVAL;
-       }
-       return __delip(set, req->ip, hash_ip);
-}
-
-static int
-delip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       return __delip(set,
-                      ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                      hash_ip);
-}
-
-static int create(struct ip_set *set, const void *data, size_t size)
+static inline int
+__ipmap_create(const struct ip_set_req_ipmap_create *req,
+              struct ip_set_ipmap *map)
 {
-       int newbytes;
-       const struct ip_set_req_ipmap_create *req = data;
-       struct ip_set_ipmap *map;
-
-       if (size != sizeof(struct ip_set_req_ipmap_create)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_ipmap_create),
-                             size);
-               return -EINVAL;
-       }
-
-       DP("from %u.%u.%u.%u to %u.%u.%u.%u",
-          HIPQUAD(req->from), HIPQUAD(req->to));
-
-       if (req->from > req->to) {
-               DP("bad ip range");
-               return -ENOEXEC;
-       }
-
-       map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL);
-       if (!map) {
-               DP("out of memory for %d bytes",
-                  sizeof(struct ip_set_ipmap));
-               return -ENOMEM;
-       }
-       map->first_ip = req->from;
-       map->last_ip = req->to;
        map->netmask = req->netmask;
 
        if (req->netmask == 0xFFFFFFFF) {
@@ -200,12 +96,12 @@ static int create(struct ip_set *set, const void *data, size_t size)
        } else {
                unsigned int mask_bits, netmask_bits;
                ip_set_ip_t mask;
-               
+
                map->first_ip &= map->netmask;  /* Should we better bark? */
-               
+
                mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
                netmask_bits = mask_to_bits(map->netmask);
-               
+
                if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF))
                    || netmask_bits <= mask_bits)
                        return -ENOEXEC;
@@ -216,101 +112,33 @@ static int create(struct ip_set *set, const void *data, size_t size)
                map->sizeid = 2 << (netmask_bits - mask_bits - 1);
        }
        if (map->sizeid > MAX_RANGE + 1) {
-               ip_set_printk("range too big (max %d addresses)",
-                              MAX_RANGE+1);
-               kfree(map);
+               ip_set_printk("range too big, %d elements (max %d)",
+                              map->sizeid, MAX_RANGE+1);
                return -ENOEXEC;
        }
        DP("hosts %u, sizeid %u", map->hosts, map->sizeid);
-       newbytes = bitmap_bytes(0, map->sizeid - 1);
-       map->members = kmalloc(newbytes, GFP_KERNEL);
-       if (!map->members) {
-               DP("out of memory for %d bytes", newbytes);
-               kfree(map);
-               return -ENOMEM;
-       }
-       memset(map->members, 0, newbytes);
-       
-       set->data = map;
-       return 0;
-}
-
-static void destroy(struct ip_set *set)
-{
-       struct ip_set_ipmap *map = set->data;
-       
-       kfree(map->members);
-       kfree(map);
-       
-       set->data = NULL;
+       return bitmap_bytes(0, map->sizeid - 1);
 }
 
-static void flush(struct ip_set *set)
-{
-       struct ip_set_ipmap *map = set->data;
-       memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
-}
+BITMAP_CREATE(ipmap)
+BITMAP_DESTROY(ipmap)
+BITMAP_FLUSH(ipmap)
 
-static void list_header(const struct ip_set *set, void *data)
+static inline void
+__ipmap_list_header(const struct ip_set_ipmap *map,
+                   struct ip_set_req_ipmap_create *header)
 {
-       const struct ip_set_ipmap *map = set->data;
-       struct ip_set_req_ipmap_create *header = data;
-
-       header->from = map->first_ip;
-       header->to = map->last_ip;
        header->netmask = map->netmask;
 }
 
-static int list_members_size(const struct ip_set *set)
-{
-       const struct ip_set_ipmap *map = set->data;
-
-       return bitmap_bytes(0, map->sizeid - 1);
-}
-
-static void list_members(const struct ip_set *set, void *data)
-{
-       const struct ip_set_ipmap *map = set->data;
-       int bytes = bitmap_bytes(0, map->sizeid - 1);
+BITMAP_LIST_HEADER(ipmap)
+BITMAP_LIST_MEMBERS_SIZE(ipmap)
+BITMAP_LIST_MEMBERS(ipmap)
 
-       memcpy(data, map->members, bytes);
-}
-
-static struct ip_set_type ip_set_ipmap = {
-       .typename               = SETTYPE_NAME,
-       .features               = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
-       .protocol_version       = IP_SET_PROTOCOL_VERSION,
-       .create                 = &create,
-       .destroy                = &destroy,
-       .flush                  = &flush,
-       .reqsize                = sizeof(struct ip_set_req_ipmap),
-       .addip                  = &addip,
-       .addip_kernel           = &addip_kernel,
-       .delip                  = &delip,
-       .delip_kernel           = &delip_kernel,
-       .testip                 = &testip,
-       .testip_kernel          = &testip_kernel,
-       .header_size            = sizeof(struct ip_set_req_ipmap_create),
-       .list_header            = &list_header,
-       .list_members_size      = &list_members_size,
-       .list_members           = &list_members,
-       .me                     = THIS_MODULE,
-};
+IP_SET_TYPE(ipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
 MODULE_DESCRIPTION("ipmap type of IP sets");
 
-static int __init ip_set_ipmap_init(void)
-{
-       return ip_set_register_set_type(&ip_set_ipmap);
-}
-
-static void __exit ip_set_ipmap_fini(void)
-{
-       /* FIXME: possible race with ip_set_create() */
-       ip_set_unregister_set_type(&ip_set_ipmap);
-}
-
-module_init(ip_set_ipmap_init);
-module_exit(ip_set_ipmap_fini);
+REGISTER_MODULE(ipmap)
index 4e656cd6492731324a1afd572167fc0ce98590cc..1dd39c3323ea5990b4d60f9422954bdb4bfde67a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  *
  * 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
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/skbuff.h>
-#include <linux/version.h>
 #include <linux/jhash.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <linux/spinlock.h>
-#include <linux/vmalloc.h>
 #include <linux/random.h>
 
 #include <net/ip.h>
 
-#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_hashes.h>
 #include <linux/netfilter_ipv4/ip_set_ipporthash.h>
+#include <linux/netfilter_ipv4/ip_set_getport.h>
 
 static int limit = MAX_RANGE;
 
-/* We must handle non-linear skbs */
-static inline ip_set_ip_t
-get_port(const struct sk_buff *skb, u_int32_t flags)
-{
-       struct iphdr *iph = ip_hdr(skb);
-       u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
-
-       switch (iph->protocol) {
-       case IPPROTO_TCP: {
-               struct tcphdr tcph;
-               
-               /* See comments at tcp_match in ip_tables.c */
-               if (offset)
-                       return INVALID_PORT;
-
-               if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
-                       /* No choice either */
-                       return INVALID_PORT;
-               
-               return ntohs(flags & IPSET_SRC ?
-                            tcph.source : tcph.dest);
-           }
-       case IPPROTO_UDP: {
-               struct udphdr udph;
-
-               if (offset)
-                       return INVALID_PORT;
-
-               if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
-                       /* No choice either */
-                       return INVALID_PORT;
-               
-               return ntohs(flags & IPSET_SRC ?
-                            udph.source : udph.dest);
-           }
-       default:
-               return INVALID_PORT;
-       }
-}
-
-static inline __u32
-jhash_ip(const struct ip_set_ipporthash *map, uint16_t i, ip_set_ip_t ip)
-{
-       return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
-}
-
-#define HASH_IP(map, ip, port) (port + ((ip - ((map)->first_ip)) << 16))
-
 static inline __u32
-hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
-       ip_set_ip_t *hash_ip)
+ipporthash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
+             ip_set_ip_t ip, ip_set_ip_t port)
 {
        struct ip_set_ipporthash *map = set->data;
        __u32 id;
        u_int16_t i;
        ip_set_ip_t *elem;
 
-       *hash_ip = HASH_IP(map, ip, port);
+       *hash_ip = pack_ip_port(map, ip, port);
        DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
           set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
        
@@ -105,81 +55,45 @@ hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
 }
 
 static inline int
-__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
-        ip_set_ip_t *hash_ip)
+ipporthash_test(struct ip_set *set, ip_set_ip_t *hash_ip,
+               ip_set_ip_t ip, ip_set_ip_t port)
 {
        struct ip_set_ipporthash *map = set->data;
        
        if (ip < map->first_ip || ip > map->last_ip)
                return -ERANGE;
 
-       return (hash_id(set, ip, port, hash_ip) != UINT_MAX);
+       return (ipporthash_id(set, hash_ip, ip, port) != UINT_MAX);
 }
 
-static int
-testip(struct ip_set *set, const void *data, size_t size,
-       ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_ipporthash *req = data;
-
-       if (size != sizeof(struct ip_set_req_ipporthash)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_ipporthash),
-                             size);
-               return -EINVAL;
-       }
-       return __testip(set, req->ip, req->port, hash_ip);
-}
-
-static int
-testip_kernel(struct ip_set *set,
-             const struct sk_buff *skb,
-             ip_set_ip_t *hash_ip,
-             const u_int32_t *flags,
-             unsigned char index)
-{
-       ip_set_ip_t port;
-       int res;
-
-       if (flags[index+1] == 0)
+#define KADT_CONDITION                                         \
+       ip_set_ip_t port;                                       \
+                                                               \
+       if (flags[index+1] == 0)                                \
+               return 0;                                       \
+                                                               \
+       port = get_port(skb, flags[index+1]);                   \
+                                                               \
+       if (port == INVALID_PORT)                               \
                return 0;
-               
-       port = get_port(skb, flags[index+1]);
-
-       DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-          flags[index] & IPSET_SRC ? "SRC" : "DST",
-          NIPQUAD(ip_hdr(skb)->saddr),
-          NIPQUAD(ip_hdr(skb)->daddr));
-       DP("flag %s port %u",
-          flags[index+1] & IPSET_SRC ? "SRC" : "DST",
-          port);       
-       if (port == INVALID_PORT)
-               return 0;       
 
-       res =  __testip(set,
-                       ntohl(flags[index] & IPSET_SRC
-                                       ? ip_hdr(skb)->saddr
-                                       : ip_hdr(skb)->daddr),
-                       port,
-                       hash_ip);
-       return (res < 0 ? 0 : res);
-       
-}
+UADT(ipporthash, test, req->port)
+KADT(ipporthash, test, ipaddr, port)
 
 static inline int
-__add_haship(struct ip_set_ipporthash *map, ip_set_ip_t hash_ip)
+__ipporthash_add(struct ip_set_ipporthash *map, ip_set_ip_t *ip)
 {
        __u32 probe;
        u_int16_t i;
        ip_set_ip_t *elem;
 
        for (i = 0; i < map->probes; i++) {
-               probe = jhash_ip(map, i, hash_ip) % map->hashsize;
+               probe = jhash_ip(map, i, *ip) % map->hashsize;
                elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
-               if (*elem == hash_ip)
+               if (*elem == *ip)
                        return -EEXIST;
                if (!*elem) {
-                       *elem = hash_ip;
+                       *elem = *ip;
                        map->elements++;
                        return 0;
                }
@@ -189,143 +103,36 @@ __add_haship(struct ip_set_ipporthash *map, ip_set_ip_t hash_ip)
 }
 
 static inline int
-__addip(struct ip_set_ipporthash *map, ip_set_ip_t ip, ip_set_ip_t port,
-       ip_set_ip_t *hash_ip)
+ipporthash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
+              ip_set_ip_t ip, ip_set_ip_t port)
 {
+       struct ip_set_ipporthash *map = set->data;
        if (map->elements > limit)
                return -ERANGE;
        if (ip < map->first_ip || ip > map->last_ip)
                return -ERANGE;
 
-       *hash_ip = HASH_IP(map, ip, port);
+       *hash_ip = pack_ip_port(map, ip, port);
        
-       return __add_haship(map, *hash_ip);
-}
-
-static int
-addip(struct ip_set *set, const void *data, size_t size,
-        ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_ipporthash *req = data;
-
-       if (size != sizeof(struct ip_set_req_ipporthash)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_ipporthash),
-                             size);
-               return -EINVAL;
-       }
-       return __addip(set->data, req->ip, req->port, hash_ip);
+       return __ipporthash_add(map, hash_ip);
 }
 
-static int
-addip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       ip_set_ip_t port;
-
-       if (flags[index+1] == 0)
-               return -EINVAL;
-               
-       port = get_port(skb, flags[index+1]);
-
-       DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-          flags[index] & IPSET_SRC ? "SRC" : "DST",
-          NIPQUAD(ip_hdr(skb)->saddr),
-          NIPQUAD(ip_hdr(skb)->daddr));
-       DP("flag %s port %u",
-          flags[index+1] & IPSET_SRC ? "SRC" : "DST",
-          port);       
-       if (port == INVALID_PORT)
-               return -EINVAL; 
-
-       return __addip(set->data,
-                      ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                      port,
-                      hash_ip);
-}
+UADT(ipporthash, add, req->port)
+KADT(ipporthash, add, ipaddr, port)
 
-static int retry(struct ip_set *set)
+static inline void
+__ipporthash_retry(struct ip_set_ipporthash *tmp,
+                  struct ip_set_ipporthash *map)
 {
-       struct ip_set_ipporthash *map = set->data;
-       ip_set_ip_t *elem;
-       void *members;
-       u_int32_t i, hashsize = map->hashsize;
-       int res;
-       struct ip_set_ipporthash *tmp;
-       
-       if (map->resize == 0)
-               return -ERANGE;
-
-    again:
-       res = 0;
-       
-       /* Calculate new hash size */
-       hashsize += (hashsize * map->resize)/100;
-       if (hashsize == map->hashsize)
-               hashsize++;
-       
-       ip_set_printk("rehashing of set %s triggered: "
-                     "hashsize grows from %u to %u",
-                     set->name, map->hashsize, hashsize);
-
-       tmp = kmalloc(sizeof(struct ip_set_ipporthash)
-                     + map->probes * sizeof(uint32_t), GFP_ATOMIC);
-       if (!tmp) {
-               DP("out of memory for %d bytes",
-                  sizeof(struct ip_set_ipporthash)
-                  + map->probes * sizeof(uint32_t));
-               return -ENOMEM;
-       }
-       tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
-       if (!tmp->members) {
-               DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
-               kfree(tmp);
-               return -ENOMEM;
-       }
-       tmp->hashsize = hashsize;
-       tmp->elements = 0;
-       tmp->probes = map->probes;
-       tmp->resize = map->resize;
        tmp->first_ip = map->first_ip;
        tmp->last_ip = map->last_ip;
-       memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
-       
-       write_lock_bh(&set->lock);
-       map = set->data; /* Play safe */
-       for (i = 0; i < map->hashsize && res == 0; i++) {
-               elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);     
-               if (*elem)
-                       res = __add_haship(tmp, *elem);
-       }
-       if (res) {
-               /* Failure, try again */
-               write_unlock_bh(&set->lock);
-               harray_free(tmp->members);
-               kfree(tmp);
-               goto again;
-       }
-       
-       /* Success at resizing! */
-       members = map->members;
-
-       map->hashsize = tmp->hashsize;
-       map->members = tmp->members;
-       write_unlock_bh(&set->lock);
-
-       harray_free(members);
-       kfree(tmp);
-
-       return 0;
 }
 
+HASH_RETRY(ipporthash, ip_set_ip_t)
+
 static inline int
-__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
-       ip_set_ip_t *hash_ip)
+ipporthash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
+              ip_set_ip_t ip, ip_set_ip_t port)
 {
        struct ip_set_ipporthash *map = set->data;
        ip_set_ip_t id;
@@ -334,7 +141,7 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
        if (ip < map->first_ip || ip > map->last_ip)
                return -ERANGE;
 
-       id = hash_id(set, ip, port, hash_ip);
+       id = ipporthash_id(set, hash_ip, ip, port);
 
        if (id == UINT_MAX)
                return -EEXIST;
@@ -346,171 +153,40 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
        return 0;
 }
 
-static int
-delip(struct ip_set *set, const void *data, size_t size,
-        ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_ipporthash *req = data;
-
-       if (size != sizeof(struct ip_set_req_ipporthash)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_ipporthash),
-                             size);
-               return -EINVAL;
-       }
-       return __delip(set, req->ip, req->port, hash_ip);
-}
-
-static int
-delip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       ip_set_ip_t port;
-
-       if (flags[index+1] == 0)
-               return -EINVAL;
-               
-       port = get_port(skb, flags[index+1]);
-
-       DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-          flags[index] & IPSET_SRC ? "SRC" : "DST",
-          NIPQUAD(ip_hdr(skb)->saddr),
-          NIPQUAD(ip_hdr(skb)->daddr));
-       DP("flag %s port %u",
-          flags[index+1] & IPSET_SRC ? "SRC" : "DST",
-          port);       
-       if (port == INVALID_PORT)
-               return -EINVAL; 
-
-       return __delip(set,
-                      ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                      port,
-                      hash_ip);
-}
+UADT(ipporthash, del, req->port)
+KADT(ipporthash, del, ipaddr, port)
 
-static int create(struct ip_set *set, const void *data, size_t size)
+static inline int
+__ipporthash_create(const struct ip_set_req_ipporthash_create *req,
+                   struct ip_set_ipporthash *map)
 {
-       const struct ip_set_req_ipporthash_create *req = data;
-       struct ip_set_ipporthash *map;
-       uint16_t i;
-
-       if (size != sizeof(struct ip_set_req_ipporthash_create)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                              sizeof(struct ip_set_req_ipporthash_create),
-                              size);
-               return -EINVAL;
-       }
-
-       if (req->hashsize < 1) {
-               ip_set_printk("hashsize too small");
+       if (req->to - req->from > MAX_RANGE) {
+               ip_set_printk("range too big, %d elements (max %d)",
+                             req->to - req->from + 1, MAX_RANGE+1);
                return -ENOEXEC;
        }
-
-       if (req->probes < 1) {
-               ip_set_printk("probes too small");
-               return -ENOEXEC;
-       }
-
-       map = kmalloc(sizeof(struct ip_set_ipporthash)
-                     + req->probes * sizeof(uint32_t), GFP_KERNEL);
-       if (!map) {
-               DP("out of memory for %d bytes",
-                  sizeof(struct ip_set_ipporthash)
-                  + req->probes * sizeof(uint32_t));
-               return -ENOMEM;
-       }
-       for (i = 0; i < req->probes; i++)
-               get_random_bytes(((uint32_t *) map->initval)+i, 4);
-       map->elements = 0;
-       map->hashsize = req->hashsize;
-       map->probes = req->probes;
-       map->resize = req->resize;
        map->first_ip = req->from;
        map->last_ip = req->to;
-       map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
-       if (!map->members) {
-               DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
-               kfree(map);
-               return -ENOMEM;
-       }
-
-       set->data = map;
        return 0;
 }
 
-static void destroy(struct ip_set *set)
-{
-       struct ip_set_ipporthash *map = set->data;
-
-       harray_free(map->members);
-       kfree(map);
+HASH_CREATE(ipporthash, ip_set_ip_t)
+HASH_DESTROY(ipporthash)
+HASH_FLUSH(ipporthash, ip_set_ip_t)
 
-       set->data = NULL;
-}
-
-static void flush(struct ip_set *set)
+static inline void
+__ipporthash_list_header(const struct ip_set_ipporthash *map,
+                        struct ip_set_req_ipporthash_create *header)
 {
-       struct ip_set_ipporthash *map = set->data;
-       harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
-       map->elements = 0;
-}
-
-static void list_header(const struct ip_set *set, void *data)
-{
-       const struct ip_set_ipporthash *map = set->data;
-       struct ip_set_req_ipporthash_create *header = data;
-
-       header->hashsize = map->hashsize;
-       header->probes = map->probes;
-       header->resize = map->resize;
        header->from = map->first_ip;
        header->to = map->last_ip;
 }
 
-static int list_members_size(const struct ip_set *set)
-{
-       const struct ip_set_ipporthash *map = set->data;
+HASH_LIST_HEADER(ipporthash)
+HASH_LIST_MEMBERS_SIZE(ipporthash, ip_set_ip_t)
+HASH_LIST_MEMBERS(ipporthash, ip_set_ip_t)
 
-       return (map->hashsize * sizeof(ip_set_ip_t));
-}
-
-static void list_members(const struct ip_set *set, void *data)
-{
-       const struct ip_set_ipporthash *map = set->data;
-       ip_set_ip_t i, *elem;
-
-       for (i = 0; i < map->hashsize; i++) {
-               elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);     
-               ((ip_set_ip_t *)data)[i] = *elem;
-       }
-}
-
-static struct ip_set_type ip_set_ipporthash = {
-       .typename               = SETTYPE_NAME,
-       .features               = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_DATA_DOUBLE,
-       .protocol_version       = IP_SET_PROTOCOL_VERSION,
-       .create                 = &create,
-       .destroy                = &destroy,
-       .flush                  = &flush,
-       .reqsize                = sizeof(struct ip_set_req_ipporthash),
-       .addip                  = &addip,
-       .addip_kernel           = &addip_kernel,
-       .retry                  = &retry,
-       .delip                  = &delip,
-       .delip_kernel           = &delip_kernel,
-       .testip                 = &testip,
-       .testip_kernel          = &testip_kernel,
-       .header_size            = sizeof(struct ip_set_req_ipporthash_create),
-       .list_header            = &list_header,
-       .list_members_size      = &list_members_size,
-       .list_members           = &list_members,
-       .me                     = THIS_MODULE,
-};
+IP_SET_RTYPE(ipporthash, IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_DATA_DOUBLE)
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -518,17 +194,4 @@ MODULE_DESCRIPTION("ipporthash type of IP sets");
 module_param(limit, int, 0600);
 MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
 
-static int __init ip_set_ipporthash_init(void)
-{
-       init_max_page_size();
-       return ip_set_register_set_type(&ip_set_ipporthash);
-}
-
-static void __exit ip_set_ipporthash_fini(void)
-{
-       /* FIXME: possible race with ip_set_create() */
-       ip_set_unregister_set_type(&ip_set_ipporthash);
-}
-
-module_init(ip_set_ipporthash_init);
-module_exit(ip_set_ipporthash_fini);
+REGISTER_MODULE(ipporthash)
diff --git a/kernel/ip_set_ipportiphash.c b/kernel/ip_set_ipportiphash.c
new file mode 100644 (file)
index 0000000..1755c57
--- /dev/null
@@ -0,0 +1,212 @@
+/* Copyright (C) 2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * 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.
+ */
+
+/* Kernel module implementing an ip+port+ip hash set */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
+#include <linux/jhash.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+
+#include <net/ip.h>
+
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_hashes.h>
+#include <linux/netfilter_ipv4/ip_set_ipportiphash.h>
+#include <linux/netfilter_ipv4/ip_set_getport.h>
+
+static int limit = MAX_RANGE;
+
+#define jhash_ip2(map, i, ipport, ip1)         \
+       jhash_2words(ipport, ip1, *(map->initval + i))
+
+static inline __u32
+ipportiphash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
+               ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
+{
+       struct ip_set_ipportiphash *map = set->data;
+       __u32 id;
+       u_int16_t i;
+       struct ipportip *elem;
+
+       *hash_ip = pack_ip_port(map, ip, port);
+       DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
+          set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
+       
+       for (i = 0; i < map->probes; i++) {
+               id = jhash_ip2(map, i, *hash_ip, ip1) % map->hashsize;
+               DP("hash key: %u", id);
+               elem = HARRAY_ELEM(map->members, struct ipportip *, id);
+               if (elem->ip == *hash_ip && elem->ip1 == ip1)
+                       return id;
+               /* No shortcut at testing - there can be deleted
+                * entries. */
+       }
+       return UINT_MAX;
+}
+
+static inline int
+ipportiphash_test(struct ip_set *set, ip_set_ip_t *hash_ip,
+                 ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
+{
+       struct ip_set_ipportiphash *map = set->data;
+       
+       if (ip < map->first_ip || ip > map->last_ip)
+               return -ERANGE;
+
+       return (ipportiphash_id(set, hash_ip, ip, port, ip1) != UINT_MAX);
+}
+
+#define KADT_CONDITION                                         \
+       ip_set_ip_t port, ip1;                                  \
+                                                               \
+       if (flags[index+2] == 0)                                \
+               return 0;                                       \
+                                                               \
+       port = get_port(skb, flags[index+1]);                   \
+       ip1 = ipaddr(skb, flags[index+2]);                      \
+                                                               \
+       if (port == INVALID_PORT)                               \
+               return 0;
+
+UADT(ipportiphash, test, req->port, req->ip1)
+KADT(ipportiphash, test, ipaddr, port, ip1)
+
+static inline int
+__ipportip_add(struct ip_set_ipportiphash *map,
+              ip_set_ip_t hash_ip, ip_set_ip_t ip1)
+{
+       __u32 probe;
+       u_int16_t i;
+       struct ipportip *elem;
+
+       for (i = 0; i < map->probes; i++) {
+               probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize;
+               elem = HARRAY_ELEM(map->members, struct ipportip *, probe);
+               if (elem->ip == hash_ip && elem->ip1 == ip1)
+                       return -EEXIST;
+               if (!(elem->ip || elem->ip1)) {
+                       elem->ip = hash_ip;
+                       elem->ip1 = ip1;
+                       map->elements++;
+                       return 0;
+               }
+       }
+       /* Trigger rehashing */
+       return -EAGAIN;
+}
+
+static inline int
+__ipportiphash_add(struct ip_set_ipportiphash *map,
+                  struct ipportip *elem)
+{
+       return __ipportip_add(map, elem->ip, elem->ip1);
+}
+
+static inline int
+ipportiphash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
+                ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
+{
+       struct ip_set_ipportiphash *map = set->data;
+       
+       if (map->elements > limit)
+               return -ERANGE;
+       if (ip < map->first_ip || ip > map->last_ip)
+               return -ERANGE;
+
+       *hash_ip = pack_ip_port(map, ip, port);
+       
+       return __ipportip_add(map, *hash_ip, ip1);
+}
+
+UADT(ipportiphash, add, req->port, req->ip1)
+KADT(ipportiphash, add, ipaddr, port, ip1)
+
+static inline void
+__ipportiphash_retry(struct ip_set_ipportiphash *tmp,
+                    struct ip_set_ipportiphash *map)
+{
+       tmp->first_ip = map->first_ip;
+       tmp->last_ip = map->last_ip;
+}
+
+HASH_RETRY2(ipportiphash, struct ipportip)
+
+static inline int
+ipportiphash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
+              ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
+{
+       struct ip_set_ipportiphash *map = set->data;
+       ip_set_ip_t id;
+       struct ipportip *elem;
+
+       if (ip < map->first_ip || ip > map->last_ip)
+               return -ERANGE;
+
+       id = ipportiphash_id(set, hash_ip, ip, port, ip1);
+
+       if (id == UINT_MAX)
+               return -EEXIST;
+               
+       elem = HARRAY_ELEM(map->members, struct ipportip *, id);
+       elem->ip = elem->ip1 = 0;
+       map->elements--;
+
+       return 0;
+}
+
+UADT(ipportiphash, del, req->port, req->ip1)
+KADT(ipportiphash, del, ipaddr, port, ip1)
+
+static inline int
+__ipportiphash_create(const struct ip_set_req_ipportiphash_create *req,
+                     struct ip_set_ipportiphash *map)
+{
+       if (req->to - req->from > MAX_RANGE) {
+               ip_set_printk("range too big, %d elements (max %d)",
+                             req->to - req->from + 1, MAX_RANGE+1);
+               return -ENOEXEC;
+       }
+       map->first_ip = req->from;
+       map->last_ip = req->to;
+       return 0;
+}
+
+HASH_CREATE(ipportiphash, struct ipportip)
+HASH_DESTROY(ipportiphash)
+HASH_FLUSH(ipportiphash, struct ipportip)
+
+static inline void
+__ipportiphash_list_header(const struct ip_set_ipportiphash *map,
+                          struct ip_set_req_ipportiphash_create *header)
+{
+       header->from = map->first_ip;
+       header->to = map->last_ip;
+}
+
+HASH_LIST_HEADER(ipportiphash)
+HASH_LIST_MEMBERS_SIZE(ipportiphash, struct ipportip)
+HASH_LIST_MEMBERS_MEMCPY(ipportiphash, struct ipportip)
+
+IP_SET_RTYPE(ipportiphash, IPSET_TYPE_IP | IPSET_TYPE_PORT
+                          | IPSET_TYPE_IP1 | IPSET_DATA_TRIPLE)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("ipportiphash type of IP sets");
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
+REGISTER_MODULE(ipportiphash)
diff --git a/kernel/ip_set_ipportnethash.c b/kernel/ip_set_ipportnethash.c
new file mode 100644 (file)
index 0000000..3783bb8
--- /dev/null
@@ -0,0 +1,299 @@
+/* Copyright (C) 2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * 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.
+ */
+
+/* Kernel module implementing an ip+port+net hash set */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
+#include <linux/jhash.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+
+#include <net/ip.h>
+
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_hashes.h>
+#include <linux/netfilter_ipv4/ip_set_ipportnethash.h>
+#include <linux/netfilter_ipv4/ip_set_getport.h>
+
+static int limit = MAX_RANGE;
+
+#define jhash_ip2(map, i, ipport, ip1)         \
+       jhash_2words(ipport, ip1, *(map->initval + i))
+
+static inline __u32
+ipportnethash_id_cidr(struct ip_set *set, ip_set_ip_t *hash_ip,
+                     ip_set_ip_t ip, ip_set_ip_t port,
+                     ip_set_ip_t ip1, uint8_t cidr)
+{
+       struct ip_set_ipportnethash *map = set->data;
+       __u32 id;
+       u_int16_t i;
+       struct ipportip *elem;
+
+       *hash_ip = pack_ip_port(map, ip, port);
+       DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
+          set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
+       ip1 = pack_ip_cidr(ip1, cidr);
+       
+       for (i = 0; i < map->probes; i++) {
+               id = jhash_ip2(map, i, *hash_ip, ip1) % map->hashsize;
+               DP("hash key: %u", id);
+               elem = HARRAY_ELEM(map->members, struct ipportip *, id);
+               if (elem->ip == *hash_ip && elem->ip1 == ip1)
+                       return id;
+               /* No shortcut at testing - there can be deleted
+                * entries. */
+       }
+       return UINT_MAX;
+}
+
+static inline __u32
+ipportnethash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
+                ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
+{
+       struct ip_set_ipportnethash *map = set->data;
+       __u32 id = UINT_MAX;
+       int i;
+
+       for (i = 0; i < 30 && map->cidr[i]; i++) {
+               id = ipportnethash_id_cidr(set, hash_ip, ip, port, ip1, 
+                                          map->cidr[i]);
+               if (id != UINT_MAX)
+                       break;
+       }
+       return id;
+}
+
+static inline int
+ipportnethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip,
+                       ip_set_ip_t ip, ip_set_ip_t port,
+                       ip_set_ip_t ip1, uint8_t cidr)
+{
+       struct ip_set_ipportnethash *map = set->data;
+       
+       if (ip < map->first_ip || ip > map->last_ip)
+               return -ERANGE;
+
+       return (ipportnethash_id_cidr(set, hash_ip, ip, port, ip1,
+                                     cidr) != UINT_MAX);
+}
+
+static inline int
+ipportnethash_test(struct ip_set *set, ip_set_ip_t *hash_ip,
+                 ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
+{
+       struct ip_set_ipportnethash *map = set->data;
+       
+       if (ip < map->first_ip || ip > map->last_ip)
+               return -ERANGE;
+
+       return (ipportnethash_id(set, hash_ip, ip, port, ip1) != UINT_MAX);
+}
+
+static int
+ipportnethash_utest(struct ip_set *set, const void *data, size_t size,
+                   ip_set_ip_t *hash_ip)
+{
+       const struct ip_set_req_ipportnethash *req = data;
+
+       if (req->cidr <= 0 || req->cidr > 32)
+               return -EINVAL;
+       return (req->cidr == 32 
+               ? ipportnethash_test(set, hash_ip, req->ip, req->port,
+                                    req->ip1)
+               : ipportnethash_test_cidr(set, hash_ip, req->ip, req->port,
+                                         req->ip1, req->cidr));
+}
+
+#define KADT_CONDITION                                         \
+       ip_set_ip_t port, ip1;                                  \
+                                                               \
+       if (flags[index+2] == 0)                                \
+               return 0;                                       \
+                                                               \
+       port = get_port(skb, flags[index+1]);                   \
+       ip1 = ipaddr(skb, flags[index+2]);                      \
+                                                               \
+       if (port == INVALID_PORT)                               \
+               return 0;
+
+KADT(ipportnethash, test, ipaddr, port, ip1)
+
+static inline int
+__ipportnet_add(struct ip_set_ipportnethash *map,
+               ip_set_ip_t hash_ip, ip_set_ip_t ip1)
+{
+       __u32 probe;
+       u_int16_t i;
+       struct ipportip *elem;
+
+       for (i = 0; i < map->probes; i++) {
+               probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize;
+               elem = HARRAY_ELEM(map->members, struct ipportip *, probe);
+               if (elem->ip == hash_ip && elem->ip1 == ip1)
+                       return -EEXIST;
+               if (!(elem->ip || elem->ip1)) {
+                       elem->ip = hash_ip;
+                       elem->ip1 = ip1;
+                       map->elements++;
+                       return 0;
+               }
+       }
+       /* Trigger rehashing */
+       return -EAGAIN;
+}
+
+static inline int
+__ipportnethash_add(struct ip_set_ipportnethash *map,
+                   struct ipportip *elem)
+{
+       return __ipportnet_add(map, elem->ip, elem->ip1);
+}
+
+static inline int
+ipportnethash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
+                ip_set_ip_t ip, ip_set_ip_t port,
+                ip_set_ip_t ip1, uint8_t cidr)
+{
+       struct ip_set_ipportnethash *map = set->data;
+       struct ipportip;
+       int ret;
+       
+       if (map->elements > limit)
+               return -ERANGE;
+       if (ip < map->first_ip || ip > map->last_ip)
+               return -ERANGE;
+       if (cidr <= 0 || cidr >= 32)
+               return -EINVAL;
+       if (map->nets[cidr-1] == UINT16_MAX)
+               return -ERANGE;
+
+       *hash_ip = pack_ip_port(map, ip, port);
+       
+       ret =__ipportnet_add(map, *hash_ip, pack_ip_cidr(ip1, cidr));
+       if (ret == 0) {
+               if (!map->nets[cidr-1]++)
+                       add_cidr_size(map->cidr, cidr);
+               map->elements++;
+       }
+       return ret;
+}
+
+#undef KADT_CONDITION
+#define KADT_CONDITION                                                 \
+       struct ip_set_ipportnethash *map = set->data;                   \
+       uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31;                \
+       ip_set_ip_t port, ip1;                                          \
+                                                                       \
+       if (flags[index+2] == 0)                                        \
+               return 0;                                               \
+                                                                       \
+       port = get_port(skb, flags[index+1]);                           \
+       ip1 = ipaddr(skb, flags[index+2]);                              \
+                                                                       \
+       if (port == INVALID_PORT)                                       \
+               return 0;
+
+UADT(ipportnethash, add, req->port, req->ip1, req->cidr)
+KADT(ipportnethash, add, ipaddr, port, ip1, cidr)
+
+static inline void
+__ipportnethash_retry(struct ip_set_ipportnethash *tmp,
+                     struct ip_set_ipportnethash *map)
+{
+       tmp->first_ip = map->first_ip;
+       tmp->last_ip = map->last_ip;
+       memcpy(tmp->cidr, map->cidr, 30 * sizeof(uint8_t));
+       memcpy(tmp->nets, map->nets, 30 * sizeof(uint16_t));
+}
+
+HASH_RETRY2(ipportnethash, struct ipportip)
+
+static inline int
+ipportnethash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
+                 ip_set_ip_t ip, ip_set_ip_t port,
+                 ip_set_ip_t ip1, uint8_t cidr)
+{
+       struct ip_set_ipportnethash *map = set->data;
+       ip_set_ip_t id;
+       struct ipportip *elem;
+
+       if (ip < map->first_ip || ip > map->last_ip)
+               return -ERANGE;
+       if (!ip)
+               return -ERANGE;
+       if (cidr <= 0 || cidr >= 32)
+               return -EINVAL; 
+
+       id = ipportnethash_id_cidr(set, hash_ip, ip, port, ip1, cidr);
+
+       if (id == UINT_MAX)
+               return -EEXIST;
+               
+       elem = HARRAY_ELEM(map->members, struct ipportip *, id);
+       elem->ip = elem->ip1 = 0;
+       map->elements--;
+       if (!map->nets[cidr-1]--)
+               del_cidr_size(map->cidr, cidr);
+
+       return 0;
+}
+
+UADT(ipportnethash, del, req->port, req->ip1, req->cidr)
+KADT(ipportnethash, del, ipaddr, port, ip1, cidr)
+
+static inline int
+__ipportnethash_create(const struct ip_set_req_ipportnethash_create *req,
+                      struct ip_set_ipportnethash *map)
+{
+       if (req->to - req->from > MAX_RANGE) {
+               ip_set_printk("range too big, %d elements (max %d)",
+                             req->to - req->from + 1, MAX_RANGE+1);
+               return -ENOEXEC;
+       }
+       map->first_ip = req->from;
+       map->last_ip = req->to;
+       memset(map->cidr, 0, 30 * sizeof(uint8_t));
+       memset(map->nets, 0, 30 * sizeof(uint16_t));
+       return 0;
+}
+
+HASH_CREATE(ipportnethash, struct ipportip)
+HASH_DESTROY(ipportnethash)
+HASH_FLUSH_CIDR(ipportnethash, struct ipportip);
+
+static inline void
+__ipportnethash_list_header(const struct ip_set_ipportnethash *map,
+                           struct ip_set_req_ipportnethash_create *header)
+{
+       header->from = map->first_ip;
+       header->to = map->last_ip;
+}
+
+HASH_LIST_HEADER(ipportnethash)
+
+HASH_LIST_MEMBERS_SIZE(ipportnethash, struct ipportip)
+HASH_LIST_MEMBERS_MEMCPY(ipportnethash, struct ipportip)
+
+IP_SET_RTYPE(ipportnethash, IPSET_TYPE_IP | IPSET_TYPE_PORT
+                           | IPSET_TYPE_IP1 | IPSET_DATA_TRIPLE)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("ipportnethash type of IP sets");
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
+REGISTER_MODULE(ipportnethash)
index 2e0a4062991c22e5b23f500b04aa28ae2fcf3c80..22a94d127716f2286f3d90026c03659a66463684 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+/* Copyright (C) 2005-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  *
  * 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
@@ -7,20 +7,19 @@
 
 /* Kernel module implementing an IP set type: the iptree type */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/ip.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <linux/spinlock.h>
 
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_bitmaps.h>
 #include <linux/netfilter_ipv4/ip_set_iptree.h>
 
 static int limit = MAX_RANGE;
@@ -61,7 +60,7 @@ static __KMEM_CACHE_T__ *leaf_cachep;
 } while (0)
 
 static inline int
-__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+iptree_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
        struct ip_set_iptree *map = set->data;
        struct ip_set_iptreeb *btree;
@@ -84,42 +83,10 @@ __testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
                   || time_after(dtree->expires[d], jiffies));
 }
 
-static int
-testip(struct ip_set *set, const void *data, size_t size,
-       ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_iptree *req = data;
+#define KADT_CONDITION
 
-       if (size != sizeof(struct ip_set_req_iptree)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_iptree),
-                             size);
-               return -EINVAL;
-       }
-       return __testip(set, req->ip, hash_ip);
-}
-
-static int
-testip_kernel(struct ip_set *set,
-             const struct sk_buff *skb,
-             ip_set_ip_t *hash_ip,
-             const u_int32_t *flags,
-             unsigned char index)
-{
-       int res;
-       
-       DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-          flags[index] & IPSET_SRC ? "SRC" : "DST",
-          NIPQUAD(ip_hdr(skb)->saddr),
-          NIPQUAD(ip_hdr(skb)->daddr));
-
-       res =  __testip(set,
-                       ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                       hash_ip);
-       return (res < 0 ? 0 : res);
-}
+UADT(iptree, test)
+KADT(iptree, test, ipaddr)
 
 #define ADDIP_WALK(map, elem, branch, type, cachep) do {       \
        if ((map)->tree[elem]) {                                \
@@ -137,8 +104,8 @@ testip_kernel(struct ip_set *set,
 } while (0)    
 
 static inline int
-__addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
-       ip_set_ip_t *hash_ip)
+iptree_add(struct ip_set *set, ip_set_ip_t *hash_ip,
+          ip_set_ip_t ip, unsigned int timeout)
 {
        struct ip_set_iptree *map = set->data;
        struct ip_set_iptreeb *btree;
@@ -161,6 +128,8 @@ __addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
        if (dtree->expires[d]
            && (!map->timeout || time_after(dtree->expires[d], jiffies)))
                ret = -EEXIST;
+       if (map->timeout && timeout == 0)
+               timeout = map->timeout;
        dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1;
        /* Lottery: I won! */
        if (dtree->expires[d] == 0)
@@ -171,41 +140,8 @@ __addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
        return ret;
 }
 
-static int
-addip(struct ip_set *set, const void *data, size_t size,
-      ip_set_ip_t *hash_ip)
-{
-       struct ip_set_iptree *map = set->data;
-       const struct ip_set_req_iptree *req = data;
-
-       if (size != sizeof(struct ip_set_req_iptree)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_iptree),
-                             size);
-               return -EINVAL;
-       }
-       DP("%u.%u.%u.%u %u", HIPQUAD(req->ip), req->timeout);
-       return __addip(set, req->ip,
-                      req->timeout ? req->timeout : map->timeout,
-                      hash_ip);
-}
-
-static int
-addip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       struct ip_set_iptree *map = set->data;
-
-       return __addip(set,
-                      ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                      map->timeout,
-                      hash_ip);
-}
+UADT(iptree, add, req->timeout)
+KADT(iptree, add, ipaddr, 0)
 
 #define DELIP_WALK(map, elem, branch) do {     \
        if ((map)->tree[elem]) {                \
@@ -215,7 +151,7 @@ addip_kernel(struct ip_set *set,
 } while (0)
 
 static inline int
-__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+iptree_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
        struct ip_set_iptree *map = set->data;
        struct ip_set_iptreeb *btree;
@@ -240,34 +176,8 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
        return -EEXIST;
 }
 
-static int
-delip(struct ip_set *set, const void *data, size_t size,
-      ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_iptree *req = data;
-
-       if (size != sizeof(struct ip_set_req_iptree)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_iptree),
-                             size);
-               return -EINVAL;
-       }
-       return __delip(set, req->ip, hash_ip);
-}
-
-static int
-delip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       return __delip(set,
-                      ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                      hash_ip);
-}
+UADT(iptree, del)
+KADT(iptree, del, ipaddr)
 
 #define LOOP_WALK_BEGIN(map, i, branch) \
        for (i = 0; i < 256; i++) {     \
@@ -277,7 +187,8 @@ delip_kernel(struct ip_set *set,
 
 #define LOOP_WALK_END }
 
-static void ip_tree_gc(unsigned long ul_set)
+static void
+ip_tree_gc(unsigned long ul_set)
 {
        struct ip_set *set = (struct ip_set *) ul_set;
        struct ip_set_iptree *map = set->data;
@@ -347,7 +258,8 @@ static void ip_tree_gc(unsigned long ul_set)
        add_timer(&map->gc);
 }
 
-static inline void init_gc_timer(struct ip_set *set)
+static inline void
+init_gc_timer(struct ip_set *set)
 {
        struct ip_set_iptree *map = set->data;
 
@@ -362,7 +274,8 @@ static inline void init_gc_timer(struct ip_set *set)
        add_timer(&map->gc);
 }
 
-static int create(struct ip_set *set, const void *data, size_t size)
+static int
+iptree_create(struct ip_set *set, const void *data, size_t size)
 {
        const struct ip_set_req_iptree_create *req = data;
        struct ip_set_iptree *map;
@@ -390,7 +303,8 @@ static int create(struct ip_set *set, const void *data, size_t size)
        return 0;
 }
 
-static void __flush(struct ip_set_iptree *map)
+static inline void
+__flush(struct ip_set_iptree *map)
 {
        struct ip_set_iptreeb *btree;
        struct ip_set_iptreec *ctree;
@@ -409,7 +323,8 @@ static void __flush(struct ip_set_iptree *map)
        map->elements = 0;
 }
 
-static void destroy(struct ip_set *set)
+static void
+iptree_destroy(struct ip_set *set)
 {
        struct ip_set_iptree *map = set->data;
 
@@ -421,7 +336,8 @@ static void destroy(struct ip_set *set)
        set->data = NULL;
 }
 
-static void flush(struct ip_set *set)
+static void
+iptree_flush(struct ip_set *set)
 {
        struct ip_set_iptree *map = set->data;
        unsigned int timeout = map->timeout;
@@ -436,7 +352,8 @@ static void flush(struct ip_set *set)
        init_gc_timer(set);
 }
 
-static void list_header(const struct ip_set *set, void *data)
+static void
+iptree_list_header(const struct ip_set *set, void *data)
 {
        const struct ip_set_iptree *map = set->data;
        struct ip_set_req_iptree_create *header = data;
@@ -444,7 +361,8 @@ static void list_header(const struct ip_set *set, void *data)
        header->timeout = map->timeout;
 }
 
-static int list_members_size(const struct ip_set *set)
+static int
+iptree_list_members_size(const struct ip_set *set)
 {
        const struct ip_set_iptree *map = set->data;
        struct ip_set_iptreeb *btree;
@@ -469,7 +387,8 @@ static int list_members_size(const struct ip_set *set)
        return (count * sizeof(struct ip_set_req_iptree));
 }
 
-static void list_members(const struct ip_set *set, void *data)
+static void
+iptree_list_members(const struct ip_set *set, void *data)
 {
        const struct ip_set_iptree *map = set->data;
        struct ip_set_iptreeb *btree;
@@ -497,26 +416,7 @@ static void list_members(const struct ip_set *set, void *data)
        LOOP_WALK_END;
 }
 
-static struct ip_set_type ip_set_iptree = {
-       .typename               = SETTYPE_NAME,
-       .features               = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
-       .protocol_version       = IP_SET_PROTOCOL_VERSION,
-       .create                 = &create,
-       .destroy                = &destroy,
-       .flush                  = &flush,
-       .reqsize                = sizeof(struct ip_set_req_iptree),
-       .addip                  = &addip,
-       .addip_kernel           = &addip_kernel,
-       .delip                  = &delip,
-       .delip_kernel           = &delip_kernel,
-       .testip                 = &testip,
-       .testip_kernel          = &testip_kernel,
-       .header_size            = sizeof(struct ip_set_req_iptree_create),
-       .list_header            = &list_header,
-       .list_members_size      = &list_members_size,
-       .list_members           = &list_members,
-       .me                     = THIS_MODULE,
-};
+IP_SET_TYPE(iptree, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
index dedf8a4ecec0a5d0b1bd98a2a7fcf2c3a438925f..4a13e4fc968cf6e2e30c6d76a8571b312340af9a 100644 (file)
  * index to find the bitmap and the last octet is used as the bit number.
  */
 
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/ip.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <linux/spinlock.h>
 
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_bitmaps.h>
 #include <linux/netfilter_ipv4/ip_set_iptreemap.h>
 
 #define IPTREEMAP_DEFAULT_GC_TIME (5 * 60)
@@ -250,7 +249,7 @@ free_b(struct ip_set_iptreemap_b *map)
 }
 
 static inline int
-__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+iptreemap_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
        struct ip_set_iptreemap *map = set->data;
        struct ip_set_iptreemap_b *btree;
@@ -269,35 +268,13 @@ __testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
        return !!test_bit(d, (void *) dtree->bitmap);
 }
 
-static int
-testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_iptreemap *req = data;
-
-       if (size != sizeof(struct ip_set_req_iptreemap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
-               return -EINVAL;
-       }
-
-       return __testip(set, req->start, hash_ip);
-}
-
-static int
-testip_kernel(struct ip_set *set, const struct sk_buff *skb, ip_set_ip_t *hash_ip, const u_int32_t *flags, unsigned char index)
-{
-       int res;
-
-       res = __testip(set,
-                      ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                      hash_ip);
+#define KADT_CONDITION
 
-       return (res < 0 ? 0 : res);
-}
+UADT(iptreemap, test)
+KADT(iptreemap, test, ipaddr)
 
 static inline int
-__addip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+__addip_single(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
        struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
        struct ip_set_iptreemap_b *btree;
@@ -322,7 +299,8 @@ __addip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
 }
 
 static inline int
-__addip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_t *hash_ip)
+iptreemap_add(struct ip_set *set, ip_set_ip_t *hash_ip,
+             ip_set_ip_t start, ip_set_ip_t end)
 {
        struct ip_set_iptreemap *map = set->data;
        struct ip_set_iptreemap_b *btree;
@@ -333,7 +311,7 @@ __addip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_
        unsigned char a2, b2, c2, d2;
 
        if (start == end)
-               return __addip_single(set, start, hash_ip);
+               return __addip_single(set, hash_ip, start);
 
        *hash_ip = start;
 
@@ -354,32 +332,12 @@ __addip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_
        return 0;
 }
 
-static int
-addip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_iptreemap *req = data;
-
-       if (size != sizeof(struct ip_set_req_iptreemap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
-               return -EINVAL;
-       }
-
-       return __addip_range(set, min(req->start, req->end), max(req->start, req->end), hash_ip);
-}
-
-static int
-addip_kernel(struct ip_set *set, const struct sk_buff *skb, ip_set_ip_t *hash_ip, const u_int32_t *flags, unsigned char index)
-{
-
-       return __addip_single(set,
-                       ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                       hash_ip);
-}
+UADT0(iptreemap, add, min(req->ip, req->end), max(req->ip, req->end))
+KADT(iptreemap, add, ipaddr, ip)
 
 static inline int
-__delip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip, unsigned int __nocast flags)
+__delip_single(struct ip_set *set, ip_set_ip_t *hash_ip,
+              ip_set_ip_t ip, unsigned int __nocast flags)
 {
        struct ip_set_iptreemap *map = set->data;
        struct ip_set_iptreemap_b *btree;
@@ -404,7 +362,8 @@ __delip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip, unsigne
 }
 
 static inline int
-__delip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_t *hash_ip, unsigned int __nocast flags)
+iptreemap_del(struct ip_set *set, ip_set_ip_t *hash_ip,
+             ip_set_ip_t start, ip_set_ip_t end, unsigned int __nocast flags)
 {
        struct ip_set_iptreemap *map = set->data;
        struct ip_set_iptreemap_b *btree;
@@ -415,7 +374,7 @@ __delip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_
        unsigned char a2, b2, c2, d2;
 
        if (start == end)
-               return __delip_single(set, start, hash_ip, flags);
+               return __delip_single(set, hash_ip, start, flags);
 
        *hash_ip = start;
 
@@ -436,29 +395,8 @@ __delip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_
        return 0;
 }
 
-static int
-delip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_iptreemap *req = data;
-
-       if (size != sizeof(struct ip_set_req_iptreemap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
-               return -EINVAL;
-       }
-
-       return __delip_range(set, min(req->start, req->end), max(req->start, req->end), hash_ip, GFP_KERNEL);
-}
-
-static int
-delip_kernel(struct ip_set *set, const struct sk_buff *skb, ip_set_ip_t *hash_ip, const u_int32_t *flags, unsigned char index)
-{
-       return __delip_single(set,
-                       ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                       hash_ip,
-                       GFP_ATOMIC);
-}
+UADT0(iptreemap, del, min(req->ip, req->end), max(req->ip, req->end), GFP_KERNEL)
+KADT(iptreemap, del, ipaddr, ip, GFP_ATOMIC)
 
 /* Check the status of the bitmap
  * -1 == all bits cleared
@@ -530,16 +468,12 @@ init_gc_timer(struct ip_set *set)
        add_timer(&map->gc);
 }
 
-static int create(struct ip_set *set, const void *data, size_t size)
+static int
+iptreemap_create(struct ip_set *set, const void *data, size_t size)
 {
        const struct ip_set_req_iptreemap_create *req = data;
        struct ip_set_iptreemap *map;
 
-       if (size != sizeof(struct ip_set_req_iptreemap_create)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap_create), size);
-               return -EINVAL;
-       }
-
        map = kzalloc(sizeof(*map), GFP_KERNEL);
        if (!map)
                return -ENOMEM;
@@ -552,7 +486,8 @@ static int create(struct ip_set *set, const void *data, size_t size)
        return 0;
 }
 
-static inline void __flush(struct ip_set_iptreemap *map)
+static inline void
+__flush(struct ip_set_iptreemap *map)
 {
        struct ip_set_iptreemap_b *btree;
        unsigned int a;
@@ -563,7 +498,8 @@ static inline void __flush(struct ip_set_iptreemap *map)
        LOOP_WALK_END();
 }
 
-static void destroy(struct ip_set *set)
+static void
+iptreemap_destroy(struct ip_set *set)
 {
        struct ip_set_iptreemap *map = set->data;
 
@@ -576,7 +512,8 @@ static void destroy(struct ip_set *set)
        set->data = NULL;
 }
 
-static void flush(struct ip_set *set)
+static void
+iptreemap_flush(struct ip_set *set)
 {
        struct ip_set_iptreemap *map = set->data;
 
@@ -590,7 +527,8 @@ static void flush(struct ip_set *set)
        init_gc_timer(set);
 }
 
-static void list_header(const struct ip_set *set, void *data)
+static void
+iptreemap_list_header(const struct ip_set *set, void *data)
 {
        struct ip_set_iptreemap *map = set->data;
        struct ip_set_req_iptreemap_create *header = data;
@@ -598,7 +536,8 @@ static void list_header(const struct ip_set *set, void *data)
        header->gc_interval = map->gc_interval;
 }
 
-static int list_members_size(const struct ip_set *set)
+static int
+iptreemap_list_members_size(const struct ip_set *set)
 {
        struct ip_set_iptreemap *map = set->data;
        struct ip_set_iptreemap_b *btree;
@@ -627,17 +566,19 @@ static int list_members_size(const struct ip_set *set)
        return (count * sizeof(struct ip_set_req_iptreemap));
 }
 
-static inline size_t add_member(void *data, size_t offset, ip_set_ip_t start, ip_set_ip_t end)
+static inline size_t
+add_member(void *data, size_t offset, ip_set_ip_t start, ip_set_ip_t end)
 {
        struct ip_set_req_iptreemap *entry = data + offset;
 
-       entry->start = start;
+       entry->ip = start;
        entry->end = end;
 
        return sizeof(*entry);
 }
 
-static void list_members(const struct ip_set *set, void *data)
+static void
+iptreemap_list_members(const struct ip_set *set, void *data)
 {
        struct ip_set_iptreemap *map = set->data;
        struct ip_set_iptreemap_b *btree;
@@ -674,26 +615,7 @@ static void list_members(const struct ip_set *set, void *data)
                add_member(data, offset, start, end);
 }
 
-static struct ip_set_type ip_set_iptreemap = {
-       .typename               = SETTYPE_NAME,
-       .features               = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
-       .protocol_version       = IP_SET_PROTOCOL_VERSION,
-       .create                 = create,
-       .destroy                = destroy,
-       .flush                  = flush,
-       .reqsize                = sizeof(struct ip_set_req_iptreemap),
-       .addip                  = addip,
-       .addip_kernel           = addip_kernel,
-       .delip                  = delip,
-       .delip_kernel           = delip_kernel,
-       .testip                 = testip,
-       .testip_kernel          = testip_kernel,
-       .header_size            = sizeof(struct ip_set_req_iptreemap_create),
-       .list_header            = list_header,
-       .list_members_size      = list_members_size,
-       .list_members           = list_members,
-       .me                     = THIS_MODULE,
-};
+IP_SET_TYPE(iptreemap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sven Wegener <sven.wegener@stealer.net>");
index 33e2808765beceddb766317acd65e2b912f7e883..4b2b1de33be14449ff77dbfeb863cae0809750f3 100644 (file)
@@ -1,7 +1,7 @@
 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
  *                         Patrick Schaaf <bof@bof.de>
  *                         Martin Josefsson <gandalf@wlug.westbo.se>
- * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ * Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  *
  * 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
 #include <linux/module.h>
 #include <linux/ip.h>
 #include <linux/skbuff.h>
-#include <linux/version.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <linux/spinlock.h>
 #include <linux/if_ether.h>
-#include <linux/vmalloc.h>
 
-#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_bitmaps.h>
 #include <linux/netfilter_ipv4/ip_set_macipmap.h>
 
 static int
-testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
+macipmap_utest(struct ip_set *set, const void *data, size_t size,
+              ip_set_ip_t *hash_ip)
 {
-       struct ip_set_macipmap *map = set->data;
-       struct ip_set_macip *table = map->members;      
+       const struct ip_set_macipmap *map = set->data;
+       const struct ip_set_macip *table = map->members;        
        const struct ip_set_req_macipmap *req = data;
 
-       if (size != sizeof(struct ip_set_req_macipmap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_macipmap),
-                             size);
-               return -EINVAL;
-       }
-
        if (req->ip < map->first_ip || req->ip > map->last_ip)
                return -ERANGE;
 
@@ -57,19 +48,17 @@ testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
 }
 
 static int
-testip_kernel(struct ip_set *set,
-             const struct sk_buff *skb,
-             ip_set_ip_t *hash_ip,
-             const u_int32_t *flags,
-             unsigned char index)
+macipmap_ktest(struct ip_set *set,
+              const struct sk_buff *skb,
+              ip_set_ip_t *hash_ip,
+              const u_int32_t *flags,
+              unsigned char index)
 {
-       struct ip_set_macipmap *map = set->data;
-       struct ip_set_macip *table = map->members;
+       const struct ip_set_macipmap *map = set->data;
+       const struct ip_set_macip *table = map->members;
        ip_set_ip_t ip;
        
-       ip = ntohl(flags[index] & IPSET_SRC
-                       ? ip_hdr(skb)->saddr
-                       : ip_hdr(skb)->daddr);
+       ip = ipaddr(skb, flags[index]);
 
        if (ip < map->first_ip || ip > map->last_ip)
                return 0;
@@ -93,8 +82,8 @@ testip_kernel(struct ip_set *set,
 
 /* returns 0 on success */
 static inline int
-__addip(struct ip_set *set,
-       ip_set_ip_t ip, const unsigned char *ethernet, ip_set_ip_t *hash_ip)
+macipmap_add(struct ip_set *set, ip_set_ip_t *hash_ip,
+            ip_set_ip_t ip, const unsigned char *ethernet)
 {
        struct ip_set_macipmap *map = set->data;
        struct ip_set_macip *table = map->members;
@@ -111,43 +100,16 @@ __addip(struct ip_set *set,
        return 0;
 }
 
-static int
-addip(struct ip_set *set, const void *data, size_t size,
-      ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_macipmap *req = data;
-
-       if (size != sizeof(struct ip_set_req_macipmap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_macipmap),
-                             size);
-               return -EINVAL;
-       }
-       return __addip(set, req->ip, req->ethernet, hash_ip);
-}
-
-static int
-addip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       ip_set_ip_t ip;
-       
-       ip = ntohl(flags[index] & IPSET_SRC
-                       ? ip_hdr(skb)->saddr
-                       : ip_hdr(skb)->daddr);
-
-       if (!(skb_mac_header(skb) >= skb->head
-             && (skb_mac_header(skb) + ETH_HLEN) <= skb->data))
+#define KADT_CONDITION                                         \
+       if (!(skb_mac_header(skb) >= skb->head                  \
+             && (skb_mac_header(skb) + ETH_HLEN) <= skb->data))\
                return -EINVAL;
 
-       return __addip(set, ip, eth_hdr(skb)->h_source, hash_ip);
-}
+UADT(macipmap, add, req->ethernet)
+KADT(macipmap, add, ipaddr, eth_hdr(skb)->h_source)
 
 static inline int
-__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+macipmap_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
        struct ip_set_macipmap *map = set->data;
        struct ip_set_macip *table = map->members;
@@ -163,173 +125,44 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
        return 0;
 }
 
-static int
-delip(struct ip_set *set, const void *data, size_t size,
-     ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_macipmap *req = data;
-
-       if (size != sizeof(struct ip_set_req_macipmap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_macipmap),
-                             size);
-               return -EINVAL;
-       }
-       return __delip(set, req->ip, hash_ip);
-}
-
-static int
-delip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       return __delip(set,
-                      ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                      hash_ip);
-}
+#undef KADT_CONDITION
+#define KADT_CONDITION
 
-static inline size_t members_size(ip_set_ip_t from, ip_set_ip_t to)
-{
-       return (size_t)((to - from + 1) * sizeof(struct ip_set_macip));
-}
+UADT(macipmap, del)
+KADT(macipmap, del, ipaddr)
 
-static int create(struct ip_set *set, const void *data, size_t size)
+static inline int
+__macipmap_create(const struct ip_set_req_macipmap_create *req,
+                 struct ip_set_macipmap *map)
 {
-       size_t newbytes;
-       const struct ip_set_req_macipmap_create *req = data;
-       struct ip_set_macipmap *map;
-
-       if (size != sizeof(struct ip_set_req_macipmap_create)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_macipmap_create),
-                             size);
-               return -EINVAL;
-       }
-
-       DP("from %u.%u.%u.%u to %u.%u.%u.%u",
-          HIPQUAD(req->from), HIPQUAD(req->to));
-
-       if (req->from > req->to) {
-               DP("bad ip range");
-               return -ENOEXEC;
-       }
-
        if (req->to - req->from > MAX_RANGE) {
-               ip_set_printk("range too big (max %d addresses)",
-                              MAX_RANGE+1);
+               ip_set_printk("range too big, %d elements (max %d)",
+                             req->to - req->from + 1, MAX_RANGE+1);
                return -ENOEXEC;
        }
-
-       map = kmalloc(sizeof(struct ip_set_macipmap), GFP_KERNEL);
-       if (!map) {
-               DP("out of memory for %d bytes",
-                  sizeof(struct ip_set_macipmap));
-               return -ENOMEM;
-       }
        map->flags = req->flags;
-       map->first_ip = req->from;
-       map->last_ip = req->to;
-       newbytes = members_size(map->first_ip, map->last_ip);
-       map->members = ip_set_malloc(newbytes);
-       DP("members: %u %p", newbytes, map->members);
-       if (!map->members) {
-               DP("out of memory for %d bytes", newbytes);
-               kfree(map);
-               return -ENOMEM;
-       }
-       memset(map->members, 0, newbytes);
-       
-       set->data = map;
-       return 0;
-}
-
-static void destroy(struct ip_set *set)
-{
-       struct ip_set_macipmap *map = set->data;
-
-       ip_set_free(map->members, members_size(map->first_ip, map->last_ip));
-       kfree(map);
-
-       set->data = NULL;
+       return (req->to - req->from + 1) * sizeof(struct ip_set_macip);
 }
 
-static void flush(struct ip_set *set)
-{
-       struct ip_set_macipmap *map = set->data;
-       memset(map->members, 0, members_size(map->first_ip, map->last_ip));
-}
+BITMAP_CREATE(macipmap)
+BITMAP_DESTROY(macipmap)
+BITMAP_FLUSH(macipmap)
 
-static void list_header(const struct ip_set *set, void *data)
+static inline void
+__macipmap_list_header(const struct ip_set_macipmap *map,
+                      struct ip_set_req_macipmap_create *header)
 {
-       const struct ip_set_macipmap *map = set->data;
-       struct ip_set_req_macipmap_create *header = data;
-
-       DP("list_header %x %x %u", map->first_ip, map->last_ip,
-          map->flags);
-
-       header->from = map->first_ip;
-       header->to = map->last_ip;
        header->flags = map->flags;
 }
 
-static int list_members_size(const struct ip_set *set)
-{
-       const struct ip_set_macipmap *map = set->data;
-
-       DP("%u", members_size(map->first_ip, map->last_ip));
-       return members_size(map->first_ip, map->last_ip);
-}
-
-static void list_members(const struct ip_set *set, void *data)
-{
-       const struct ip_set_macipmap *map = set->data;
+BITMAP_LIST_HEADER(macipmap)
+BITMAP_LIST_MEMBERS_SIZE(macipmap)
+BITMAP_LIST_MEMBERS(macipmap)
 
-       int bytes = members_size(map->first_ip, map->last_ip);
-
-       DP("members: %u %p", bytes, map->members);
-       memcpy(data, map->members, bytes);
-}
-
-static struct ip_set_type ip_set_macipmap = {
-       .typename               = SETTYPE_NAME,
-       .features               = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
-       .protocol_version       = IP_SET_PROTOCOL_VERSION,
-       .create                 = &create,
-       .destroy                = &destroy,
-       .flush                  = &flush,
-       .reqsize                = sizeof(struct ip_set_req_macipmap),
-       .addip                  = &addip,
-       .addip_kernel           = &addip_kernel,
-       .delip                  = &delip,
-       .delip_kernel           = &delip_kernel,
-       .testip                 = &testip,
-       .testip_kernel          = &testip_kernel,
-       .header_size            = sizeof(struct ip_set_req_macipmap_create),
-       .list_header            = &list_header,
-       .list_members_size      = &list_members_size,
-       .list_members           = &list_members,
-       .me                     = THIS_MODULE,
-};
+IP_SET_TYPE(macipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
 MODULE_DESCRIPTION("macipmap type of IP sets");
 
-static int __init ip_set_macipmap_init(void)
-{
-       init_max_page_size();
-       return ip_set_register_set_type(&ip_set_macipmap);
-}
-
-static void __exit ip_set_macipmap_fini(void)
-{
-       /* FIXME: possible race with ip_set_create() */
-       ip_set_unregister_set_type(&ip_set_macipmap);
-}
-
-module_init(ip_set_macipmap_init);
-module_exit(ip_set_macipmap_fini);
+REGISTER_MODULE(macipmap)
index ecdf3696b18da7596f2337604e17ad91d2c3062e..a04857cd0db083dd4ef744107f2bddaec1d7c733 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  *
  * 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
 #include <linux/moduleparam.h>
 #include <linux/ip.h>
 #include <linux/skbuff.h>
-#include <linux/version.h>
 #include <linux/jhash.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <linux/spinlock.h>
-#include <linux/vmalloc.h>
 #include <linux/random.h>
 
 #include <net/ip.h>
 
-#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_hashes.h>
 #include <linux/netfilter_ipv4/ip_set_nethash.h>
 
 static int limit = MAX_RANGE;
 
 static inline __u32
-jhash_ip(const struct ip_set_nethash *map, uint16_t i, ip_set_ip_t ip)
-{
-       return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
-}
-
-static inline __u32
-hash_id_cidr(struct ip_set_nethash *map,
-            ip_set_ip_t ip,
-            unsigned char cidr,
-            ip_set_ip_t *hash_ip)
+nethash_id_cidr(const struct ip_set_nethash *map,
+               ip_set_ip_t *hash_ip,
+               ip_set_ip_t ip,
+               uint8_t cidr)
 {
        __u32 id;
        u_int16_t i;
        ip_set_ip_t *elem;
 
-       *hash_ip = pack(ip, cidr);
+       *hash_ip = pack_ip_cidr(ip, cidr);
        
        for (i = 0; i < map->probes; i++) {
                id = jhash_ip(map, i, *hash_ip) % map->hashsize;
@@ -58,14 +49,14 @@ hash_id_cidr(struct ip_set_nethash *map,
 }
 
 static inline __u32
-hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+nethash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
-       struct ip_set_nethash *map = set->data;
+       const struct ip_set_nethash *map = set->data;
        __u32 id = UINT_MAX;
        int i;
 
        for (i = 0; i < 30 && map->cidr[i]; i++) {
-               id = hash_id_cidr(map, ip, map->cidr[i], hash_ip);
+               id = nethash_id_cidr(map, hash_ip, ip, map->cidr[i]);
                if (id != UINT_MAX)
                        break;
        }
@@ -73,65 +64,50 @@ hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
 }
 
 static inline int
-__testip_cidr(struct ip_set *set, ip_set_ip_t ip, unsigned char cidr,
-             ip_set_ip_t *hash_ip)
+nethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip,
+                 ip_set_ip_t ip, uint8_t cidr)
 {
-       struct ip_set_nethash *map = set->data;
+       const struct ip_set_nethash *map = set->data;
 
-       return (ip && hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX);
+       return (ip && nethash_id_cidr(map, hash_ip, ip, cidr) != UINT_MAX);
 }
 
 static inline int
-__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+nethash_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
 {
-       return (ip && hash_id(set, ip, hash_ip) != UINT_MAX);
+       return (ip && nethash_id(set, hash_ip, ip) != UINT_MAX);
 }
 
 static int
-testip(struct ip_set *set, const void *data, size_t size,
-       ip_set_ip_t *hash_ip)
+nethash_utest(struct ip_set *set, const void *data, size_t size,
+             ip_set_ip_t *hash_ip)
 {
        const struct ip_set_req_nethash *req = data;
 
-       if (size != sizeof(struct ip_set_req_nethash)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_nethash),
-                             size);
+       if (req->cidr <= 0 || req->cidr > 32)
                return -EINVAL;
-       }
-       return (req->cidr == 32 ? __testip(set, req->ip, hash_ip)
-               : __testip_cidr(set, req->ip, req->cidr, hash_ip));
+       return (req->cidr == 32 ? nethash_test(set, hash_ip, req->ip)
+               : nethash_test_cidr(set, hash_ip, req->ip, req->cidr));
 }
 
-static int
-testip_kernel(struct ip_set *set,
-             const struct sk_buff *skb,
-             ip_set_ip_t *hash_ip,
-             const u_int32_t *flags,
-             unsigned char index)
-{
-       return __testip(set,
-                       ntohl(flags[index] & IPSET_SRC
-                               ? ip_hdr(skb)->saddr
-                               : ip_hdr(skb)->daddr),
-                       hash_ip);
-}
+#define KADT_CONDITION
+
+KADT(nethash, test, ipaddr)
 
 static inline int
-__addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
+__nethash_add(struct ip_set_nethash *map, ip_set_ip_t *ip)
 {
        __u32 probe;
        u_int16_t i;
        ip_set_ip_t *elem;
        
        for (i = 0; i < map->probes; i++) {
-               probe = jhash_ip(map, i, ip) % map->hashsize;
+               probe = jhash_ip(map, i, *ip) % map->hashsize;
                elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
-               if (*elem == ip)
+               if (*elem == *ip)
                        return -EEXIST;
                if (!*elem) {
-                       *elem = ip;
-                       map->elements++;
+                       *elem = *ip;
                        return 0;
                }
        }
@@ -140,319 +116,102 @@ __addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
 }
 
 static inline int
-__addip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
-       ip_set_ip_t *hash_ip)
+nethash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
+           ip_set_ip_t ip, uint8_t cidr)
 {
+       struct ip_set_nethash *map = set->data;
+       int ret;
+       
        if (!ip || map->elements >= limit)
                return -ERANGE;
+       if (cidr <= 0 || cidr >= 32)
+               return -EINVAL;
+       if (map->nets[cidr-1] == UINT16_MAX)
+               return -ERANGE;
        
-       *hash_ip = pack(ip, cidr);
+       *hash_ip = pack_ip_cidr(ip, cidr);
        DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip));
        
-       return __addip_base(map, *hash_ip);
-}
-
-static void
-update_cidr_sizes(struct ip_set_nethash *map, unsigned char cidr)
-{
-       unsigned char next;
-       int i;
-       
-       for (i = 0; i < 30 && map->cidr[i]; i++) {
-               if (map->cidr[i] == cidr) {
-                       return;
-               } else if (map->cidr[i] < cidr) {
-                       next = map->cidr[i];
-                       map->cidr[i] = cidr;
-                       cidr = next;
-               }
+       ret = __nethash_add(map, hash_ip);
+       if (ret == 0) {
+               if (!map->nets[cidr-1]++)
+                       add_cidr_size(map->cidr, cidr);
+               map->elements++;
        }
-       if (i < 30)
-               map->cidr[i] = cidr;
-}
-
-static int
-addip(struct ip_set *set, const void *data, size_t size,
-        ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_nethash *req = data;
-       int ret;
-
-       if (size != sizeof(struct ip_set_req_nethash)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_nethash),
-                             size);
-               return -EINVAL;
-       }
-       ret = __addip(set->data, req->ip, req->cidr, hash_ip);
-       
-       if (ret == 0)
-               update_cidr_sizes(set->data, req->cidr);
        
        return ret;
 }
 
-static int
-addip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       struct ip_set_nethash *map = set->data;
-       int ret = -ERANGE;
-       ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
-                                       ? ip_hdr(skb)->saddr
-                                       : ip_hdr(skb)->daddr);
-       
-       if (map->cidr[0])
-               ret = __addip(map, ip, map->cidr[0], hash_ip);
-               
-       return ret;
-}
-
-static int retry(struct ip_set *set)
-{
-       struct ip_set_nethash *map = set->data;
-       ip_set_ip_t *elem;
-       void *members;
-       u_int32_t i, hashsize = map->hashsize;
-       int res;
-       struct ip_set_nethash *tmp;
-       
-       if (map->resize == 0)
-               return -ERANGE;
-
-    again:
-       res = 0;
-       
-       /* Calculate new parameters */
-       hashsize += (hashsize * map->resize)/100;
-       if (hashsize == map->hashsize)
-               hashsize++;
-       
-       ip_set_printk("rehashing of set %s triggered: "
-                     "hashsize grows from %u to %u",
-                     set->name, map->hashsize, hashsize);
-
-       tmp = kmalloc(sizeof(struct ip_set_nethash)
-                     + map->probes * sizeof(uint32_t), GFP_ATOMIC);
-       if (!tmp) {
-               DP("out of memory for %d bytes",
-                  sizeof(struct ip_set_nethash)
-                  + map->probes * sizeof(uint32_t));
-               return -ENOMEM;
-       }
-       tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
-       if (!tmp->members) {
-               DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
-               kfree(tmp);
-               return -ENOMEM;
-       }
-       tmp->hashsize = hashsize;
-       tmp->elements = 0;
-       tmp->probes = map->probes;
-       tmp->resize = map->resize;
-       memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
-       memcpy(tmp->cidr, map->cidr, 30 * sizeof(unsigned char));
-       
-       write_lock_bh(&set->lock);
-       map = set->data; /* Play safe */
-       for (i = 0; i < map->hashsize && res == 0; i++) {
-               elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);     
-               if (*elem)
-                       res = __addip_base(tmp, *elem);
-       }
-       if (res) {
-               /* Failure, try again */
-               write_unlock_bh(&set->lock);
-               harray_free(tmp->members);
-               kfree(tmp);
-               goto again;
-       }
-       
-       /* Success at resizing! */
-       members = map->members;
-       
-       map->hashsize = tmp->hashsize;
-       map->members = tmp->members;
-       write_unlock_bh(&set->lock);
+#undef KADT_CONDITION
+#define KADT_CONDITION                                                 \
+       struct ip_set_nethash *map = set->data;                         \
+       uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31;
 
-       harray_free(members);
-       kfree(tmp);
+UADT(nethash, add, req->cidr)
+KADT(nethash, add, ipaddr, cidr)
 
-       return 0;
+static inline void
+__nethash_retry(struct ip_set_nethash *tmp, struct ip_set_nethash *map)
+{
+       memcpy(tmp->cidr, map->cidr, 30 * sizeof(uint8_t));
+       memcpy(tmp->nets, map->nets, 30 * sizeof(uint16_t));
 }
 
+HASH_RETRY(nethash, ip_set_ip_t)
+
 static inline int
-__delip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
-       ip_set_ip_t *hash_ip)
+nethash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
+           ip_set_ip_t ip, uint8_t cidr)
 {
+       struct ip_set_nethash *map = set->data;
        ip_set_ip_t id, *elem;
 
        if (!ip)
                return -ERANGE;
+       if (cidr <= 0 || cidr >= 32)
+               return -EINVAL; 
        
-       id = hash_id_cidr(map, ip, cidr, hash_ip);
+       id = nethash_id_cidr(map, hash_ip, ip, cidr);
        if (id == UINT_MAX)
                return -EEXIST;
                
        elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
        *elem = 0;
        map->elements--;
+       if (!map->nets[cidr-1]--)
+               del_cidr_size(map->cidr, cidr);
        return 0;
 }
 
-static int
-delip(struct ip_set *set, const void *data, size_t size,
-        ip_set_ip_t *hash_ip)
-{
-       const struct ip_set_req_nethash *req = data;
+UADT(nethash, del, req->cidr)
+KADT(nethash, del, ipaddr, cidr)
 
-       if (size != sizeof(struct ip_set_req_nethash)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_nethash),
-                             size);
-               return -EINVAL;
-       }
-       /* TODO: no garbage collection in map->cidr */          
-       return __delip(set->data, req->ip, req->cidr, hash_ip);
-}
-
-static int
-delip_kernel(struct ip_set *set,
-            const struct sk_buff *skb,
-            ip_set_ip_t *hash_ip,
-            const u_int32_t *flags,
-            unsigned char index)
-{
-       struct ip_set_nethash *map = set->data;
-       int ret = -ERANGE;
-       ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
-                                       ? ip_hdr(skb)->saddr
-                                       : ip_hdr(skb)->daddr);
-       
-       if (map->cidr[0])
-               ret = __delip(map, ip, map->cidr[0], hash_ip);
-       
-       return ret;
-}
-
-static int create(struct ip_set *set, const void *data, size_t size)
+static inline int
+__nethash_create(const struct ip_set_req_nethash_create *req,
+                struct ip_set_nethash *map)
 {
-       const struct ip_set_req_nethash_create *req = data;
-       struct ip_set_nethash *map;
-       uint16_t i;
-
-       if (size != sizeof(struct ip_set_req_nethash_create)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                              sizeof(struct ip_set_req_nethash_create),
-                              size);
-               return -EINVAL;
-       }
-
-       if (req->hashsize < 1) {
-               ip_set_printk("hashsize too small");
-               return -ENOEXEC;
-       }
-       if (req->probes < 1) {
-               ip_set_printk("probes too small");
-               return -ENOEXEC;
-       }
-
-       map = kmalloc(sizeof(struct ip_set_nethash)
-                     + req->probes * sizeof(uint32_t), GFP_KERNEL);
-       if (!map) {
-               DP("out of memory for %d bytes",
-                  sizeof(struct ip_set_nethash)
-                  + req->probes * sizeof(uint32_t));
-               return -ENOMEM;
-       }
-       for (i = 0; i < req->probes; i++)
-               get_random_bytes(((uint32_t *) map->initval)+i, 4);
-       map->elements = 0;
-       map->hashsize = req->hashsize;
-       map->probes = req->probes;
-       map->resize = req->resize;
-       memset(map->cidr, 0, 30 * sizeof(unsigned char));
-       map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
-       if (!map->members) {
-               DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
-               kfree(map);
-               return -ENOMEM;
-       }
+       memset(map->cidr, 0, 30 * sizeof(uint8_t));
+       memset(map->nets, 0, 30 * sizeof(uint16_t));
        
-       set->data = map;
        return 0;
 }
 
-static void destroy(struct ip_set *set)
-{
-       struct ip_set_nethash *map = set->data;
+HASH_CREATE(nethash, ip_set_ip_t)
+HASH_DESTROY(nethash)
 
-       harray_free(map->members);
-       kfree(map);
+HASH_FLUSH_CIDR(nethash, ip_set_ip_t)
 
-       set->data = NULL;
+static inline void
+__nethash_list_header(const struct ip_set_nethash *map,
+                     struct ip_set_req_nethash_create *header)
+{    
 }
 
-static void flush(struct ip_set *set)
-{
-       struct ip_set_nethash *map = set->data;
-       harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
-       memset(map->cidr, 0, 30 * sizeof(unsigned char));
-       map->elements = 0;
-}
+HASH_LIST_HEADER(nethash)
+HASH_LIST_MEMBERS_SIZE(nethash, ip_set_ip_t)
+HASH_LIST_MEMBERS(nethash, ip_set_ip_t)
 
-static void list_header(const struct ip_set *set, void *data)
-{
-       const struct ip_set_nethash *map = set->data;
-       struct ip_set_req_nethash_create *header = data;
-
-       header->hashsize = map->hashsize;
-       header->probes = map->probes;
-       header->resize = map->resize;
-}
-
-static int list_members_size(const struct ip_set *set)
-{
-       struct ip_set_nethash *map = set->data;
-
-       return (map->hashsize * sizeof(ip_set_ip_t));
-}
-
-static void list_members(const struct ip_set *set, void *data)
-{
-       const struct ip_set_nethash *map = set->data;
-       ip_set_ip_t i, *elem;
-
-       for (i = 0; i < map->hashsize; i++) {
-               elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);     
-               ((ip_set_ip_t *)data)[i] = *elem;
-       }
-}
-
-static struct ip_set_type ip_set_nethash = {
-       .typename               = SETTYPE_NAME,
-       .features               = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
-       .protocol_version       = IP_SET_PROTOCOL_VERSION,
-       .create                 = &create,
-       .destroy                = &destroy,
-       .flush                  = &flush,
-       .reqsize                = sizeof(struct ip_set_req_nethash),
-       .addip                  = &addip,
-       .addip_kernel           = &addip_kernel,
-       .retry                  = &retry,
-       .delip                  = &delip,
-       .delip_kernel           = &delip_kernel,
-       .testip                 = &testip,
-       .testip_kernel          = &testip_kernel,
-       .header_size            = sizeof(struct ip_set_req_nethash_create),
-       .list_header            = &list_header,
-       .list_members_size      = &list_members_size,
-       .list_members           = &list_members,
-       .me                     = THIS_MODULE,
-};
+IP_SET_RTYPE(nethash, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -460,17 +219,4 @@ MODULE_DESCRIPTION("nethash type of IP sets");
 module_param(limit, int, 0600);
 MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
 
-static int __init ip_set_nethash_init(void)
-{
-       init_max_page_size();
-       return ip_set_register_set_type(&ip_set_nethash);
-}
-
-static void __exit ip_set_nethash_fini(void)
-{
-       /* FIXME: possible race with ip_set_create() */
-       ip_set_unregister_set_type(&ip_set_nethash);
-}
-
-module_init(ip_set_nethash_init);
-module_exit(ip_set_nethash_fini);
+REGISTER_MODULE(nethash)
index aeaabcd3c358ddfd2c4cc3fd14bced64cecedd56..79cc51144dfea3f8af299bfadd83ea7a9830d9a0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  *
  * 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
@@ -12,9 +12,6 @@
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/skbuff.h>
-#include <linux/version.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #include <net/ip.h>
 
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_bitmaps.h>
 #include <linux/netfilter_ipv4/ip_set_portmap.h>
-
-/* We must handle non-linear skbs */
-static inline ip_set_ip_t
-get_port(const struct sk_buff *skb, u_int32_t flags)
-{
-       struct iphdr *iph = ip_hdr(skb);
-       u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
-       switch (iph->protocol) {
-       case IPPROTO_TCP: {
-               struct tcphdr tcph;
-               
-               /* See comments at tcp_match in ip_tables.c */
-               if (offset)
-                       return INVALID_PORT;
-
-               if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
-                       /* No choice either */
-                       return INVALID_PORT;
-               
-               return ntohs(flags & IPSET_SRC ?
-                            tcph.source : tcph.dest);
-           }
-       case IPPROTO_UDP: {
-               struct udphdr udph;
-
-               if (offset)
-                       return INVALID_PORT;
-
-               if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
-                       /* No choice either */
-                       return INVALID_PORT;
-               
-               return ntohs(flags & IPSET_SRC ?
-                            udph.source : udph.dest);
-           }
-       default:
-               return INVALID_PORT;
-       }
-}
+#include <linux/netfilter_ipv4/ip_set_getport.h>
 
 static inline int
-__testport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
+portmap_test(const struct ip_set *set, ip_set_ip_t *hash_port,
+            ip_set_ip_t port)
 {
-       struct ip_set_portmap *map = set->data;
+       const struct ip_set_portmap *map = set->data;
 
-       if (port < map->first_port || port > map->last_port)
+       if (port < map->first_ip || port > map->last_ip)
                return -ERANGE;
                
        *hash_port = port;
        DP("set: %s, port:%u, %u", set->name, port, *hash_port);
-       return !!test_bit(port - map->first_port, map->members);
+       return !!test_bit(port - map->first_ip, map->members);
 }
 
-static int
-testport(struct ip_set *set, const void *data, size_t size,
-         ip_set_ip_t *hash_port)
-{
-       const struct ip_set_req_portmap *req = data;
-
-       if (size != sizeof(struct ip_set_req_portmap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_portmap),
-                             size);
-               return -EINVAL;
-       }
-       return __testport(set, req->port, hash_port);
-}
-
-static int
-testport_kernel(struct ip_set *set,
-               const struct sk_buff *skb,
-               ip_set_ip_t *hash_port,
-               const u_int32_t *flags,
-               unsigned char index)
-{
-       int res;
-       ip_set_ip_t port = get_port(skb, flags[index]);
-
-       DP("flag %s port %u", flags[index] & IPSET_SRC ? "SRC" : "DST", port);  
-       if (port == INVALID_PORT)
+#define KADT_CONDITION                 \
+       if (ip == INVALID_PORT)         \
                return 0;       
 
-       res =  __testport(set, port, hash_port);
-       
-       return (res < 0 ? 0 : res);
-}
+UADT(portmap, test)
+KADT(portmap, test, get_port)
 
 static inline int
-__addport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
+portmap_add(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port)
 {
        struct ip_set_portmap *map = set->data;
 
-       if (port < map->first_port || port > map->last_port)
+       if (port < map->first_ip || port > map->last_ip)
                return -ERANGE;
-       if (test_and_set_bit(port - map->first_port, map->members))
+       if (test_and_set_bit(port - map->first_ip, map->members))
                return -EEXIST;
                
        *hash_port = port;
@@ -125,44 +60,17 @@ __addport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
        return 0;
 }
 
-static int
-addport(struct ip_set *set, const void *data, size_t size,
-        ip_set_ip_t *hash_port)
-{
-       const struct ip_set_req_portmap *req = data;
-
-       if (size != sizeof(struct ip_set_req_portmap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_portmap),
-                             size);
-               return -EINVAL;
-       }
-       return __addport(set, req->port, hash_port);
-}
-
-static int
-addport_kernel(struct ip_set *set,
-              const struct sk_buff *skb,
-              ip_set_ip_t *hash_port,
-              const u_int32_t *flags,
-              unsigned char index)
-{
-       ip_set_ip_t port = get_port(skb, flags[index]);
-       
-       if (port == INVALID_PORT)
-               return -EINVAL;
-
-       return __addport(set, port, hash_port);
-}
+UADT(portmap, add)
+KADT(portmap, add, get_port)
 
 static inline int
-__delport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
+portmap_del(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port)
 {
        struct ip_set_portmap *map = set->data;
 
-       if (port < map->first_port || port > map->last_port)
+       if (port < map->first_ip || port > map->last_ip)
                return -ERANGE;
-       if (!test_and_clear_bit(port - map->first_port, map->members))
+       if (!test_and_clear_bit(port - map->first_ip, map->members))
                return -EEXIST;
                
        *hash_port = port;
@@ -170,160 +78,39 @@ __delport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
        return 0;
 }
 
-static int
-delport(struct ip_set *set, const void *data, size_t size,
-        ip_set_ip_t *hash_port)
-{
-       const struct ip_set_req_portmap *req = data;
+UADT(portmap, del)
+KADT(portmap, del, get_port)
 
-       if (size != sizeof(struct ip_set_req_portmap)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                             sizeof(struct ip_set_req_portmap),
-                             size);
-               return -EINVAL;
-       }
-       return __delport(set, req->port, hash_port);
-}
-
-static int
-delport_kernel(struct ip_set *set,
-              const struct sk_buff *skb,
-              ip_set_ip_t *hash_port,
-              const u_int32_t *flags,
-              unsigned char index)
-{
-       ip_set_ip_t port = get_port(skb, flags[index]);
-       
-       if (port == INVALID_PORT)
-               return -EINVAL;
-
-       return __delport(set, port, hash_port);
-}
-
-static int create(struct ip_set *set, const void *data, size_t size)
+static inline int
+__portmap_create(const struct ip_set_req_portmap_create *req,
+                struct ip_set_portmap *map)
 {
-       int newbytes;
-       const struct ip_set_req_portmap_create *req = data;
-       struct ip_set_portmap *map;
-
-       if (size != sizeof(struct ip_set_req_portmap_create)) {
-               ip_set_printk("data length wrong (want %zu, have %zu)",
-                              sizeof(struct ip_set_req_portmap_create),
-                              size);
-               return -EINVAL;
-       }
-
-       DP("from %u to %u", req->from, req->to);
-
-       if (req->from > req->to) {
-               DP("bad port range");
-               return -ENOEXEC;
-       }
-
        if (req->to - req->from > MAX_RANGE) {
-               ip_set_printk("range too big (max %d ports)",
-                              MAX_RANGE+1);
+               ip_set_printk("range too big, %d elements (max %d)",
+                             req->to - req->from + 1, MAX_RANGE+1);
                return -ENOEXEC;
        }
-
-       map = kmalloc(sizeof(struct ip_set_portmap), GFP_KERNEL);
-       if (!map) {
-               DP("out of memory for %d bytes",
-                  sizeof(struct ip_set_portmap));
-               return -ENOMEM;
-       }
-       map->first_port = req->from;
-       map->last_port = req->to;
-       newbytes = bitmap_bytes(req->from, req->to);
-       map->members = kmalloc(newbytes, GFP_KERNEL);
-       if (!map->members) {
-               DP("out of memory for %d bytes", newbytes);
-               kfree(map);
-               return -ENOMEM;
-       }
-       memset(map->members, 0, newbytes);
-
-       set->data = map;
-       return 0;
-}
-
-static void destroy(struct ip_set *set)
-{
-       struct ip_set_portmap *map = set->data;
-
-       kfree(map->members);
-       kfree(map);
-
-       set->data = NULL;
-}
-
-static void flush(struct ip_set *set)
-{
-       struct ip_set_portmap *map = set->data;
-       memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
+       return bitmap_bytes(req->from, req->to);
 }
 
-static void list_header(const struct ip_set *set, void *data)
-{
-       const struct ip_set_portmap *map = set->data;
-       struct ip_set_req_portmap_create *header = data;
-
-       DP("list_header %u %u", map->first_port, map->last_port);
+BITMAP_CREATE(portmap)
+BITMAP_DESTROY(portmap)
+BITMAP_FLUSH(portmap)
 
-       header->from = map->first_port;
-       header->to = map->last_port;
-}
-
-static int list_members_size(const struct ip_set *set)
+static inline void
+__portmap_list_header(const struct ip_set_portmap *map,
+                     struct ip_set_req_portmap_create *header)
 {
-       const struct ip_set_portmap *map = set->data;
-
-       return bitmap_bytes(map->first_port, map->last_port);
 }
 
-static void list_members(const struct ip_set *set, void *data)
-{
-       const struct ip_set_portmap *map = set->data;
-       int bytes = bitmap_bytes(map->first_port, map->last_port);
-
-       memcpy(data, map->members, bytes);
-}
+BITMAP_LIST_HEADER(portmap)
+BITMAP_LIST_MEMBERS_SIZE(portmap)
+BITMAP_LIST_MEMBERS(portmap)
 
-static struct ip_set_type ip_set_portmap = {
-       .typename               = SETTYPE_NAME,
-       .features               = IPSET_TYPE_PORT | IPSET_DATA_SINGLE,
-       .protocol_version       = IP_SET_PROTOCOL_VERSION,
-       .create                 = &create,
-       .destroy                = &destroy,
-       .flush                  = &flush,
-       .reqsize                = sizeof(struct ip_set_req_portmap),
-       .addip                  = &addport,
-       .addip_kernel           = &addport_kernel,
-       .delip                  = &delport,
-       .delip_kernel           = &delport_kernel,
-       .testip                 = &testport,
-       .testip_kernel          = &testport_kernel,
-       .header_size            = sizeof(struct ip_set_req_portmap_create),
-       .list_header            = &list_header,
-       .list_members_size      = &list_members_size,
-       .list_members           = &list_members,
-       .me                     = THIS_MODULE,
-};
+IP_SET_TYPE(portmap, IPSET_TYPE_PORT | IPSET_DATA_SINGLE)
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
 MODULE_DESCRIPTION("portmap type of IP sets");
 
-static int __init ip_set_portmap_init(void)
-{
-       return ip_set_register_set_type(&ip_set_portmap);
-}
-
-static void __exit ip_set_portmap_fini(void)
-{
-       /* FIXME: possible race with ip_set_create() */
-       ip_set_unregister_set_type(&ip_set_portmap);
-}
-
-module_init(ip_set_portmap_init);
-module_exit(ip_set_portmap_fini);
+REGISTER_MODULE(portmap)
diff --git a/kernel/ip_set_setlist.c b/kernel/ip_set_setlist.c
new file mode 100644 (file)
index 0000000..50bc368
--- /dev/null
@@ -0,0 +1,332 @@
+/* Copyright (C) 2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * 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.
+ */
+
+/* Kernel module implementing an IP set type: the setlist type */
+
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_bitmaps.h>
+#include <linux/netfilter_ipv4/ip_set_setlist.h>
+
+/*
+ * before ==> id, ref
+ * after  ==> ref, id
+ */
+
+static inline bool
+next_id_eq(const struct ip_set_setlist *map, int i, ip_set_id_t id)
+{
+       return i < map->size && map->id[i] == id;
+}
+
+static int
+setlist_utest(struct ip_set *set, const void *data, size_t size,
+              ip_set_ip_t *hash_ip)
+{
+       const struct ip_set_setlist *map = set->data;
+       const struct ip_set_req_setlist *req = data;
+       ip_set_id_t id, ref = IP_SET_INVALID_ID;
+       int i, res = 0;
+       struct ip_set *s;
+       
+       if (req->before && req->ref[0] == '\0')
+               return -EINVAL;
+
+       id = __ip_set_get_byname(req->name, &s);
+       if (id == IP_SET_INVALID_ID)
+               return -EEXIST;
+       if (req->ref[0] != '\0') {
+               ref = __ip_set_get_byname(req->ref, &s);
+               if (ref == IP_SET_INVALID_ID) {
+                       res = -EEXIST;
+                       goto finish;
+               }
+       }
+       for (i = 0; i < map->size
+                   && map->id[i] != IP_SET_INVALID_ID; i++) {
+               if (req->before && map->id[i] == id) {
+                       res = next_id_eq(map, i + 1, ref);
+                       break;
+               } else if (!req->before) {
+                       if ((ref == IP_SET_INVALID_ID
+                            && map->id[i] == id)
+                           || (map->id[i] == ref
+                               && next_id_eq(map, i + 1, id))) {
+                               res = 1;
+                               break;
+                       }
+               }
+       }
+       if (ref != IP_SET_INVALID_ID)
+               __ip_set_put_byid(ref);
+finish:
+       __ip_set_put_byid(id);
+       return res;
+}
+
+static int
+setlist_ktest(struct ip_set *set,
+              const struct sk_buff *skb,
+              ip_set_ip_t *hash_ip,
+              const u_int32_t *flags,
+              unsigned char index)
+{
+       struct ip_set_setlist *map = set->data;
+       int i, res = 0;
+       
+       for (i = 0; i < map->size
+                   && map->id[i] != IP_SET_INVALID_ID
+                   && res == 0; i++)
+               res = ip_set_testip_kernel(map->id[i], skb, flags);
+       return res;
+}
+
+static inline int
+insert_setlist(struct ip_set_setlist *map, int i, ip_set_id_t id)
+{
+       ip_set_id_t tmp;
+       int j;
+
+       printk("i: %u, last %u\n", i, map->id[map->size - 1]);  
+       if (i >= map->size || map->id[map->size - 1] != IP_SET_INVALID_ID)
+               return -ERANGE;
+       
+       for (j = i; j < map->size
+                   && id != IP_SET_INVALID_ID; j++) {
+               tmp = map->id[j];
+               map->id[j] = id;
+               id = tmp;
+       }
+       return 0;
+}
+
+static int
+setlist_uadd(struct ip_set *set, const void *data, size_t size,
+            ip_set_ip_t *hash_ip)
+{
+       struct ip_set_setlist *map = set->data;
+       const struct ip_set_req_setlist *req = data;
+       ip_set_id_t id, ref = IP_SET_INVALID_ID;
+       int i, res = -ERANGE;
+       struct ip_set *s;
+       
+       if (req->before && req->ref[0] == '\0')
+               return -EINVAL;
+
+       id = __ip_set_get_byname(req->name, &s);
+       if (id == IP_SET_INVALID_ID)
+               return -EEXIST;
+       /* "Loop detection" */
+       if (strcmp(s->type->typename, "setlist") == 0)
+               goto finish;
+
+       if (req->ref[0] != '\0') {
+               ref = __ip_set_get_byname(req->ref, &s);
+               if (ref == IP_SET_INVALID_ID) {
+                       res = -EEXIST;
+                       goto finish;
+               }
+       }
+       for (i = 0; i < map->size; i++) {
+               if (map->id[i] != ref)
+                       continue;
+               if (req->before) 
+                       res = insert_setlist(map, i, id);
+               else
+                       res = insert_setlist(map,
+                               ref == IP_SET_INVALID_ID ? i : i + 1,
+                               id);
+               break;
+       }
+       if (ref != IP_SET_INVALID_ID)
+               __ip_set_put_byid(ref);
+       /* In case of success, we keep the reference to the id */
+finish:
+       if (res != 0)
+               __ip_set_put_byid(id);
+       return res;
+}
+
+static int
+setlist_kadd(struct ip_set *set,
+            const struct sk_buff *skb,
+            ip_set_ip_t *hash_ip,
+            const u_int32_t *flags,
+            unsigned char index)
+{
+       struct ip_set_setlist *map = set->data;
+       int i, res = -EINVAL;
+       
+       for (i = 0; i < map->size
+                   && map->id[i] != IP_SET_INVALID_ID
+                   && res != 0; i++)
+               res = ip_set_addip_kernel(map->id[i], skb, flags);
+       return res;
+}
+
+static inline bool
+unshift_setlist(struct ip_set_setlist *map, int i)
+{
+       int j;
+       
+       for (j = i; j < map->size - 1; j++)
+               map->id[j] = map->id[j+1];
+       map->id[map->size-1] = IP_SET_INVALID_ID;
+       return 0;
+}
+
+static int
+setlist_udel(struct ip_set *set, const void *data, size_t size,
+            ip_set_ip_t *hash_ip)
+{
+       struct ip_set_setlist *map = set->data;
+       const struct ip_set_req_setlist *req = data;
+       ip_set_id_t id, ref = IP_SET_INVALID_ID;
+       int i, res = -EEXIST;
+       struct ip_set *s;
+       
+       if (req->before && req->ref[0] == '\0')
+               return -EINVAL;
+
+       id = __ip_set_get_byname(req->name, &s);
+       if (id == IP_SET_INVALID_ID)
+               return -EEXIST;
+       if (req->ref[0] != '\0') {
+               ref = __ip_set_get_byname(req->ref, &s);
+               if (ref == IP_SET_INVALID_ID)
+                       goto finish;
+       }
+       for (i = 0; i < map->size
+                   && map->id[i] != IP_SET_INVALID_ID; i++) {
+               if (req->before) {
+                       if (map->id[i] == id
+                           && next_id_eq(map, i + 1, ref)) {
+                               res = unshift_setlist(map, i);
+                               break;
+                       }
+               } else if (ref == IP_SET_INVALID_ID) {
+                       if (map->id[i] == id) {
+                               res = unshift_setlist(map, i);
+                               break;
+                       }
+               } else if (map->id[i] == ref
+                          && next_id_eq(map, i + 1, id)) {
+                       res = unshift_setlist(map, i + 1);
+                       break;
+               }
+       }
+       if (ref != IP_SET_INVALID_ID)
+               __ip_set_put_byid(ref);
+finish:
+       __ip_set_put_byid(id);
+       /* In case of success, release the reference to the id */
+       if (res == 0)
+               __ip_set_put_byid(id);
+       return res;
+}
+
+static int
+setlist_kdel(struct ip_set *set,
+            const struct sk_buff *skb,
+            ip_set_ip_t *hash_ip,
+            const u_int32_t *flags,
+            unsigned char index)
+{
+       struct ip_set_setlist *map = set->data;
+       int i, res = -EINVAL;
+       
+       for (i = 0; i < map->size
+                   && map->id[i] != IP_SET_INVALID_ID
+                   && res != 0; i++)
+               res = ip_set_delip_kernel(map->id[i], skb, flags);
+       return res;
+}
+
+static int
+setlist_create(struct ip_set *set, const void *data, size_t size)
+{
+       struct ip_set_setlist *map;
+       const struct ip_set_req_setlist_create *req = data;
+       int i;
+       
+       map = kmalloc(sizeof(struct ip_set_setlist) +
+                     req->size * sizeof(ip_set_id_t), GFP_KERNEL);
+       if (!map)
+               return -ENOMEM;
+       map->size = req->size;
+       for (i = 0; i < map->size; i++)
+               map->id[i] = IP_SET_INVALID_ID;
+       
+       set->data = map;
+       return 0;
+}                        
+
+static void
+setlist_destroy(struct ip_set *set)
+{
+       struct ip_set_setlist *map = set->data;
+       int i;
+       
+       for (i = 0; i < map->size
+                   && map->id[i] != IP_SET_INVALID_ID; i++)
+               __ip_set_put_byid(map->id[i]);
+
+       kfree(map);
+       set->data = NULL;
+}
+
+static void
+setlist_flush(struct ip_set *set)
+{
+       struct ip_set_setlist *map = set->data;
+       int i;
+       
+       for (i = 0; i < map->size
+                   && map->id[i] != IP_SET_INVALID_ID; i++) {
+               __ip_set_put_byid(map->id[i]);
+               map->id[i] = IP_SET_INVALID_ID;
+       }
+}
+
+static void
+setlist_list_header(const struct ip_set *set, void *data)
+{
+       const struct ip_set_setlist *map = set->data;
+       struct ip_set_req_setlist_create *header = data;
+       
+       header->size = map->size;
+}
+
+static int
+setlist_list_members_size(const struct ip_set *set)
+{
+       const struct ip_set_setlist *map = set->data;
+       
+       return map->size * sizeof(ip_set_id_t);
+}
+
+static void
+setlist_list_members(const struct ip_set *set, void *data)
+{
+       struct ip_set_setlist *map = set->data;
+       int i;
+       
+       for (i = 0; i < map->size; i++)
+               *((ip_set_id_t *)data + i) = map->id[i];
+}
+
+IP_SET_TYPE(setlist, IPSET_TYPE_SETNAME | IPSET_DATA_SINGLE)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("setlist type of IP sets");
+
+REGISTER_MODULE(setlist)
index fc0a7d56b05927d399ff70308d7b41e7c1073510..edbbb0c004d010b4e788b433e5632f414491a546 100644 (file)
@@ -3,25 +3,25 @@
 # Range: Create a set from a valid range
 0 ipset -N test ipporthash --from 2.0.0.1 --to 2.1.0.0
 # Range: Add lower boundary
-0 ipset -A test 2.0.0.1:5
+0 ipset -A test 2.0.0.1,5
 # Range: Add upper boundary
-0 ipset -A test 2.1.0.0:128
+0 ipset -A test 2.1.0.0,128
 # Range: Test lower boundary
-0 ipset -T test 2.0.0.1:5
+0 ipset -T test 2.0.0.1,5
 # Range: Test upper boundary
-0 ipset -T test 2.1.0.0:128
+0 ipset -T test 2.1.0.0,128
 # Range: Test value not added to the set
-1 ipset -T test 2.0.0.1:4
+1 ipset -T test 2.0.0.1,4
 # Range: Test value not added to the set
-1 ipset -T test 2.0.0.1:6
+1 ipset -T test 2.0.0.1,6
 # Range: Test value before lower boundary
-1 ipset -T test 2.0.0.0:5
+1 ipset -T test 2.0.0.0,5
 # Range: Test value after upper boundary
-1 ipset -T test 2.1.0.1:128
+1 ipset -T test 2.1.0.1,128
 # Range: Try to add value before lower boundary
-1 ipset -A test 2.0.0.0:5
+1 ipset -A test 2.0.0.0,5
 # Range: Try to add value after upper boundary
-1 ipset -A test 2.1.0.1:128
+1 ipset -A test 2.1.0.1,128
 # Range: Delete test test
 0 ipset -X test
 # Network: Try to create a set from an invalid network
 # Network: Create a set from a valid network
 0 ipset -N test ipporthash --network 2.0.0.0/16
 # Network: Add lower boundary
-0 ipset -A test 2.0.0.0:5
+0 ipset -A test 2.0.0.0,5
 # Network: Add upper boundary
-0 ipset -A test 2.0.255.255:128
+0 ipset -A test 2.0.255.255,128
 # Network: Test lower boundary
-0 ipset -T test 2.0.0.0:5
+0 ipset -T test 2.0.0.0,5
 # Network: Test upper boundary
-0 ipset -T test 2.0.255.255:128
+0 ipset -T test 2.0.255.255,128
 # Network: Test value not added to the set
-1 ipset -T test 2.0.0.0:4
+1 ipset -T test 2.0.0.0,4
 # Network: Test value not added to the set
-1 ipset -T test 2.0.0.0:6
+1 ipset -T test 2.0.0.0,6
 # Network: Test value before lower boundary
-1 ipset -T test 1.255.255.255:5
+1 ipset -T test 1.255.255.255,5
 # Network: Test value after upper boundary
-1 ipset -T test 2.1.0.0:128
+1 ipset -T test 2.1.0.0,128
 # Network: Try to add value before lower boundary
-1 ipset -A test 1.255.255.255:5
+1 ipset -A test 1.255.255.255,5
 # Network: Try to add value after upper boundary
-1 ipset -A test 2.1.0.0:128
+1 ipset -A test 2.1.0.0,128
 # Network: Delete test set
 0 ipset -X test
 # eof
diff --git a/tests/ipportiphash.t b/tests/ipportiphash.t
new file mode 100644 (file)
index 0000000..5ffd08a
--- /dev/null
@@ -0,0 +1,55 @@
+# Range: Try to create from an invalid range
+2 ipset -N test ipportiphash --from 2.0.0.1 --to 2.1.0.1
+# Range: Create a set from a valid range
+0 ipset -N test ipportiphash --from 2.0.0.1 --to 2.1.0.0
+# Range: Add lower boundary
+0 ipset -A test 2.0.0.1,5,1.1.1.1
+# Range: Add upper boundary
+0 ipset -A test 2.1.0.0,128,2.2.2.2
+# Range: Test lower boundary
+0 ipset -T test 2.0.0.1,5,1.1.1.1
+# Range: Test upper boundary
+0 ipset -T test 2.1.0.0,128,2.2.2.2
+# Range: Test value not added to the set
+1 ipset -T test 2.0.0.1,5,1.1.1.2
+# Range: Test value not added to the set
+1 ipset -T test 2.0.0.1,6,1.1.1.1
+# Range: Test value not added to the set
+1 ipset -T test 2.0.0.2,6,1.1.1.1
+# Range: Test value before lower boundary
+1 ipset -T test 2.0.0.0,5,1.1.1.1
+# Range: Test value after upper boundary
+1 ipset -T test 2.1.0.1,128,2.2.2.2
+# Range: Try to add value before lower boundary
+1 ipset -A test 2.0.0.0,5,1.1.1.1
+# Range: Try to add value after upper boundary
+1 ipset -A test 2.1.0.1,128,2.2.2.2
+# Range: Delete test test
+0 ipset -X test
+# Network: Try to create a set from an invalid network
+2 ipset -N test ipportiphash --network 2.0.0.0/15
+# Network: Create a set from a valid network
+0 ipset -N test ipportiphash --network 2.0.0.0/16
+# Network: Add lower boundary
+0 ipset -A test 2.0.0.0,5,1.1.1.1
+# Network: Add upper boundary
+0 ipset -A test 2.0.255.255,128,2.2.2.2
+# Network: Test lower boundary
+0 ipset -T test 2.0.0.0,5,1.1.1.1
+# Network: Test upper boundary
+0 ipset -T test 2.0.255.255,128,2.2.2.2
+# Network: Test value not added to the set
+1 ipset -T test 2.0.0.0,5,1.1.1.2
+# Network: Test value not added to the set
+1 ipset -T test 2.0.0.0,6,1.1.1.1
+# Network: Test value before lower boundary
+1 ipset -T test 1.255.255.255,5,1.1.1.1
+# Network: Test value after upper boundary
+1 ipset -T test 2.1.0.0,128,2.2.2.2
+# Network: Try to add value before lower boundary
+1 ipset -A test 1.255.255.255,5,1.1.1.1
+# Network: Try to add value after upper boundary
+1 ipset -A test 2.1.0.0,128,2.2.2.2
+# Network: Delete test set
+0 ipset -X test
+# eof
diff --git a/tests/ipportnethash.t b/tests/ipportnethash.t
new file mode 100644 (file)
index 0000000..b7d64ff
--- /dev/null
@@ -0,0 +1,55 @@
+# Range: Try to create from an invalid range
+2 ipset -N test ipportnethash --from 2.0.0.1 --to 2.1.0.1
+# Range: Create a set from a valid range
+0 ipset -N test ipportnethash --from 2.0.0.1 --to 2.1.0.0
+# Range: Add lower boundary
+0 ipset -A test 2.0.0.1,5,1.1.1.1/24
+# Range: Add upper boundary
+0 ipset -A test 2.1.0.0,128,2.2.2.2/12
+# Range: Test lower boundary
+0 ipset -T test 2.0.0.1,5,1.1.1.2
+# Range: Test upper boundary
+0 ipset -T test 2.1.0.0,128,2.2.2.0
+# Range: Test value not added to the set
+1 ipset -T test 2.0.0.1,5,1.1.0.255
+# Range: Test value not added to the set
+1 ipset -T test 2.0.0.1,6,1.1.1.1
+# Range: Test value not added to the set
+1 ipset -T test 2.0.0.2,6,1.1.1.1
+# Range: Test value before lower boundary
+1 ipset -T test 2.0.0.0,5,1.1.1.1
+# Range: Test value after upper boundary
+1 ipset -T test 2.1.0.1,128,2.2.2.2
+# Range: Try to add value before lower boundary
+1 ipset -A test 2.0.0.0,5,1.1.1.1/24
+# Range: Try to add value after upper boundary
+1 ipset -A test 2.1.0.1,128,2.2.2.2/12
+# Range: Delete test test
+0 ipset -X test
+# Network: Try to create a set from an invalid network
+2 ipset -N test ipportnethash --network 2.0.0.0/15
+# Network: Create a set from a valid network
+0 ipset -N test ipportnethash --network 2.0.0.0/16
+# Network: Add lower boundary
+0 ipset -A test 2.0.0.0,5,1.1.1.1/24
+# Network: Add upper boundary
+0 ipset -A test 2.0.255.255,128,2.2.2.2/12
+# Network: Test lower boundary
+0 ipset -T test 2.0.0.0,5,1.1.1.2
+# Network: Test upper boundary
+0 ipset -T test 2.0.255.255,128,2.2.2.0
+# Network: Test value not added to the set
+1 ipset -T test 2.0.0.0,5,1.1.0.255
+# Network: Test value not added to the set
+1 ipset -T test 2.0.0.0,6,1.1.1.1
+# Network: Test value before lower boundary
+1 ipset -T test 1.255.255.255,5,1.1.1.1
+# Network: Test value after upper boundary
+1 ipset -T test 2.1.0.0,128,2.2.2.2
+# Network: Try to add value before lower boundary
+1 ipset -A test 1.255.255.255,5,1.1.1.1/24
+# Network: Try to add value after upper boundary
+1 ipset -A test 2.1.0.0,128,2.2.2.2/12
+# Network: Delete test set
+0 ipset -X test
+# eof
index 76cac54bb094b24dd4e69a4a0f955e562f9062a4..0e661ce744af14076342dc0951bc90da6f2ea386 100644 (file)
 1 ipset -T test 2.0.0.2
 # Timeout: Test value not added to the set
 1 ipset -T test 192.168.68.70
+# Timeout: Add entry with 3s timeout value
+0 ipset -A test 2.0.0.2,3
+# Timeout: Test entry added with 3s timeout
+0 ipset -T test 2.0.0.2
+# Timeout: Sleep 4s so that entry can time out
+0 sleep 4
+# Timeout: Test entry added with 3s timeout
+1 ipset -T test 2.0.0.2
 # Timeout: Delete test set
 0 ipset -X test
 # eof
index b8aeef2f4cf3ff70213a3245e086758152cd4b0f..66ee3257cf2ae616ec0e6252b9f3fe7c5544ea3e 100644 (file)
@@ -13,7 +13,7 @@
 # Test value not added to the set
 1 ipset -T test 192.168.68.70
 # Add IP range
-0 ipset -A test 3.0.0.0:3.0.0.2
+0 ipset -A test 3.0.0.0-3.0.0.2
 # Test the three members of the range: first
 0 ipset -T test 3.0.0.0
 # Test the three members of the range: second
 0 ipset -T test 192.168.68.71
 # Delete a network from the middle
 0 ipset -D test 192.168.68.70/30
-# Test element from the middle
+# Test lower bound of deleted network
+1 ipset -T test 192.168.68.68
+# Test upper bound of deleted network
 1 ipset -T test 192.168.68.71
+# Test element before lower bound of deleted network
+0 ipset -T test 192.168.68.67
+# Test element after upper bound of deleted network
+0 ipset -T test 192.168.68.72
 # Delete test set
 0 ipset -X test
 # eof
index 035160a7ae4b4d3394788624bc9b8efbed976761..049eaee71424eaf916bb7e40e9bfc3c9f904368f 100644 (file)
 1 ipset -A test 2.0.0.0
 # Range: Try to add value after upper boundary
 1 ipset -A test 2.1.0.1
+# Range: Try to add value with MAC
+0 ipset -A test 2.0.0.2,00:11:22:33:44:55
+# Range: Test value with invalid MAC
+1 ipset -T test 2.0.0.2,00:11:22:33:44:56
+# Range: Test value with valid MAC
+0 ipset -T test 2.0.0.2,00:11:22:33:44:55
 # Range: Delete test test
 0 ipset -X test
 # Network: Try to create a set from an invalid network
index 4cd586755e7f17c45af0c983a016a15964a87b5a..ef213f9058ae22e80a77879d80b985824722d064 100644 (file)
@@ -10,6 +10,8 @@
 0 ipset -T test 192.168.68.95
 # Test value not added to the set
 1 ipset -T test 2.0.1.0
+# Try to add IP address
+2 ipset -A test 2.0.0.1
 # Delete test set
 0 ipset -X test
 # eof
index 028e9684f01bf325e388e7fb7b22defd99a71b3c..4f2a2d273a0fa09486cd9cfd39cbfa22f9ea9b71 100755 (executable)
@@ -1,9 +1,15 @@
-#!/bin/sh
+#!/bin/bash
 
 tests="init"
 tests+=" ipmap macipmap portmap"
 tests+=" iphash nethash ipporthash"
+tests+=" ipportiphash ipportnethash"
 tests+=" iptree iptreemap"
+tests+=" setlist"
+
+if [ "$1" ]; then
+       tests="init $@"
+fi
 
 for types in $tests; do
     ipset -X test >/dev/null 2>&1
@@ -24,7 +30,7 @@ for types in $tests; do
        r=$?
        # echo $ret $r
        if [ "$ret" = "$r" ]; then
-               echo "OK"
+               echo "passed"
        else
                echo "FAILED"
                echo "Failed test: $cmd"
@@ -33,6 +39,8 @@ for types in $tests; do
        # sleep 1
     done < $types.t
 done
+# Remove test sets created by setlist.t
+ipset -X
 for x in $tests; do
        case $x in
        init)
@@ -43,5 +51,5 @@ for x in $tests; do
        esac
 done
 rmmod ip_set >/dev/null 2>&1
-echo "All tests are OK"
+echo "All tests are passed"
 
diff --git a/tests/setlist.t b/tests/setlist.t
new file mode 100644 (file)
index 0000000..785dc13
--- /dev/null
@@ -0,0 +1,31 @@
+# Setlist: Create base set foo
+0 ipset -N foo ipmap --from 2.0.0.1 --to 2.1.0.0
+# Setlist: Create base set bar
+0 ipset -N bar iphash
+# Setlist: Create setlist kind of set
+0 ipset -N test setlist
+# Setlist: Add foo set to setlist
+0 ipset -A test foo
+# Setlist: Test foo set in setlist
+0 ipset -T test foo
+# Setlist: Try to delete foo set
+1 ipset -X foo
+# Setlist: Add bar set to setlist, after foo
+0 ipset -A test bar
+# Setlist: Test bar,after,foo
+0 ipset -T test bar,after,foo
+# Setlist: Test foo,before,bar
+0 ipset -T test foo,before,bar
+# Setlist: Test bar,before,foo
+1 ipset -T test bar,before,foo
+# Setlist: Test foo,after,bar
+1 ipset -T test foo,after,bar
+# Setlist: Delete bar,before,foo
+1 ipset -D test bar,before,foo
+# Setlist: Delete foo,after,bar
+1 ipset -D test foo,after,bar
+# Setlist: Delete bar,after,foo
+0 ipset -D test bar,after,foo
+# Setlist: Delete test test
+0 ipset -X test
+# eof