summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
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>2008-10-20 10:00:26 +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>2008-10-20 10:00:26 +0000
commita96e4fca10506462df4ee4035f0f86f09bd9dc34 (patch)
tree103bed0a7ae3608675f371d2ac91f3fa7f3a58cc
parentbc2ddd2d8da1252e78a1f25bd91c1e3cd8016ead (diff)
ipset 2.4 release
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
-rw-r--r--ChangeLog16
-rw-r--r--Makefile27
-rw-r--r--ipset.8217
-rw-r--r--ipset.c98
-rw-r--r--ipset.h5
-rw-r--r--ipset_iphash.c31
-rw-r--r--ipset_ipmap.c56
-rw-r--r--ipset_ipporthash.c63
-rw-r--r--ipset_ipportiphash.c360
-rw-r--r--ipset_ipportnethash.c428
-rw-r--r--ipset_iptree.c43
-rw-r--r--ipset_iptreemap.c32
-rw-r--r--ipset_macipmap.c50
-rw-r--r--ipset_nethash.c36
-rw-r--r--ipset_portmap.c59
-rw-r--r--ipset_setlist.c219
-rw-r--r--kernel/ChangeLog17
-rw-r--r--kernel/Config.in.ipset3
-rw-r--r--kernel/Kbuild6
-rw-r--r--kernel/Kconfig.ipset24
-rw-r--r--kernel/Makefile9
-rw-r--r--kernel/Makefile.ipset3
-rwxr-xr-xkernel/expand_macros.pl17
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set.h86
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_bitmaps.h119
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_getport.h48
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_hashes.h300
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_iphash.h3
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h6
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_ipporthash.h4
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_ipportiphash.h38
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_ipportnethash.h41
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_iptree.h1
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_iptreemap.h2
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_macipmap.h2
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_malloc.h8
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_nethash.h33
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_portmap.h9
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_setlist.h26
-rw-r--r--kernel/ip_set.c76
-rw-r--r--kernel/ip_set_iphash.c339
-rw-r--r--kernel/ip_set_ipmap.c240
-rw-r--r--kernel/ip_set_ipporthash.c455
-rw-r--r--kernel/ip_set_ipportiphash.c212
-rw-r--r--kernel/ip_set_ipportnethash.c299
-rw-r--r--kernel/ip_set_iptree.c170
-rw-r--r--kernel/ip_set_iptreemap.c152
-rw-r--r--kernel/ip_set_macipmap.c255
-rw-r--r--kernel/ip_set_nethash.c422
-rw-r--r--kernel/ip_set_portmap.c293
-rw-r--r--kernel/ip_set_setlist.c332
-rw-r--r--tests/ipporthash.t40
-rw-r--r--tests/ipportiphash.t55
-rw-r--r--tests/ipportnethash.t55
-rw-r--r--tests/iptree.t8
-rw-r--r--tests/iptreemap.t10
-rw-r--r--tests/macipmap.t6
-rw-r--r--tests/nethash.t2
-rwxr-xr-xtests/runtest.sh14
-rw-r--r--tests/setlist.t31
60 files changed, 3656 insertions, 2355 deletions
diff --git a/ChangeLog b/ChangeLog
index 7d66ebe..93b1f01 100644
--- 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
diff --git a/Makefile b/Makefile
index 80f6ec1..a192216 100644
--- 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 2c4edcb..0d57869 100644
--- 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 bd23758..d57318a 100644
--- a/ipset.c
+++ b/ipset.c
@@ -11,11 +11,8 @@
#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 ad43f65..3e181c4 100644
--- 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))
diff --git a/ipset_iphash.c b/ipset_iphash.c
index 573ad63..6dbb84b 100644
--- a/ipset_iphash.c
+++ b/ipset_iphash.c
@@ -15,22 +15,12 @@
* 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,
diff --git a/ipset_ipmap.c b/ipset_ipmap.c
index d628767..f1586bb 100644
--- a/ipset_ipmap.c
+++ b/ipset_ipmap.c
@@ -19,10 +19,7 @@
#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);
diff --git a/ipset_ipporthash.c b/ipset_ipporthash.c
index c090744..1b92979 100644
--- a/ipset_ipporthash.c
+++ b/ipset_ipporthash.c
@@ -15,21 +15,12 @@
* 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
index 0000000..0bd2e9f
--- /dev/null
+++ b/ipset_ipportiphash.c
@@ -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
index 0000000..51297ff
--- /dev/null
+++ b/ipset_ipportnethash.c
@@ -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);
+
+}
diff --git a/ipset_iptree.c b/ipset_iptree.c
index 379c113..0c23c99 100644
--- a/ipset_iptree.c
+++ b/ipset_iptree.c
@@ -15,12 +15,9 @@
* 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");
}
diff --git a/ipset_iptreemap.c b/ipset_iptreemap.c
index 9448339..141210f 100644
--- a/ipset_iptreemap.c
+++ b/ipset_iptreemap.c
@@ -15,11 +15,9 @@
* 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");
diff --git a/ipset_macipmap.c b/ipset_macipmap.c
index a243dc4..7345f8b 100644
--- a/ipset_macipmap.c
+++ b/ipset_macipmap.c
@@ -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 = {
diff --git a/ipset_nethash.c b/ipset_nethash.c
index 1e7aa41..d1f3344 100644
--- a/ipset_nethash.c
+++ b/ipset_nethash.c
@@ -15,21 +15,13 @@
* 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)
diff --git a/ipset_portmap.c b/ipset_portmap.c
index 1237e52..d13cdb1 100644
--- a/ipset_portmap.c
+++ b/ipset_portmap.c
@@ -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
index 0000000..b82cd6c
--- /dev/null
+++ b/ipset_setlist.c
@@ -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);
+
+}
diff --git a/kernel/ChangeLog b/kernel/ChangeLog
index c020713..d034b34 100644
--- a/kernel/ChangeLog
+++ b/kernel/ChangeLog
@@ -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
diff --git a/kernel/Config.in.ipset b/kernel/Config.in.ipset
index 0758f0a..0f442e7 100644
--- a/kernel/Config.in.ipset
+++ b/kernel/Config.in.ipset
@@ -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
diff --git a/kernel/Kbuild b/kernel/Kbuild
index c7cb727..9757a4a 100644
--- a/kernel/Kbuild
+++ b/kernel/Kbuild
@@ -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
diff --git a/kernel/Kconfig.ipset b/kernel/Kconfig.ipset
index 2c6022a..8b27517 100644
--- a/kernel/Kconfig.ipset
+++ b/kernel/Kconfig.ipset
@@ -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
diff --git a/kernel/Makefile b/kernel/Makefile
index 60e5362..9ec91f6 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -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
diff --git a/kernel/Makefile.ipset b/kernel/Makefile.ipset
index bb3c131..fe42cc1 100644
--- a/kernel/Makefile.ipset
+++ b/kernel/Makefile.ipset
@@ -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
index 0000000..ea0f4b6
--- /dev/null
+++ b/kernel/expand_macros.pl
@@ -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
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set.h b/kernel/include/linux/netfilter_ipv4/ip_set.h
index b8c7202..c29a460 100644
--- a/kernel/include/linux/netfilter_ipv4/ip_set.h
+++ b/kernel/include/linux/netfilter_ipv4/ip_set.h
@@ -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
index 0000000..916cb80
--- /dev/null
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_bitmaps.h
@@ -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
index 0000000..9e322bf
--- /dev/null
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_getport.h
@@ -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
index 0000000..405784a
--- /dev/null
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_hashes.h
@@ -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 */
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_iphash.h b/kernel/include/linux/netfilter_ipv4/ip_set_iphash.h
index 7de854b..7551cb2 100644
--- a/kernel/include/linux/netfilter_ipv4/ip_set_iphash.h
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_iphash.h
@@ -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 {
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h b/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h
index e3390be..2f409d9 100644
--- a/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h
@@ -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;
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_ipporthash.h b/kernel/include/linux/netfilter_ipv4/ip_set_ipporthash.h
index b715c56..ccec14e 100644
--- a/kernel/include/linux/netfilter_ipv4/ip_set_ipporthash.h
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_ipporthash.h
@@ -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
index 0000000..4d794bf
--- /dev/null
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_ipportiphash.h
@@ -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
index 0000000..9c78a68
--- /dev/null
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_ipportnethash.h
@@ -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 */
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_iptree.h b/kernel/include/linux/netfilter_ipv4/ip_set_iptree.h
index 64e716b..de5cf47 100644
--- a/kernel/include/linux/netfilter_ipv4/ip_set_iptree.h
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_iptree.h
@@ -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 */
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_iptreemap.h b/kernel/include/linux/netfilter_ipv4/ip_set_iptreemap.h
index bef576a..a58bc4e 100644
--- a/kernel/include/linux/netfilter_ipv4/ip_set_iptreemap.h
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_iptreemap.h
@@ -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;
};
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_macipmap.h b/kernel/include/linux/netfilter_ipv4/ip_set_macipmap.h
index ee34c9b..82ea96d 100644
--- a/kernel/include/linux/netfilter_ipv4/ip_set_macipmap.h
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_macipmap.h
@@ -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 {
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_malloc.h b/kernel/include/linux/netfilter_ipv4/ip_set_malloc.h
index d22bed7..8bce667 100644
--- a/kernel/include/linux/netfilter_ipv4/ip_set_malloc.h
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_malloc.h
@@ -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);
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_nethash.h b/kernel/include/linux/netfilter_ipv4/ip_set_nethash.h
index 172ef02..eecd68b 100644
--- a/kernel/include/linux/netfilter_ipv4/ip_set_nethash.h
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_nethash.h
@@ -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 */
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_portmap.h b/kernel/include/linux/netfilter_ipv4/ip_set_portmap.h
index c17165c..1a15380 100644
--- a/kernel/include/linux/netfilter_ipv4/ip_set_portmap.h
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_portmap.h
@@ -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
index 0000000..55f0afb
--- /dev/null
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_setlist.h
@@ -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 */
diff --git a/kernel/ip_set.c b/kernel/ip_set.c
index a525518..c4fcc69 100644
--- a/kernel/ip_set.c
+++ b/kernel/ip_set.c
@@ -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>
@@ -30,10 +29,10 @@
#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);
diff --git a/kernel/ip_set_iphash.c b/kernel/ip_set_iphash.c
index 2ac6066..38b83ed 100644
--- a/kernel/ip_set_iphash.c
+++ b/kernel/ip_set_iphash.c
@@ -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
@@ -11,32 +11,23 @@
#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)
diff --git a/kernel/ip_set_ipmap.c b/kernel/ip_set_ipmap.c
index aeead3b..e1a1663 100644
--- a/kernel/ip_set_ipmap.c
+++ b/kernel/ip_set_ipmap.c
@@ -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
@@ -12,14 +12,13 @@
#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)
diff --git a/kernel/ip_set_ipporthash.c b/kernel/ip_set_ipporthash.c
index 4e656cd..1dd39c3 100644
--- a/kernel/ip_set_ipporthash.c
+++ b/kernel/ip_set_ipporthash.c
@@ -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
@@ -13,82 +13,32 @@
#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
index 0000000..1755c57
--- /dev/null
+++ b/kernel/ip_set_ipportiphash.c
@@ -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
index 0000000..3783bb8
--- /dev/null
+++ b/kernel/ip_set_ipportnethash.c
@@ -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)
diff --git a/kernel/ip_set_iptree.c b/kernel/ip_set_iptree.c
index 2e0a406..22a94d1 100644
--- a/kernel/ip_set_iptree.c
+++ b/kernel/ip_set_iptree.c
@@ -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>");
diff --git a/kernel/ip_set_iptreemap.c b/kernel/ip_set_iptreemap.c
index dedf8a4..4a13e4f 100644
--- a/kernel/ip_set_iptreemap.c
+++ b/kernel/ip_set_iptreemap.c
@@ -11,20 +11,19 @@
* 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>");
diff --git a/kernel/ip_set_macipmap.c b/kernel/ip_set_macipmap.c
index 33e2808..4b2b1de 100644
--- a/kernel/ip_set_macipmap.c
+++ b/kernel/ip_set_macipmap.c
@@ -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
@@ -13,33 +13,24 @@
#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)
diff --git a/kernel/ip_set_nethash.c b/kernel/ip_set_nethash.c
index ecdf369..a04857c 100644
--- a/kernel/ip_set_nethash.c
+++ b/kernel/ip_set_nethash.c
@@ -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
@@ -11,41 +11,32 @@
#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)
diff --git a/kernel/ip_set_portmap.c b/kernel/ip_set_portmap.c
index aeaabcd..79cc511 100644
--- a/kernel/ip_set_portmap.c
+++ b/kernel/ip_set_portmap.c
@@ -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>
@@ -22,102 +19,40 @@
#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
index 0000000..50bc368
--- /dev/null
+++ b/kernel/ip_set_setlist.c
@@ -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)
diff --git a/tests/ipporthash.t b/tests/ipporthash.t
index fc0a7d5..edbbb0c 100644
--- a/tests/ipporthash.t
+++ b/tests/ipporthash.t
@@ -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
@@ -29,25 +29,25 @@
# 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
index 0000000..5ffd08a
--- /dev/null
+++ b/tests/ipportiphash.t
@@ -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
index 0000000..b7d64ff
--- /dev/null
+++ b/tests/ipportnethash.t
@@ -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
diff --git a/tests/iptree.t b/tests/iptree.t
index 76cac54..0e661ce 100644
--- a/tests/iptree.t
+++ b/tests/iptree.t
@@ -38,6 +38,14 @@
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
diff --git a/tests/iptreemap.t b/tests/iptreemap.t
index b8aeef2..66ee325 100644
--- a/tests/iptreemap.t
+++ b/tests/iptreemap.t
@@ -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
@@ -38,8 +38,14 @@
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
diff --git a/tests/macipmap.t b/tests/macipmap.t
index 035160a..049eaee 100644
--- a/tests/macipmap.t
+++ b/tests/macipmap.t
@@ -20,6 +20,12 @@
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
diff --git a/tests/nethash.t b/tests/nethash.t
index 4cd5867..ef213f9 100644
--- a/tests/nethash.t
+++ b/tests/nethash.t
@@ -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
diff --git a/tests/runtest.sh b/tests/runtest.sh
index 028e968..4f2a2d2 100755
--- a/tests/runtest.sh
+++ b/tests/runtest.sh
@@ -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
index 0000000..785dc13
--- /dev/null
+++ b/tests/setlist.t
@@ -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