-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
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
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)
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
[ -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
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
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
.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
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
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
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.
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
.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.
.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
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.
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
#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>
#include <netdb.h>
#include <dlfcn.h>
#include <fcntl.h>
-/* #include <asm/bitops.h> */
#include "ipset.h"
#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 */
{"sorted", 0, 0, 's'},
{"quiet", 0, 0, 'q'},
{"binding", 1, 0, 'b'},
+ {"resolve", 0, 0, 'r'},
#ifdef IPSET_DEBUG
/* debug (if compiled with it) */
};
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.
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 */
{ 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++) {
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);
}
/* 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;
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;
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),
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] == ':')
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",
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",
/* 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;
/* 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);
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,
" 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);
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;
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
*/
#include <getopt.h>
-#include <sys/types.h>
-#include <netdb.h>
#include <linux/netfilter_ipv4/ip_set.h>
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))
* 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;
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");
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);
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)
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;
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);
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,
#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"
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;
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");
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,
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",
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 {
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);
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;
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));
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++)
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,
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);
* 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"
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");
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");
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",
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;
};
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;
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));
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;
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));
}
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,
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;
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));
}
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;
" [--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 = {
--- /dev/null
+/* 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);
+
+}
--- /dev/null
+/* 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);
+
+}
* 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>
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;
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");
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)
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;
}
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);
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));
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",
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;
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);
{
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");
}
* 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>
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;
}
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);
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");
#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>
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");
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,
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)
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;
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));
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) {
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,
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);
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 = {
* 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"
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");
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");
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);
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;
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;
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);
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,
parse_ip(ptr, ip);
free(saved);
- *ip = pack(*ip, cidr);
+ *ip = pack_ip_cidr(*ip, cidr);
}
static void usage(void)
#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>
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");
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,
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;
}
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++;
}
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));
--- /dev/null
+/* 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);
+
+}
-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
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
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
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
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
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
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
--- /dev/null
+#!/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
#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:"
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 { \
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*/
--- /dev/null
+#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 */
--- /dev/null
+#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*/
--- /dev/null
+#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 */
#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 */
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 {
#include <linux/netfilter_ipv4/ip_set.h>
#define SETTYPE_NAME "ipmap"
-#define MAX_RANGE 0x0000FFFF
struct ip_set_ipmap {
void *members; /* the ipmap proper */
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 {
ip_set_ip_t ip;
};
-static unsigned int
+static inline unsigned int
mask_to_bits(ip_set_ip_t mask)
{
unsigned int bits = 32;
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;
#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 */
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 {
--- /dev/null
+#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 */
--- /dev/null
+#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 */
#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 */
};
struct ip_set_req_iptreemap {
- ip_set_ip_t start;
+ ip_set_ip_t ip;
ip_set_ip_t end;
};
#include <linux/netfilter_ipv4/ip_set.h>
#define SETTYPE_NAME "macipmap"
-#define MAX_RANGE 0x0000FFFF
/* general flags */
#define IPSET_MACIP_MATCHUNSET 1
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 {
#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)
{
#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;
{
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);
{
BUG_ON(max_malloc_size == 0);
- if (bytes > max_malloc_size)
+ if (bytes > default_max_malloc_size)
vfree(data);
else
kfree(data);
#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 */
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 {
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 */
#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 {
};
struct ip_set_req_portmap {
- ip_set_ip_t port;
+ ip_set_ip_t ip;
};
#endif /* __IP_SET_PORTMAP_H */
--- /dev/null
+#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 */
#include <linux/skbuff.h>
#include <linux/random.h>
#include <linux/jhash.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <linux/semaphore.h>
#endif
#include <linux/spinlock.h>
-#include <linux/vmalloc.h>
#define ASSERT_READ_LOCK(x)
#define ASSERT_WRITE_LOCK(x)
+#include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_set.h>
static struct list_head set_type_list; /* all registered sets */
&& 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)
&& 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)
&& flags[i]
&& follow_bindings(index, set, ip));
read_unlock_bh(&ip_set_lock);
+
+ return res;
}
/* Register and deregister settype */
}
+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
*/
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));
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),
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),
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.
}
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.
*/
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;
};
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);
vfree(ip_set_hash);
return res;
}
+
return 0;
}
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);
-/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include <linux/moduleparam.h>
#include <linux/ip.h>
#include <linux/skbuff.h>
-#include <linux/version.h>
#include <linux/jhash.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <linux/spinlock.h>
-#include <linux/vmalloc.h>
#include <linux/random.h>
#include <net/ip.h>
-#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_hashes.h>
#include <linux/netfilter_ipv4/ip_set_iphash.h>
static int limit = MAX_RANGE;
static inline __u32
-jhash_ip(const struct ip_set_iphash *map, uint16_t i, ip_set_ip_t ip)
-{
- return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
-}
-
-static inline __u32
-hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+iphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
{
struct ip_set_iphash *map = set->data;
__u32 id;
}
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;
}
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;
if (!ip)
return -ERANGE;
- id = hash_id(set, ip, hash_ip);
+ id = iphash_id(set, hash_ip, ip);
if (id == UINT_MAX)
return -EEXIST;
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>");
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)
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
* Patrick Schaaf <bof@bof.de>
- * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ * Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/skbuff.h>
-#include <linux/version.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <linux/spinlock.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_bitmaps.h>
#include <linux/netfilter_ipv4/ip_set_ipmap.h>
static inline ip_set_ip_t
}
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;
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;
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;
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) {
} 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;
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)
-/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/skbuff.h>
-#include <linux/version.h>
#include <linux/jhash.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <linux/spinlock.h>
-#include <linux/vmalloc.h>
#include <linux/random.h>
#include <net/ip.h>
-#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_hashes.h>
#include <linux/netfilter_ipv4/ip_set_ipporthash.h>
+#include <linux/netfilter_ipv4/ip_set_getport.h>
static int limit = MAX_RANGE;
-/* We must handle non-linear skbs */
-static inline ip_set_ip_t
-get_port(const struct sk_buff *skb, u_int32_t flags)
-{
- struct iphdr *iph = ip_hdr(skb);
- u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
-
- switch (iph->protocol) {
- case IPPROTO_TCP: {
- struct tcphdr tcph;
-
- /* See comments at tcp_match in ip_tables.c */
- if (offset)
- return INVALID_PORT;
-
- if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
- /* No choice either */
- return INVALID_PORT;
-
- return ntohs(flags & IPSET_SRC ?
- tcph.source : tcph.dest);
- }
- case IPPROTO_UDP: {
- struct udphdr udph;
-
- if (offset)
- return INVALID_PORT;
-
- if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
- /* No choice either */
- return INVALID_PORT;
-
- return ntohs(flags & IPSET_SRC ?
- udph.source : udph.dest);
- }
- default:
- return INVALID_PORT;
- }
-}
-
-static inline __u32
-jhash_ip(const struct ip_set_ipporthash *map, uint16_t i, ip_set_ip_t ip)
-{
- return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
-}
-
-#define HASH_IP(map, ip, port) (port + ((ip - ((map)->first_ip)) << 16))
-
static inline __u32
-hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
- ip_set_ip_t *hash_ip)
+ipporthash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
+ ip_set_ip_t ip, ip_set_ip_t port)
{
struct ip_set_ipporthash *map = set->data;
__u32 id;
u_int16_t i;
ip_set_ip_t *elem;
- *hash_ip = HASH_IP(map, ip, port);
+ *hash_ip = pack_ip_port(map, ip, port);
DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
}
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;
}
}
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;
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;
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>");
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)
--- /dev/null
+/* 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)
--- /dev/null
+/* 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)
-/* 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
/* 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;
} 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;
|| 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]) { \
} 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;
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)
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]) { \
} 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;
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++) { \
#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;
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;
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;
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;
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;
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;
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;
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;
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;
LOOP_WALK_END;
}
-static struct ip_set_type ip_set_iptree = {
- .typename = SETTYPE_NAME,
- .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
- .protocol_version = IP_SET_PROTOCOL_VERSION,
- .create = &create,
- .destroy = &destroy,
- .flush = &flush,
- .reqsize = sizeof(struct ip_set_req_iptree),
- .addip = &addip,
- .addip_kernel = &addip_kernel,
- .delip = &delip,
- .delip_kernel = &delip_kernel,
- .testip = &testip,
- .testip_kernel = &testip_kernel,
- .header_size = sizeof(struct ip_set_req_iptree_create),
- .list_header = &list_header,
- .list_members_size = &list_members_size,
- .list_members = &list_members,
- .me = THIS_MODULE,
-};
+IP_SET_TYPE(iptree, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
* index 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)
}
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;
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;
}
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;
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;
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;
}
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;
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;
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
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;
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;
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;
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;
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;
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;
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;
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>");
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
* Patrick Schaaf <bof@bof.de>
* Martin Josefsson <gandalf@wlug.westbo.se>
- * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ * Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/skbuff.h>
-#include <linux/version.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <linux/spinlock.h>
#include <linux/if_ether.h>
-#include <linux/vmalloc.h>
-#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_bitmaps.h>
#include <linux/netfilter_ipv4/ip_set_macipmap.h>
static int
-testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
+macipmap_utest(struct ip_set *set, const void *data, size_t size,
+ ip_set_ip_t *hash_ip)
{
- struct ip_set_macipmap *map = set->data;
- struct ip_set_macip *table = map->members;
+ const struct ip_set_macipmap *map = set->data;
+ const struct ip_set_macip *table = map->members;
const struct ip_set_req_macipmap *req = data;
- if (size != sizeof(struct ip_set_req_macipmap)) {
- ip_set_printk("data length wrong (want %zu, have %zu)",
- sizeof(struct ip_set_req_macipmap),
- size);
- return -EINVAL;
- }
-
if (req->ip < map->first_ip || req->ip > map->last_ip)
return -ERANGE;
}
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;
/* 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;
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;
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)
-/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include <linux/moduleparam.h>
#include <linux/ip.h>
#include <linux/skbuff.h>
-#include <linux/version.h>
#include <linux/jhash.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <linux/spinlock.h>
-#include <linux/vmalloc.h>
#include <linux/random.h>
#include <net/ip.h>
-#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_hashes.h>
#include <linux/netfilter_ipv4/ip_set_nethash.h>
static int limit = MAX_RANGE;
static inline __u32
-jhash_ip(const struct ip_set_nethash *map, uint16_t i, ip_set_ip_t ip)
-{
- return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
-}
-
-static inline __u32
-hash_id_cidr(struct ip_set_nethash *map,
- ip_set_ip_t ip,
- unsigned char cidr,
- ip_set_ip_t *hash_ip)
+nethash_id_cidr(const struct ip_set_nethash *map,
+ ip_set_ip_t *hash_ip,
+ ip_set_ip_t ip,
+ uint8_t cidr)
{
__u32 id;
u_int16_t i;
ip_set_ip_t *elem;
- *hash_ip = pack(ip, cidr);
+ *hash_ip = pack_ip_cidr(ip, cidr);
for (i = 0; i < map->probes; i++) {
id = jhash_ip(map, i, *hash_ip) % map->hashsize;
}
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;
}
}
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;
}
}
}
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>");
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)
-/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/skbuff.h>
-#include <linux/version.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <net/ip.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/netfilter_ipv4/ip_set_bitmaps.h>
#include <linux/netfilter_ipv4/ip_set_portmap.h>
-
-/* We must handle non-linear skbs */
-static inline ip_set_ip_t
-get_port(const struct sk_buff *skb, u_int32_t flags)
-{
- struct iphdr *iph = ip_hdr(skb);
- u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
- switch (iph->protocol) {
- case IPPROTO_TCP: {
- struct tcphdr tcph;
-
- /* See comments at tcp_match in ip_tables.c */
- if (offset)
- return INVALID_PORT;
-
- if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
- /* No choice either */
- return INVALID_PORT;
-
- return ntohs(flags & IPSET_SRC ?
- tcph.source : tcph.dest);
- }
- case IPPROTO_UDP: {
- struct udphdr udph;
-
- if (offset)
- return INVALID_PORT;
-
- if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
- /* No choice either */
- return INVALID_PORT;
-
- return ntohs(flags & IPSET_SRC ?
- udph.source : udph.dest);
- }
- default:
- return INVALID_PORT;
- }
-}
+#include <linux/netfilter_ipv4/ip_set_getport.h>
static inline int
-__testport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
+portmap_test(const struct ip_set *set, ip_set_ip_t *hash_port,
+ ip_set_ip_t port)
{
- struct ip_set_portmap *map = set->data;
+ const struct ip_set_portmap *map = set->data;
- if (port < map->first_port || port > map->last_port)
+ if (port < map->first_ip || port > map->last_ip)
return -ERANGE;
*hash_port = port;
DP("set: %s, port:%u, %u", set->name, port, *hash_port);
- return !!test_bit(port - map->first_port, map->members);
+ return !!test_bit(port - map->first_ip, map->members);
}
-static int
-testport(struct ip_set *set, const void *data, size_t size,
- ip_set_ip_t *hash_port)
-{
- const struct ip_set_req_portmap *req = data;
-
- if (size != sizeof(struct ip_set_req_portmap)) {
- ip_set_printk("data length wrong (want %zu, have %zu)",
- sizeof(struct ip_set_req_portmap),
- size);
- return -EINVAL;
- }
- return __testport(set, req->port, hash_port);
-}
-
-static int
-testport_kernel(struct ip_set *set,
- const struct sk_buff *skb,
- ip_set_ip_t *hash_port,
- const u_int32_t *flags,
- unsigned char index)
-{
- int res;
- ip_set_ip_t port = get_port(skb, flags[index]);
-
- DP("flag %s port %u", flags[index] & IPSET_SRC ? "SRC" : "DST", port);
- if (port == INVALID_PORT)
+#define KADT_CONDITION \
+ if (ip == INVALID_PORT) \
return 0;
- res = __testport(set, port, hash_port);
-
- return (res < 0 ? 0 : res);
-}
+UADT(portmap, test)
+KADT(portmap, test, get_port)
static inline int
-__addport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
+portmap_add(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port)
{
struct ip_set_portmap *map = set->data;
- if (port < map->first_port || port > map->last_port)
+ if (port < map->first_ip || port > map->last_ip)
return -ERANGE;
- if (test_and_set_bit(port - map->first_port, map->members))
+ if (test_and_set_bit(port - map->first_ip, map->members))
return -EEXIST;
*hash_port = port;
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;
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)
--- /dev/null
+/* 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)
# Range: Create a set from a valid range
0 ipset -N test ipporthash --from 2.0.0.1 --to 2.1.0.0
# Range: Add lower boundary
-0 ipset -A test 2.0.0.1:5
+0 ipset -A test 2.0.0.1,5
# Range: Add upper boundary
-0 ipset -A test 2.1.0.0:128
+0 ipset -A test 2.1.0.0,128
# Range: Test lower boundary
-0 ipset -T test 2.0.0.1:5
+0 ipset -T test 2.0.0.1,5
# Range: Test upper boundary
-0 ipset -T test 2.1.0.0:128
+0 ipset -T test 2.1.0.0,128
# Range: Test value not added to the set
-1 ipset -T test 2.0.0.1:4
+1 ipset -T test 2.0.0.1,4
# Range: Test value not added to the set
-1 ipset -T test 2.0.0.1:6
+1 ipset -T test 2.0.0.1,6
# Range: Test value before lower boundary
-1 ipset -T test 2.0.0.0:5
+1 ipset -T test 2.0.0.0,5
# Range: Test value after upper boundary
-1 ipset -T test 2.1.0.1:128
+1 ipset -T test 2.1.0.1,128
# Range: Try to add value before lower boundary
-1 ipset -A test 2.0.0.0:5
+1 ipset -A test 2.0.0.0,5
# Range: Try to add value after upper boundary
-1 ipset -A test 2.1.0.1:128
+1 ipset -A test 2.1.0.1,128
# Range: Delete test test
0 ipset -X test
# Network: Try to create a set from an invalid network
# Network: Create a set from a valid network
0 ipset -N test ipporthash --network 2.0.0.0/16
# Network: Add lower boundary
-0 ipset -A test 2.0.0.0:5
+0 ipset -A test 2.0.0.0,5
# Network: Add upper boundary
-0 ipset -A test 2.0.255.255:128
+0 ipset -A test 2.0.255.255,128
# Network: Test lower boundary
-0 ipset -T test 2.0.0.0:5
+0 ipset -T test 2.0.0.0,5
# Network: Test upper boundary
-0 ipset -T test 2.0.255.255:128
+0 ipset -T test 2.0.255.255,128
# Network: Test value not added to the set
-1 ipset -T test 2.0.0.0:4
+1 ipset -T test 2.0.0.0,4
# Network: Test value not added to the set
-1 ipset -T test 2.0.0.0:6
+1 ipset -T test 2.0.0.0,6
# Network: Test value before lower boundary
-1 ipset -T test 1.255.255.255:5
+1 ipset -T test 1.255.255.255,5
# Network: Test value after upper boundary
-1 ipset -T test 2.1.0.0:128
+1 ipset -T test 2.1.0.0,128
# Network: Try to add value before lower boundary
-1 ipset -A test 1.255.255.255:5
+1 ipset -A test 1.255.255.255,5
# Network: Try to add value after upper boundary
-1 ipset -A test 2.1.0.0:128
+1 ipset -A test 2.1.0.0,128
# Network: Delete test set
0 ipset -X test
# eof
--- /dev/null
+# 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
--- /dev/null
+# 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
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
# Test value not added to the set
1 ipset -T test 192.168.68.70
# Add IP range
-0 ipset -A test 3.0.0.0:3.0.0.2
+0 ipset -A test 3.0.0.0-3.0.0.2
# Test the three members of the range: first
0 ipset -T test 3.0.0.0
# Test the three members of the range: second
0 ipset -T test 192.168.68.71
# Delete a network from the middle
0 ipset -D test 192.168.68.70/30
-# Test element from the middle
+# Test lower bound of deleted network
+1 ipset -T test 192.168.68.68
+# Test upper bound of deleted network
1 ipset -T test 192.168.68.71
+# Test element before lower bound of deleted network
+0 ipset -T test 192.168.68.67
+# Test element after upper bound of deleted network
+0 ipset -T test 192.168.68.72
# Delete test set
0 ipset -X test
# eof
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
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
-#!/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
r=$?
# echo $ret $r
if [ "$ret" = "$r" ]; then
- echo "OK"
+ echo "passed"
else
echo "FAILED"
echo "Failed test: $cmd"
# sleep 1
done < $types.t
done
+# Remove test sets created by setlist.t
+ipset -X
for x in $tests; do
case $x in
init)
esac
done
rmmod ip_set >/dev/null 2>&1
-echo "All tests are OK"
+echo "All tests are passed"
--- /dev/null
+# 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