diff options
77 files changed, 1357 insertions, 1906 deletions
@@ -1,3 +1,8 @@ +4.0 + - New protocol is introduced to handle aligment issues properly + (bug reported by Georg Chini) + - Binding support is removed + 3.1 - Correct format specifiers and change %i to %d (Jan Engelhardt) @@ -20,7 +20,7 @@ ifndef V V=0 endif -IPSET_VERSION:=3.2 +IPSET_VERSION:=4.0 PREFIX:=/usr/local LIBDIR:=$(PREFIX)/lib @@ -60,11 +60,13 @@ EXTRA_WARN_FLAGS:=\ -Werror ifndef NO_EXTRA_WARN_FLAGS -WARN_FLAGS+=$(EXTRA_WARN_FLAGS) + WARN_FLAGS+=$(EXTRA_WARN_FLAGS) endif -CFLAGS:=$(COPT_FLAGS) $(WARN_FLAGS) -Ikernel/include -I. # -g -DIPSET_DEBUG #-pg +ABI_FLAGS:= +CFLAGS:=$(ABI_FLAGS) $(COPT_FLAGS) $(WARN_FLAGS) -Ikernel/include -I. # -g -DIPSET_DEBUG SH_CFLAGS:=$(CFLAGS) -fPIC +LDFLAGS:=$(ABI_FLAGS) SETTYPES:=ipmap portmap macipmap SETTYPES+=iptree iptreemap SETTYPES+=iphash nethash ipporthash ipportiphash ipportnethash @@ -26,13 +26,11 @@ ipset \- administration tool for IP sets .br .BR "ipset -[EW] " "from-set to-set" .br -.BR "ipset -[ADU] " "set entry" -.br -.BR "ipset -B " "set entry -b binding" -.br -.BR "ipset -T " "set entry [-b binding]" +.BR "ipset -[ADT] " "set entry" .br .BR "ipset -R " +.br +.BR "ipset -[Vv] " .SH DESCRIPTION .B ipset is used to set up, maintain and inspect so called IP sets in the Linux @@ -40,19 +38,9 @@ kernel. Depending on the type, an IP set may store IP addresses, (TCP/UDP) port numbers or additional informations besides IP addresses: the word IP means a general term here. See the set type definitions below. .P -Any entry in a set can be bound to another set, which forms a relationship -between a set element and the set it is bound to. In order to define a -binding it is not required that the entry be already added to the set. -The sets may have a default binding, which is valid for every set element -for which there is no binding defined at all. -.P -IP set bindings pointing to sets and iptables matches and targets -referring to sets creates references, which protects the given sets in -the kernel. A set cannot be removed (destroyed) while there is a single -reference pointing to it. -.P -.B -Please note, binding sets is a deprecated feature and will be removed in a later release. Switch to the multidata type of sets from using bindings. +Iptables matches and targets referring to sets creates references, which +protects the given sets in the kernel. A set cannot be removed (destroyed) +while there is a single reference pointing to it. .SH OPTIONS The options that are recognized by .B ipset @@ -70,21 +58,13 @@ Create a set identified with setname and specified type. Type-specific options must be supplied. .TP .BI "-X, --destroy " "[\fIsetname\fP]" -Destroy the specified set, or all sets if none or the keyword -.B -:all: -is specified. -Before destroying the set, all bindings belonging to the -set elements and the default binding of the set are removed. +Destroy the specified set or all the sets if none is given. If the set has got references, nothing is done. .TP .BI "-F, --flush " "[\fIsetname\fP]" -Delete all entries from the specified set, or flush -all sets if none or the keyword -.B -:all: -is given. Bindings are not affected by the flush operation. +Delete all entries from the specified set or flush +all sets if none is given. .TP .BI "-E, --rename " "\fIfrom-setname\fP \fIto-setname\fP" Rename a set. Set identified by to-setname must not exist. @@ -95,102 +75,63 @@ 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 -all sets if none or the keyword -.B -:all: -is given. The -.B "-n, --numeric" -option can be used to suppress name lookups and generate numeric -output. When the +List the entries for the specified set, or for +all sets if none is given. The +.B "-r, --resolve" +option can be used to force name lookups (which may be slow). When the .B "-s, --sorted" option is given, the entries are listed sorted (if the given set type supports the operation). .TP .BI "-S, --save " "[\fIsetname\fP]" -Save the given set, or all sets if none or the keyword -.B -:all: -is specified to stdout in a format that --restore can read. +Save the given set, or all sets if none is given +to stdout in a format that --restore can read. .TP .BI "-R, --restore " Restore a saved session generated by --save. The saved session can be fed from stdin. When generating a session file please note that the supported commands -(create set, add element, bind) must appear in a strict order: first create +(create set and add element) must appear in a strict order: first create the set, then add all elements. Then create the next set, add all its elements -and so on. Finally you can list all binding commands. Also, it is a restore -operation, so the sets being restored must not exist. +and so on. Also, it is a restore operation, so the sets being restored must +not exist. .TP .BI "-A, --add " "\fIsetname\fP \fIIP\fP" -Add an IP to a set. +Add an IP entry to a set. .TP .BI "-D, --del " "\fIsetname\fP \fIIP\fP" -Delete an IP from a set. +Delete an IP entry from a set. .TP .BI "-T, --test " "\fIsetname\fP \fIIP -Test wether an IP is in a set or not. Exit status number is zero +Test wether an IP entry is in a set or not. Exit status number is zero if the tested IP is in the set and nonzero if it is missing from the set. .TP -.BI "-T, --test " "\fIsetname\fP \fIIP\fP \fI--binding\fP \fIto-setname\fP" -Test wether the IP belonging to the set points to the specified binding. -Exit status number is zero if the binding points to the specified set, -otherwise it is nonzero. The keyword -.B -:default: -can be used to test the default binding of the set. -.TP -.BI "-B, --bind " "\fIsetname\fP \fIIP\fP \fI--binding\fP \fIto-setname\fP" -Bind the IP in setname to to-setname. -.TP -.BI "-U, --unbind " "\fIsetname\fP \fIIP\fP" -Delete the binding belonging to IP in set setname. -.TP .BI "-H, --help " "[settype]" Print help and settype specific help if settype specified. +.TP +.BI "-V, -v, --version " +Print program version and protocol version. .P -At the -.B --B, -U -and -.B --T -commands you can use the token -.B -:default: -to bind, unbind or test the default binding of a set instead -of an IP. At the -.B --U -command you can use the token -.B -:all: -to destroy the bindings of all elements of a set. .SS "OTHER OPTIONS" The following additional options can be specified: .TP -.B "-b, --binding setname" -The option specifies the value of the binding for the -.B "-B" -binding command, for which it is a mandatory option. -You can use it in the -.B "-T" -test command as well to test bindings. +.B "-r, --resolve" +When listing sets, enforce name lookup. The +program will try to display the IP entries resolved to +host names or services (whenever applicable), which can trigger +.B +slow +DNS +lookups. .TP .B "-s, --sorted" Sorted output. When listing sets, entries are listed sorted. .TP .B "-n, --numeric" -Numeric output. When listing sets, bindings, IP addresses and -port numbers will be printed in numeric format. By default the -program will try to display them as host names, network names -or services (whenever applicable), which can trigger -.B -slow -DNS -lookups. +Numeric output. When listing sets, IP addresses and +port numbers will be printed in numeric format. This is the default. .TP .B "-q, --quiet" Suppress any output to stdout and stderr. ipset will still return @@ -224,6 +165,10 @@ When the optional parameter specified, network addresses will be stored in the set instead of IP addresses, and the from-IP parameter must be a network address. The CIDR-netmask value must be between 1-31. +.PP +Example: +.IP +ipset \-N test ipmap \-\-network 192.168.0.0/16 .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 @@ -319,6 +264,10 @@ parameter. In general higher probe value results better utilized hash while smaller value produces larger, sparser hash. +.PP +Example: +.IP +ipset \-N test iphash \-\-probes 2 .SS nethash The nethash set type uses a hash to store different size of network addresses. The @@ -538,7 +487,7 @@ 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 +.PP By the .I set @@ -562,8 +511,9 @@ 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 +.IP +iptables \-m set \-\-match\-set a src,dst \-j SET \-\-add-set b src,dst +.PP the match and target will skip any set in .I a and @@ -589,6 +539,8 @@ use the iphash set type. If you have got random size of netblocks, use nethash. .P Old separator tokens (':' and '%") are still accepted. +.P +Binding support is removed. .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 @@ -32,6 +32,11 @@ char program_name[] = "ipset"; char program_version[] = IPSET_VERSION; +static int protocol_version = 0; + +#define STREQ(a,b) (strncmp(a,b,IP_SET_MAXNAMELEN) == 0) +#define DONT_ALIGN (protocol_version == IP_SET_PROTOCOL_UNALIGNED) +#define ALIGNED(len) IPSET_VALIGN(len, DONT_ALIGN) /* The list of loaded set types */ static struct settype *all_settypes = NULL; @@ -65,7 +70,7 @@ static unsigned int global_option_offset = 0; static const char cmdflags[] = { ' ', /* CMD_NONE */ 'N', 'X', 'F', 'E', 'W', 'L', 'S', 'R', - 'A', 'D', 'T', 'B', 'U', 'H', 'V', + 'A', 'D', 'T', 'H', 'V', }; /* Options */ @@ -74,11 +79,10 @@ static const char cmdflags[] = { ' ', /* CMD_NONE */ #define OPT_SORTED 0x0002U /* -s */ #define OPT_QUIET 0x0004U /* -q */ #define OPT_DEBUG 0x0008U /* -z */ -#define OPT_BINDING 0x0010U /* -b */ #define OPT_RESOLVE 0x0020U /* -r */ -#define NUMBER_OF_OPT 6 +#define NUMBER_OF_OPT 5 static const char optflags[] = - { 'n', 's', 'q', 'z', 'b', 'r' }; + { 'n', 's', 'q', 'z', 'r' }; static struct option opts_long[] = { /* set operations */ @@ -97,15 +101,10 @@ static struct option opts_long[] = { {"del", 1, 0, 'D'}, {"test", 1, 0, 'T'}, - /* binding operations */ - {"bind", 1, 0, 'B'}, - {"unbind", 1, 0, 'U'}, - /* free options */ {"numeric", 0, 0, 'n'}, {"sorted", 0, 0, 's'}, {"quiet", 0, 0, 'q'}, - {"binding", 1, 0, 'b'}, {"resolve", 0, 0, 'r'}, #ifdef IPSET_DEBUG @@ -122,7 +121,7 @@ static struct option opts_long[] = { }; static char opts_short[] = - "-N:X::F::E:W:L::S::RA:D:T:B:U:nrsqzb:Vh::H::"; + "-N:X::F::E:W:L::S::RA:D:T:nrsqzvVh::H::"; /* Table of legal combinations of commands and options. If any of the * given commands make an option legal, that option is legal. @@ -133,22 +132,20 @@ static char opts_short[] = */ static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = { - /* -n -s -q -z -b */ - /*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'}, + /* -n -s -q -z -r */ + /*CREATE*/ {'x', 'x', ' ', ' ', 'x'}, + /*DESTROY*/ {'x', 'x', ' ', ' ', 'x'}, + /*FLUSH*/ {'x', 'x', ' ', ' ', 'x'}, + /*RENAME*/ {'x', 'x', ' ', ' ', 'x'}, + /*SWAP*/ {'x', 'x', ' ', ' ', 'x'}, + /*LIST*/ {' ', ' ', 'x', ' ', ' '}, + /*SAVE*/ {'x', 'x', ' ', ' ', 'x'}, + /*RESTORE*/ {'x', 'x', ' ', ' ', 'x'}, + /*ADD*/ {'x', 'x', ' ', ' ', 'x'}, + /*DEL*/ {'x', 'x', ' ', ' ', 'x'}, + /*TEST*/ {'x', 'x', ' ', ' ', 'x'}, + /*HELP*/ {'x', 'x', 'x', ' ', 'x'}, + /*VERSION*/ {'x', 'x', 'x', ' ', 'x'}, }; /* Main parser function */ @@ -451,25 +448,26 @@ static void check_protocolversion(void) { struct ip_set_req_version req_version; socklen_t size = sizeof(struct ip_set_req_version); - int sockfd = kernel_getsocket(); int res; + if (protocol_version) + return; + req_version.op = IP_SET_OP_VERSION; - res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size); + res = wrapped_getsockopt(&req_version, &size); - if (res != 0) { - ipset_printf("I'm of protocol version %u.\n" - "Kernel module is not loaded in, " - "cannot verify kernel version.", - IP_SET_PROTOCOL_VERSION); - return; - } - if (req_version.version != IP_SET_PROTOCOL_VERSION) + if (res != 0) + exit_error(OTHER_PROBLEM, + "Couldn't verify kernel module version!"); + + if (!(req_version.version == IP_SET_PROTOCOL_VERSION + || req_version.version == IP_SET_PROTOCOL_UNALIGNED)) exit_error(OTHER_PROBLEM, - "Kernel ipset code is of protocol version %u." + "Kernel ip_set module is of protocol version %u." "I'm of protocol version %u.\n" "Please upgrade your kernel and/or ipset(8) utillity.", req_version.version, IP_SET_PROTOCOL_VERSION); + protocol_version = req_version.version; } static void set_command(int *cmd, int newcmd) @@ -591,11 +589,6 @@ char *ip_tostring(ip_set_ip_t ip, unsigned options) return inet_ntoa(addr); } -char *binding_ip_tostring(struct set *set UNUSED, - ip_set_ip_t ip, unsigned options) -{ - return ip_tostring(ip, options); -} char *ip_tostring_numeric(ip_set_ip_t ip) { return ip_tostring(ip, OPT_NUMERIC); @@ -760,8 +753,7 @@ static struct settype *settype_find(const char *typename) DP("%s", typename); while (runner != NULL) { - if (strncmp(runner->typename, typename, - IP_SET_MAXNAMELEN) == 0) + if (STREQ(runner->typename, typename)) return runner; runner = runner->next; @@ -883,9 +875,7 @@ struct set *set_find_byname(const char *name) ip_set_id_t i; for (i = 0; i < max_sets; i++) - if (set_list[i] - && strncmp(set_list[i]->name, name, - IP_SET_MAXNAMELEN) == 0) { + if (set_list[i] != NULL && STREQ(set_list[i]->name, name)) { set = set_list[i]; break; } @@ -903,9 +893,7 @@ static ip_set_id_t set_find_free_index(const char *name) if (idx == IP_SET_INVALID_ID && set_list[i] == NULL) idx = i; - if (set_list[i] != NULL - && strncmp(set_list[i]->name, name, - IP_SET_MAXNAMELEN) == 0) + if (set_list[i] != NULL && STREQ(set_list[i]->name, name)) exit_error(PARAMETER_PROBLEM, "Set %s is already defined, cannot be restored", name); @@ -932,7 +920,7 @@ static void set_create(const char *name, struct settype *settype) DP("%s %s", name, settype->typename); req_create.op = IP_SET_OP_CREATE; - req_create.version = IP_SET_PROTOCOL_VERSION; + req_create.version = protocol_version; strcpy(req_create.name, name); strcpy(req_create.typename, settype->typename); @@ -956,14 +944,14 @@ static void set_restore_create(const char *name, struct settype *settype) { struct set *set; - DP("%s %s %u %u %u %u", name, settype->typename, + DP("%s %s %zu %zu %u %u", name, settype->typename, restore_offset, sizeof(struct ip_set_restore), settype->create_size, restore_size); /* Sanity checking */ if (restore_offset - + sizeof(struct ip_set_restore) - + settype->create_size > restore_size) + + ALIGNED(sizeof(struct ip_set_restore)) + + ALIGNED(settype->create_size) > restore_size) exit_error(PARAMETER_PROBLEM, "Giving up, restore file is screwed up!"); @@ -982,11 +970,11 @@ static void set_restore_create(const char *name, struct settype *settype) DP("name %s, restore index %u", restore_set->name, restore_set->index); /* Add settype data */ - memcpy(restore_data + restore_offset + sizeof(struct ip_set_restore), - settype->data, settype->create_size); + restore_offset += ALIGNED(sizeof(struct ip_set_restore)); + memcpy(restore_data + restore_offset, settype->data, settype->create_size); - restore_offset += sizeof(struct ip_set_restore) - + settype->create_size; + restore_offset += ALIGNED(settype->create_size); + DP("restore_offset: %zu", restore_offset); /* Add set to set_list */ set = ipset_malloc(sizeof(struct set)); @@ -1006,7 +994,7 @@ static void set_destroy(const char *name, unsigned op, unsigned cmd) DP("%s %s", cmd == CMD_DESTROY ? "destroy" : "flush", name); req.op = op; - req.version = IP_SET_PROTOCOL_VERSION; + req.version = protocol_version; strcpy(req.name, name); kernel_sendto(cmd, &req, sizeof(struct ip_set_req_std)); @@ -1024,7 +1012,7 @@ static void set_rename(const char *name, const char *newname, name, newname); req.op = op; - req.version = IP_SET_PROTOCOL_VERSION; + req.version = protocol_version; strcpy(req.name, name); strcpy(req.typename, newname); @@ -1062,7 +1050,7 @@ tryagain: } /* Get max_sets */ req_max_sets.op = IP_SET_OP_MAX_SETS; - req_max_sets.version = IP_SET_PROTOCOL_VERSION; + req_max_sets.version = protocol_version; strcpy(req_max_sets.set.name, name); size = sizeof(req_max_sets); kernel_getfrom(CMD_MAX_SETS, &req_max_sets, &size); @@ -1080,8 +1068,8 @@ tryagain: return 0; /* Get setnames */ - size = req_size = sizeof(struct ip_set_req_setnames) - + req_max_sets.sets * sizeof(struct ip_set_name_list); + size = req_size = ALIGNED(sizeof(struct ip_set_req_setnames)) + + req_max_sets.sets * ALIGNED(sizeof(struct ip_set_name_list)); data = ipset_malloc(size); ((struct ip_set_req_setnames *) data)->op = op; ((struct ip_set_req_setnames *) data)->index = *idx; @@ -1099,8 +1087,8 @@ tryagain: } /* Load in setnames */ - size = sizeof(struct ip_set_req_setnames); - while (size + sizeof(struct ip_set_name_list) <= req_size) { + size = ALIGNED(sizeof(struct ip_set_req_setnames)); + while (size + ALIGNED(sizeof(struct ip_set_name_list)) <= req_size) { name_list = (struct ip_set_name_list *) (data + size); set = ipset_malloc(sizeof(struct set)); @@ -1111,9 +1099,9 @@ tryagain: set_list[name_list->index] = set; DP("loaded %s, type %s, index %u", set->name, set->settype->typename, set->index); - size += sizeof(struct ip_set_name_list); + size += ALIGNED(sizeof(struct ip_set_name_list)); } - /* Size to get set members, bindings */ + /* Size to get set members */ size = ((struct ip_set_req_setnames *)data)->size; free(data); @@ -1123,36 +1111,7 @@ tryagain: /* * Save operation */ -static size_t save_bindings(void *data, size_t offset, size_t len) -{ - struct ip_set_hash_save *hash = - (struct ip_set_hash_save *) (data + offset); - struct set *set; - - DP("offset %u, len %u", offset, len); - if (offset + sizeof(struct ip_set_hash_save) > len) - exit_error(OTHER_PROBLEM, - "Save operation failed, try again later."); - - set = set_find_byid(hash->id); - 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), - set_list[hash->binding]->name); - - return sizeof(struct ip_set_hash_save); -} - -static size_t save_set(void *data, int *bindings, - size_t offset, size_t len) +static size_t save_set(void *data, size_t offset, size_t len) { struct ip_set_save *set_save = (struct ip_set_save *) (data + offset); @@ -1160,12 +1119,12 @@ static size_t save_set(void *data, int *bindings, struct settype *settype; size_t used; - DP("offset %u (%u/%u/%u), len %u", offset, + DP("offset %zu (%zu/%u/%u), len %zu", offset, sizeof(struct ip_set_save), set_save->header_size, set_save->members_size, len); - if (offset + sizeof(struct ip_set_save) > len - || offset + sizeof(struct ip_set_save) + if (offset + ALIGNED(sizeof(struct ip_set_save)) > len + || offset + ALIGNED(sizeof(struct ip_set_save)) + set_save->header_size + set_save->members_size > len) exit_error(OTHER_PROBLEM, "Save operation failed, try again later."); @@ -1173,8 +1132,7 @@ static size_t save_set(void *data, int *bindings, DP("index: %u", set_save->index); if (set_save->index == IP_SET_INVALID_ID) { /* Marker */ - *bindings = 1; - return sizeof(struct ip_set_save); + return ALIGNED(sizeof(struct ip_set_save)); } set = set_list[set_save->index]; if (!set) @@ -1183,7 +1141,7 @@ static size_t save_set(void *data, int *bindings, settype = set->settype; /* Init set header */ - used = sizeof(struct ip_set_save); + used = ALIGNED(sizeof(struct ip_set_save)); settype->initheader(set, data + offset + used); /* Print create set */ @@ -1192,44 +1150,18 @@ static size_t save_set(void *data, int *bindings, /* Print add IPs */ used += set_save->header_size; settype->saveips(set, data + offset + used, - set_save->members_size, OPT_NUMERIC); + set_save->members_size, OPT_NUMERIC, + DONT_ALIGN); return (used + set_save->members_size); } -static size_t save_default_bindings(void *data, int *bindings) -{ - struct ip_set_save *set_save = (struct ip_set_save *) data; - struct set *set; - - if (set_save->index == IP_SET_INVALID_ID) { - /* Marker */ - *bindings = 1; - return sizeof(struct ip_set_save); - } - - set = set_list[set_save->index]; - DP("%s, binding %u", set->name, set_save->binding); - if (set_save->binding != IP_SET_INVALID_ID) { - if (!set_list[set_save->binding]) - exit_error(OTHER_PROBLEM, - "Save set failed, try again later."); - - printf("-B %s %s -b %s\n", - set->name, IPSET_TOKEN_DEFAULT, - set_list[set_save->binding]->name); - } - return (sizeof(struct ip_set_save) - + set_save->header_size - + set_save->members_size); -} - static int try_save_sets(const char name[IP_SET_MAXNAMELEN]) { void *data = NULL; socklen_t size, req_size = 0; ip_set_id_t idx; - int res = 0, bindings = 0; + int res = 0; time_t now = time(NULL); /* Load set_list from kernel */ @@ -1237,15 +1169,17 @@ static int try_save_sets(const char name[IP_SET_MAXNAMELEN]) IP_SET_OP_SAVE_SIZE, CMD_SAVE); if (size) { - /* Get sets, bindings and print them */ + /* Get sets and print them */ /* Take into account marker */ - req_size = (size += sizeof(struct ip_set_save)); + req_size = (size += ALIGNED(sizeof(struct ip_set_save))); data = ipset_malloc(size); ((struct ip_set_req_list *) data)->op = IP_SET_OP_SAVE; ((struct ip_set_req_list *) data)->index = idx; res = kernel_getfrom_handleerrno(CMD_SAVE, data, &size); if (res != 0 || size != req_size) { + DP("Try again: res: %i, size %u, req_size: %u", + res, size, req_size); free(data); return -EAGAIN; } @@ -1255,17 +1189,8 @@ static int try_save_sets(const char name[IP_SET_MAXNAMELEN]) size = 0; while (size < req_size) { DP("size: %u, req_size: %u", size, req_size); - if (bindings) - size += save_bindings(data, size, req_size); - else - size += save_set(data, &bindings, size, req_size); + size += save_set(data, size, req_size); } - /* Re-read data to save default bindings */ - bindings = 0; - size = 0; - while (size < req_size && bindings == 0) - size += save_default_bindings(data + size, &bindings); - printf("COMMIT\n"); now = time(NULL); printf("# Completed on %s", ctime(&now)); @@ -1363,7 +1288,7 @@ static void set_restore(char *argv0) char buffer[1024]; char *ptr, *name = NULL; char cmd = ' '; - int first_pass, i, bindings = 0; + int first_pass, i; struct settype *settype = NULL; struct ip_set_req_setnames *header; ip_set_id_t idx; @@ -1378,8 +1303,7 @@ static void set_restore(char *argv0) IP_SET_OP_LIST_SIZE, CMD_RESTORE); restore_line = 0; - restore_size = sizeof(struct ip_set_req_setnames)/* header */ - + sizeof(struct ip_set_restore); /* marker */ + restore_size = ALIGNED(sizeof(struct ip_set_req_setnames)); /* header */ DP("restore_size: %u", restore_size); /* First pass: calculate required amount of data */ while (fgets(buffer, sizeof(buffer), in)) { @@ -1426,13 +1350,9 @@ static void set_restore(char *argv0) exit_error(PARAMETER_PROBLEM, "Missing settype in line %u\n", restore_line); - if (bindings) - exit_error(PARAMETER_PROBLEM, - "Invalid line %u: create must precede bindings\n", - restore_line); settype = check_set_typename(ptr); - restore_size += sizeof(struct ip_set_restore) - + settype->create_size; + restore_size += ALIGNED(sizeof(struct ip_set_restore)) + + ALIGNED(settype->create_size); DP("restore_size (N): %u", restore_size); break; } @@ -1443,20 +1363,10 @@ static void set_restore(char *argv0) "Add IP to set %s in line %u without " "preceding corresponding create set line\n", ptr, restore_line); - if (bindings) - exit_error(PARAMETER_PROBLEM, - "Invalid line %u: adding entries must precede bindings\n", - restore_line); - restore_size += settype->adt_size; + restore_size += ALIGNED(settype->adt_size); DP("restore_size (A): %u", restore_size); break; } - case 'B': { - bindings = 1; - restore_size += sizeof(struct ip_set_hash_save); - DP("restore_size (B): %u", restore_size); - break; - } default: { exit_error(PARAMETER_PROBLEM, "Unrecognized restore command in line %u\n", @@ -1468,12 +1378,13 @@ static void set_restore(char *argv0) if (!restore) exit_error(PARAMETER_PROBLEM, "Missing COMMIT line\n"); + restore_size += ALIGNED(sizeof(struct ip_set_restore)); /* marker */ DP("restore_size: %u", restore_size); restore_data = ipset_malloc(restore_size); header = (struct ip_set_req_setnames *) restore_data; header->op = IP_SET_OP_RESTORE; header->size = restore_size; - restore_offset = sizeof(struct ip_set_req_setnames); + restore_offset = ALIGNED(sizeof(struct ip_set_req_setnames)); /* Rewind to scan the file again */ fseek(in, 0L, SEEK_SET); @@ -1505,17 +1416,15 @@ static void set_restore(char *argv0) exit_error(PARAMETER_PROBLEM, "Broken restore file\n"); do_restore: - if (bindings == 0 - && restore_size == - (restore_offset + sizeof(struct ip_set_restore))) { + if (restore_size == (restore_offset + ALIGNED(sizeof(struct ip_set_restore)))) { /* No bindings */ struct ip_set_restore *marker = (struct ip_set_restore *) (restore_data + restore_offset); - DP("restore marker"); marker->index = IP_SET_INVALID_ID; marker->header_size = marker->members_size = 0; - restore_offset += sizeof(struct ip_set_restore); + restore_offset += ALIGNED(sizeof(struct ip_set_restore)); + DP("restore marker, restore_offset: %zu", restore_offset); } if (restore_size != restore_offset) exit_error(PARAMETER_PROBLEM, @@ -1547,8 +1456,10 @@ static struct set *set_adt_get(const char *name) DP("%s", name); + check_protocolversion(); + req_adt_get.op = IP_SET_OP_ADT_GET; - req_adt_get.version = IP_SET_PROTOCOL_VERSION; + req_adt_get.version = protocol_version; strcpy(req_adt_get.set.name, name); size = sizeof(struct ip_set_req_adt_get); @@ -1576,15 +1487,15 @@ static int set_adtip(struct set *set, const char *adt, DP("%s -> %s", set->name, adt); /* Alloc memory for the data to send */ - size = sizeof(struct ip_set_req_adt) + set->settype->adt_size ; - DP("alloc size %d", size); + size = ALIGNED(sizeof(struct ip_set_req_adt)) + set->settype->adt_size ; + DP("alloc size %zu", size); data = ipset_malloc(size); /* Fill out the request */ req_adt = (struct ip_set_req_adt *) data; req_adt->op = op; req_adt->index = set->index; - memcpy(data + sizeof(struct ip_set_req_adt), + memcpy(data + ALIGNED(sizeof(struct ip_set_req_adt)), set->settype->data, set->settype->adt_size); if (kernel_sendto_handleerrno(cmd, data, size) == -1) @@ -1622,155 +1533,22 @@ static void set_restore_add(struct set *set, const char *adt UNUSED) { DP("%s %s", set->name, adt); /* Sanity checking */ - if (restore_offset + set->settype->adt_size > restore_size) + if (restore_offset + ALIGNED(set->settype->adt_size) > restore_size) exit_error(PARAMETER_PROBLEM, "Giving up, restore file is screwed up!"); memcpy(restore_data + restore_offset, set->settype->data, set->settype->adt_size); - restore_set->members_size += set->settype->adt_size; - restore_offset += set->settype->adt_size; -} + restore_set->members_size += ALIGNED(set->settype->adt_size); + restore_offset += ALIGNED(set->settype->adt_size); -/* - * Send bind/unbind/test binding order to kernel for a set - */ -static int set_bind(struct set *set, const char *adt, - const char *binding, - unsigned op, unsigned cmd) -{ - struct ip_set_req_bind *req_bind; - size_t size; - void *data; - int res = 0; - - /* set may be null: '-U :all: :all:|:default:' */ - DP("(%s, %s) -> %s", set ? set->name : IPSET_TOKEN_ALL, adt, binding); - - /* Ugly */ - 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, - "%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] == ':') - /* Set default binding */ - size += IP_SET_MAXNAMELEN; - else if (!(op == IP_SET_OP_UNBIND_SET && set == NULL)) - size += set->settype->adt_size; - DP("alloc size %d", size); - data = ipset_malloc(size); - - /* Fill out the request */ - req_bind = (struct ip_set_req_bind *) data; - req_bind->op = op; - req_bind->index = set ? set->index : IP_SET_INVALID_ID; - if (adt[0] == ':') { - /* ':default:' and ':all:' */ - strncpy(req_bind->binding, adt, IP_SET_MAXNAMELEN); - if (op != IP_SET_OP_UNBIND_SET && adt[0] == ':') - strncpy(data + sizeof(struct ip_set_req_bind), - binding, IP_SET_MAXNAMELEN); - } else { - strncpy(req_bind->binding, binding, IP_SET_MAXNAMELEN); - memcpy(data + sizeof(struct ip_set_req_bind), - set->settype->data, set->settype->adt_size); - } - - if (op == IP_SET_OP_TEST_BIND_SET) { - if (kernel_sendto_handleerrno(cmd, data, size) == -1) { - ipset_printf("%s in set %s is bound to %s.", - adt, set->name, binding); - res = 0; - } else { - ipset_printf("%s in set %s is NOT bound to %s.", - adt, set->name, binding); - res = 1; - } - } else - kernel_sendto(cmd, data, size); - free(data); - - return res; -} - -static void set_restore_bind(struct set *set, - const char *adt, - const char *binding) -{ - struct ip_set_hash_save *hash_restore; - - if (restore == 1) { - /* Marker */ - struct ip_set_restore *marker = - (struct ip_set_restore *) (restore_data + restore_offset); - - DP("restore marker"); - if (restore_offset + sizeof(struct ip_set_restore) - > restore_size) - exit_error(PARAMETER_PROBLEM, - "Giving up, restore file is screwed up!"); - marker->index = IP_SET_INVALID_ID; - marker->header_size = marker->members_size = 0; - restore_offset += sizeof(struct ip_set_restore); - restore = 2; - } - /* Sanity checking */ - if (restore_offset + sizeof(struct ip_set_hash_save) > restore_size) - exit_error(PARAMETER_PROBLEM, - "Giving up, restore file is screwed up!"); - - hash_restore = (struct ip_set_hash_save *) (restore_data + restore_offset); - DP("%s -> %s", adt, binding); - if (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0) - hash_restore->ip = 0; - 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", - hash_restore->id, hash_restore->ip, hash_restore->binding); - restore_offset += sizeof(struct ip_set_hash_save); + DP("restore_offset: %zu", restore_offset); } /* * Print operation */ -static void print_bindings(struct set *set, - void *data, size_t size, unsigned options, - char * (*printip)(struct set *set, - ip_set_ip_t ip, unsigned options)) -{ - 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", - printip(set, hash->ip, options), - set_list[hash->binding]->name); - offset += sizeof(struct ip_set_hash_list); - } -} - /* Help function to set_list() */ static size_t print_set(void *data, unsigned options) { @@ -1780,15 +1558,14 @@ static size_t print_set(void *data, unsigned options) size_t offset; /* Pretty print the set */ + DP("header size: %u, members size: %u", + setlist->header_size, setlist->members_size); printf("Name: %s\n", set->name); printf("Type: %s\n", settype->typename); printf("References: %d\n", setlist->ref); - printf("Default binding: %s\n", - setlist->binding == IP_SET_INVALID_ID ? "" - : set_list[setlist->binding]->name); /* Init header */ - offset = sizeof(struct ip_set_list); + offset = ALIGNED(sizeof(struct ip_set_list)); settype->initheader(set, data + offset); /* Pretty print the type header */ @@ -1798,24 +1575,20 @@ static size_t print_set(void *data, unsigned options) /* Pretty print all IPs */ printf("Members:\n"); offset += setlist->header_size; + DP("Aligned: %u, offset: %zu, members_size %u\n", !DONT_ALIGN, offset, + setlist->members_size); if (options & OPT_SORTED) settype->printips_sorted(set, data + offset, - setlist->members_size, options); + setlist->members_size, options, + DONT_ALIGN); else settype->printips(set, data + offset, - setlist->members_size, options); - - /* Print bindings */ - printf("Bindings:\n"); - offset += setlist->members_size; - if (set->settype->bindip_tostring) - print_bindings(set, - data + offset, setlist->bindings_size, options, - settype->bindip_tostring); + setlist->members_size, options, + DONT_ALIGN); printf("\n"); /* One newline between sets */ - return (offset + setlist->bindings_size); + return (offset + setlist->members_size); } static int try_list_sets(const char name[IP_SET_MAXNAMELEN], @@ -1886,9 +1659,9 @@ static void set_help(const struct settype *settype) "Usage: %s -N new-set settype [options]\n" " %s -[XFLSH] [set] [options]\n" " %s -[EW] from-set to-set\n" - " %s -[ADTU] set IP\n" - " %s -B set IP option\n" + " %s -[ADT] set IP\n" " %s -R\n" + " %s -v\n" " %s -h (print this help information)\n\n", program_name, program_version, program_name, program_name, program_name, @@ -1919,13 +1692,6 @@ static void set_help(const struct settype *settype) " Deletes an IP from a set\n" " --test -T setname IP \n" " Tests if an IP exists in a set.\n" - " --bind -B setname IP|:default: -b bind-setname\n" - " Bind the IP in setname to bind-setname.\n" - " --unbind -U setname IP|:all:|:default:\n" - " Delete binding belonging to IP,\n" - " all bindings or default binding of setname.\n" - " --unbind -U :all: :all:|:default:\n" - " Delete all bindings or all default bindings.\n" " --help -H [settype]\n" " Prints this help, and settype specific help\n" " --version -V\n" @@ -1934,8 +1700,7 @@ static void set_help(const struct settype *settype) " --sorted -s Numeric sort of the IPs in -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"); + " --quiet -q Suppress any output to stdout and stderr.\n"); #ifdef IPSET_DEBUG printf(" --debug -z Enable debugging\n\n"); #else @@ -1967,40 +1732,13 @@ static int parse_adt_cmdline(int command, { int res = 0; - /* -U :all: :all:|:default: */ - if (command == CMD_UNBIND) { - if (strcmp(name, IPSET_TOKEN_ALL) == 0) { - if (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0 - || strcmp(adt, IPSET_TOKEN_ALL) == 0) { - *set = NULL; - *settype = NULL; - return 1; - } else - exit_error(PARAMETER_PROBLEM, - "-U %s requires %s or %s as binding name", - IPSET_TOKEN_ALL, - IPSET_TOKEN_DEFAULT, - IPSET_TOKEN_ALL); - } - } - *set = restore ? set_find_byname(name) - : set_adt_get(name); + *set = restore ? set_find_byname(name) : set_adt_get(name); /* Reset space for adt data */ *settype = (*set)->settype; memset((*settype)->data, 0, (*settype)->adt_size); - if ((command == CMD_TEST - || command == CMD_BIND - || command == CMD_UNBIND) - && (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0 - || strcmp(adt, IPSET_TOKEN_ALL) == 0)) - res = 1; - else - res = (*settype)->adt_parser( - command, - adt, - (*settype)->data); + res = (*settype)->adt_parser(command, adt, (*settype)->data); return res; } @@ -2015,9 +1753,8 @@ int parse_commandline(int argc, char *argv[]) char *name = NULL; /* All except -H, -R */ char *newname = NULL; /* -E, -W */ - char *adt = NULL; /* -A, -D, -T, -B, -U */ - char *binding = NULL; /* -B */ - struct set *set = NULL; /* -A, -D, -T, -B, -U */ + char *adt = NULL; /* -A, -D, -T */ + struct set *set = NULL; /* -A, -D, -T */ struct settype *settype = NULL; /* -N, -H */ char all_sets[] = IPSET_TOKEN_ALL; @@ -2051,11 +1788,14 @@ int parse_commandline(int argc, char *argv[]) break; } - case 'V':{ /* Version */ - printf("%s v%s Protocol version %u.\n", + case 'V': + case 'v': { /* Version */ + printf("%s v%s, protocol version %u.\n", program_name, program_version, IP_SET_PROTOCOL_VERSION); check_protocolversion(); + printf("Kernel module protocol version %u.\n", + protocol_version); exit(0); } @@ -2064,7 +1804,7 @@ int parse_commandline(int argc, char *argv[]) name = check_set_name(optarg); - /* Protect reserved names (binding) */ + /* Protect reserved names */ if (name[0] == ':') exit_error(PARAMETER_PROBLEM, "setname might not start with colon", @@ -2139,9 +1879,7 @@ int parse_commandline(int argc, char *argv[]) case 'A': /* Add IP */ case 'D': /* Del IP */ - case 'T': /* Test IP */ - case 'B': /* Bind IP */ - case 'U':{ /* Unbind IP */ + case 'T':{ /* Test IP */ set_command(&command, find_cmd(c)); name = check_set_name(optarg); @@ -2194,11 +1932,6 @@ int parse_commandline(int argc, char *argv[]) break; #endif - case 'b': - add_option(&options, OPT_BINDING); - binding = check_set_name(optarg); - break; - case 1: /* non option */ printf("Bad argument `%s'\n", optarg); exit_tryhelp(PARAMETER_PROBLEM); @@ -2245,6 +1978,8 @@ int parse_commandline(int argc, char *argv[]) generic_opt_check(command, options); DP("cmd: %c", cmd2char(command)); + + check_protocolversion(); switch (command) { case CMD_CREATE: @@ -2295,26 +2030,7 @@ int parse_commandline(int argc, char *argv[]) break; case CMD_TEST: - if (binding) - res = set_bind(set, adt, binding, - IP_SET_OP_TEST_BIND_SET, CMD_TEST); - else - res = set_adtip(set, adt, - IP_SET_OP_TEST_IP, CMD_TEST); - 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 - set_bind(set, adt, binding, - IP_SET_OP_BIND_SET, CMD_BIND); - break; - - case CMD_UNBIND: - set_bind(set, adt, "", IP_SET_OP_UNBIND_SET, CMD_UNBIND); + res = set_adtip(set, adt, IP_SET_OP_TEST_IP, CMD_TEST); break; case CMD_HELP: @@ -56,8 +56,6 @@ enum set_commands { CMD_ADD, /* -A */ CMD_DEL, /* -D */ CMD_TEST, /* -T */ - CMD_BIND, /* -B */ - CMD_UNBIND, /* -U */ CMD_HELP, /* -H */ CMD_VERSION, /* -V */ NUMBER_OF_CMD = CMD_VERSION, @@ -134,22 +132,19 @@ struct settype { void (*printheader) (struct set *set, unsigned options); /* Pretty print all IPs */ - void (*printips) (struct set *set, void *data, u_int32_t len, unsigned options); + void (*printips) (struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align); /* Pretty print all IPs sorted */ - void (*printips_sorted) (struct set *set, void *data, u_int32_t len, unsigned options); + void (*printips_sorted) (struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align); /* Print save arguments for creating the set */ void (*saveheader) (struct set *set, unsigned options); /* Print save for all IPs */ - void (*saveips) (struct set *set, void *data, u_int32_t len, unsigned options); - - /* Conver a single IP (binding) to string */ - char * (*bindip_tostring)(struct set *set, ip_set_ip_t ip, unsigned options); - - /* Parse an IP at restoring bindings. FIXME */ - void (*bindip_parse) (const char *str, ip_set_ip_t * ip); + void (*saveips) (struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align); /* Print usage */ void (*usage) (void); @@ -189,12 +184,12 @@ extern struct set *set_find_byid(ip_set_id_t id); extern unsigned warn_once; -#define BITS_PER_LONG (8*sizeof(unsigned long)) +#define BITS_PER_LONG (8*sizeof(ip_set_ip_t)) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) -static inline int test_bit(int nr, const unsigned long *addr) +static inline int test_bit(int nr, const ip_set_ip_t *addr) { - return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); + return 1 & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); } #define UNUSED __attribute__ ((unused)) diff --git a/ipset_iphash.c b/ipset_iphash.c index dc9c89b..b352df4 100644 --- a/ipset_iphash.c +++ b/ipset_iphash.c @@ -32,7 +32,7 @@ /* Initialize the create. */ static void -create_init(void *data) +iphash_create_init(void *data) { struct ip_set_req_iphash_create *mydata = data; @@ -48,7 +48,7 @@ create_init(void *data) /* Function which parses command options; returns true if it ate an option */ static int -create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) +iphash_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_iphash_create *mydata = (struct ip_set_req_iphash_create *) data; @@ -117,7 +117,7 @@ create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data UNUSED, unsigned int flags UNUSED) +iphash_create_final(void *data UNUSED, unsigned int flags UNUSED) { } @@ -132,7 +132,7 @@ static const struct option create_opts[] = { /* Add, del, test parser */ static ip_set_ip_t -adt_parser(int cmd UNUSED, const char *arg, void *data) +iphash_adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_iphash *mydata = data; @@ -149,7 +149,7 @@ adt_parser(int cmd UNUSED, const char *arg, void *data) */ static void -initheader(struct set *set, const void *data) +iphash_initheader(struct set *set, const void *data) { const struct ip_set_req_iphash_create *header = data; struct ip_set_iphash *map = set->settype->header; @@ -178,7 +178,7 @@ mask_to_bits(ip_set_ip_t mask) } static void -printheader(struct set *set, unsigned options UNUSED) +iphash_printheader(struct set *set, unsigned options UNUSED) { struct ip_set_iphash *mysetdata = set->settype->header; @@ -192,7 +192,8 @@ printheader(struct set *set, unsigned options UNUSED) } static void -printips(struct set *set UNUSED, void *data, u_int32_t len, unsigned options) +iphash_printips(struct set *set UNUSED, void *data, u_int32_t len, + unsigned options, char dont_align) { size_t offset = 0; ip_set_ip_t *ip; @@ -201,12 +202,12 @@ printips(struct set *set UNUSED, void *data, u_int32_t len, unsigned options) ip = data + offset; if (*ip) printf("%s\n", ip_tostring(*ip, options)); - offset += sizeof(ip_set_ip_t); + offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align); } } static void -saveheader(struct set *set, unsigned options UNUSED) +iphash_saveheader(struct set *set, unsigned options UNUSED) { struct ip_set_iphash *mysetdata = set->settype->header; @@ -221,7 +222,8 @@ saveheader(struct set *set, unsigned options UNUSED) /* Print save for an IP */ static void -saveips(struct set *set UNUSED, void *data, u_int32_t len, unsigned options) +iphash_saveips(struct set *set UNUSED, void *data, u_int32_t len, + unsigned options, char dont_align) { size_t offset = 0; ip_set_ip_t *ip; @@ -231,11 +233,12 @@ saveips(struct set *set UNUSED, void *data, u_int32_t len, unsigned options) if (*ip) printf("-A %s %s\n", set->name, ip_tostring(*ip, options)); - offset += sizeof(ip_set_ip_t); + offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align); } } -static void usage(void) +static void +iphash_usage(void) { printf ("-N set iphash [--hashsize hashsize] [--probes probes ]\n" @@ -251,29 +254,25 @@ static struct settype settype_iphash = { /* Create */ .create_size = sizeof(struct ip_set_req_iphash_create), - .create_init = &create_init, - .create_parse = &create_parse, - .create_final = &create_final, + .create_init = iphash_create_init, + .create_parse = iphash_create_parse, + .create_final = iphash_create_final, .create_opts = create_opts, /* Add/del/test */ .adt_size = sizeof(struct ip_set_req_iphash), - .adt_parser = &adt_parser, + .adt_parser = iphash_adt_parser, /* Printing */ .header_size = sizeof(struct ip_set_iphash), - .initheader = &initheader, - .printheader = &printheader, - .printips = &printips, /* We only have the unsorted version */ - .printips_sorted = &printips, - .saveheader = &saveheader, - .saveips = &saveips, - - /* Bindings */ - .bindip_tostring = &binding_ip_tostring, - .bindip_parse = &parse_ip, + .initheader = iphash_initheader, + .printheader = iphash_printheader, + .printips = iphash_printips, + .printips_sorted = iphash_printips, + .saveheader = iphash_saveheader, + .saveips = iphash_saveips, - .usage = &usage, + .usage = iphash_usage, }; CONSTRUCTOR(iphash) diff --git a/ipset_ipmap.c b/ipset_ipmap.c index 992a862..87b8e69 100644 --- a/ipset_ipmap.c +++ b/ipset_ipmap.c @@ -35,7 +35,7 @@ /* Initialize the create. */ static void -create_init(void *data) +ipmap_create_init(void *data) { struct ip_set_req_ipmap_create *mydata = data; @@ -45,7 +45,7 @@ create_init(void *data) /* Function which parses command options; returns true if it ate an option */ static int -create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) +ipmap_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_ipmap_create *mydata = data; unsigned int bits; @@ -115,7 +115,7 @@ create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data, unsigned int flags) +ipmap_create_final(void *data, unsigned int flags) { struct ip_set_req_ipmap_create *mydata = data; ip_set_ip_t range; @@ -188,7 +188,7 @@ static const struct option create_opts[] = { /* Add, del, test parser */ static ip_set_ip_t -adt_parser(int cmd UNUSED, const char *arg, void *data) +ipmap_adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_ipmap *mydata = data; @@ -205,7 +205,7 @@ adt_parser(int cmd UNUSED, const char *arg, void *data) */ static void -initheader(struct set *set, const void *data) +ipmap_initheader(struct set *set, const void *data) { const struct ip_set_req_ipmap_create *header = data; struct ip_set_ipmap *map = set->settype->header; @@ -234,7 +234,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options) +ipmap_printheader(struct set *set, unsigned options) { struct ip_set_ipmap *mysetdata = set->settype->header; @@ -246,9 +246,9 @@ printheader(struct set *set, unsigned options) printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask)); } -static void -printips_sorted(struct set *set, void *data, - u_int32_t len UNUSED, unsigned options) +static inline void +__ipmap_printips_sorted(struct set *set, void *data, + u_int32_t len UNUSED, unsigned options) { struct ip_set_ipmap *mysetdata = set->settype->header; ip_set_ip_t id; @@ -262,7 +262,26 @@ printips_sorted(struct set *set, void *data, } static void -saveheader(struct set *set, unsigned options) +ipmap_printips_sorted(struct set *set, void *data, + u_int32_t len, unsigned options, + char dont_align) +{ + ip_set_ip_t *ip; + size_t offset = 0; + + if (dont_align) + return __ipmap_printips_sorted(set, data, len, options); + + while (offset < len) { + DP("offset: %zu, len %u\n", offset, len); + ip = data + offset; + printf("%s\n", ip_tostring(*ip, options)); + offset += IPSET_ALIGN(sizeof(ip_set_ip_t)); + } +} + +static void +ipmap_saveheader(struct set *set, unsigned options) { struct ip_set_ipmap *mysetdata = set->settype->header; @@ -278,8 +297,9 @@ saveheader(struct set *set, unsigned options) mask_to_bits(mysetdata->netmask)); } -static void -saveips(struct set *set, void *data, u_int32_t len UNUSED, unsigned options) +static inline void +__ipmap_saveips(struct set *set, void *data, u_int32_t len UNUSED, + unsigned options) { struct ip_set_ipmap *mysetdata = set->settype->header; ip_set_ip_t id; @@ -294,7 +314,25 @@ saveips(struct set *set, void *data, u_int32_t len UNUSED, unsigned options) options)); } -static void usage(void) +static void +ipmap_saveips(struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align) +{ + ip_set_ip_t *ip; + size_t offset = 0; + + if (dont_align) + return __ipmap_saveips(set, data, len, options); + + while (offset < len) { + ip = data + offset; + printf("-A %s %s\n", set->name, ip_tostring(*ip, options)); + offset += IPSET_ALIGN(sizeof(ip_set_ip_t)); + } +} + +static void +ipmap_usage(void) { printf ("-N set ipmap --from IP --to IP [--netmask CIDR-netmask]\n" @@ -310,29 +348,25 @@ static struct settype settype_ipmap = { /* Create */ .create_size = sizeof(struct ip_set_req_ipmap_create), - .create_init = &create_init, - .create_parse = &create_parse, - .create_final = &create_final, + .create_init = ipmap_create_init, + .create_parse = ipmap_create_parse, + .create_final = ipmap_create_final, .create_opts = create_opts, /* Add/del/test */ .adt_size = sizeof(struct ip_set_req_ipmap), - .adt_parser = &adt_parser, + .adt_parser = ipmap_adt_parser, /* Printing */ .header_size = sizeof(struct ip_set_ipmap), - .initheader = &initheader, - .printheader = &printheader, - .printips = &printips_sorted, /* We only have sorted version */ - .printips_sorted = &printips_sorted, - .saveheader = &saveheader, - .saveips = &saveips, + .initheader = ipmap_initheader, + .printheader = ipmap_printheader, + .printips = ipmap_printips_sorted, + .printips_sorted = ipmap_printips_sorted, + .saveheader = ipmap_saveheader, + .saveips = ipmap_saveips, - /* Bindings */ - .bindip_tostring = &binding_ip_tostring, - .bindip_parse = &parse_ip, - - .usage = &usage, + .usage = ipmap_usage, }; CONSTRUCTOR(ipmap) diff --git a/ipset_ipporthash.c b/ipset_ipporthash.c index 0073988..ce783ee 100644 --- a/ipset_ipporthash.c +++ b/ipset_ipporthash.c @@ -32,7 +32,7 @@ /* Initialize the create. */ static void -create_init(void *data) +ipporthash_create_init(void *data) { struct ip_set_req_ipporthash_create *mydata = data; @@ -46,7 +46,8 @@ create_init(void *data) /* Function which parses command options; returns true if it ate an option */ static int -create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) +ipporthash_create_parse(int c, char *argv[] UNUSED, void *data, + unsigned *flags) { struct ip_set_req_ipporthash_create *mydata = data; ip_set_ip_t value; @@ -137,7 +138,7 @@ create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data, unsigned int flags) +ipporthash_create_final(void *data, unsigned int flags) { struct ip_set_req_ipporthash_create *mydata = data; @@ -189,7 +190,7 @@ static const struct option create_opts[] = { /* Add, del, test parser */ static ip_set_ip_t -adt_parser(int cmd UNUSED, const char *arg, void *data) +ipporthash_adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_ipporthash *mydata = data; char *saved = ipset_strdup(arg); @@ -222,7 +223,7 @@ adt_parser(int cmd UNUSED, const char *arg, void *data) */ static void -initheader(struct set *set, const void *data) +ipporthash_initheader(struct set *set, const void *data) { const struct ip_set_req_ipporthash_create *header = data; struct ip_set_ipporthash *map = set->settype->header; @@ -236,7 +237,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options) +ipporthash_printheader(struct set *set, unsigned options) { struct ip_set_ipporthash *mysetdata = set->settype->header; @@ -248,7 +249,8 @@ printheader(struct set *set, unsigned options) } static void -printips(struct set *set, void *data, u_int32_t len, unsigned options) +ipporthash_printips(struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align) { struct ip_set_ipporthash *mysetdata = set->settype->header; size_t offset = 0; @@ -264,12 +266,12 @@ printips(struct set *set, void *data, u_int32_t len, unsigned options) ip_tostring(ip, options), port_tostring(port, options)); } - offset += sizeof(ip_set_ip_t); + offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align); } } static void -saveheader(struct set *set, unsigned options) +ipporthash_saveheader(struct set *set, unsigned options) { struct ip_set_ipporthash *mysetdata = set->settype->header; @@ -284,7 +286,8 @@ saveheader(struct set *set, unsigned options) /* Print save for an IP */ static void -saveips(struct set *set, void *data, u_int32_t len, unsigned options) +ipporthash_saveips(struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align) { struct ip_set_ipporthash *mysetdata = set->settype->header; size_t offset = 0; @@ -300,27 +303,12 @@ saveips(struct set *set, void *data, u_int32_t len, unsigned options) ip_tostring(ip, options), port_tostring(port, options)); } - offset += sizeof(ip_set_ip_t); + offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align); } } -static char buffer[22]; - -static char * -unpack_ipport_tostring(struct set *set, ip_set_ip_t bip, unsigned options) -{ - 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", - ip_tostring(ip, options), port_tostring(port, options)); - - return buffer; -} - -static void usage(void) +static void +ipporthash_usage(void) { printf ("-N set ipporthash --from IP --to IP\n" @@ -338,29 +326,25 @@ static struct settype settype_ipporthash = { /* Create */ .create_size = sizeof(struct ip_set_req_ipporthash_create), - .create_init = &create_init, - .create_parse = &create_parse, - .create_final = &create_final, + .create_init = ipporthash_create_init, + .create_parse = ipporthash_create_parse, + .create_final = ipporthash_create_final, .create_opts = create_opts, /* Add/del/test */ .adt_size = sizeof(struct ip_set_req_ipporthash), - .adt_parser = &adt_parser, + .adt_parser = ipporthash_adt_parser, /* Printing */ .header_size = sizeof(struct ip_set_ipporthash), - .initheader = &initheader, - .printheader = &printheader, - .printips = &printips, /* We only have the unsorted version */ - .printips_sorted = &printips, - .saveheader = &saveheader, - .saveips = &saveips, - - /* Bindings */ - .bindip_tostring = &unpack_ipport_tostring, - .bindip_parse = &parse_ip, + .initheader = ipporthash_initheader, + .printheader = ipporthash_printheader, + .printips = ipporthash_printips, + .printips_sorted = ipporthash_printips, + .saveheader = ipporthash_saveheader, + .saveips = ipporthash_saveips, - .usage = &usage, + .usage = ipporthash_usage, }; CONSTRUCTOR(ipporthash) diff --git a/ipset_ipportiphash.c b/ipset_ipportiphash.c index 22a92ef..95cbcfd 100644 --- a/ipset_ipportiphash.c +++ b/ipset_ipportiphash.c @@ -32,7 +32,7 @@ /* Initialize the create. */ static void -create_init(void *data) +ipportiphash_create_init(void *data) { struct ip_set_req_ipportiphash_create *mydata = data; @@ -46,7 +46,8 @@ create_init(void *data) /* Function which parses command options; returns true if it ate an option */ static int -create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) +ipportiphash_create_parse(int c, char *argv[] UNUSED, void *data, + unsigned *flags) { struct ip_set_req_ipportiphash_create *mydata = data; ip_set_ip_t value; @@ -137,7 +138,7 @@ create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data, unsigned int flags) +ipportiphash_create_final(void *data, unsigned int flags) { struct ip_set_req_ipportiphash_create *mydata = data; @@ -189,7 +190,7 @@ static const struct option create_opts[] = { /* Add, del, test parser */ static ip_set_ip_t -adt_parser(int cmd UNUSED, const char *arg, void *data) +ipportiphash_adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_ipportiphash *mydata = data; char *saved = ipset_strdup(arg); @@ -227,7 +228,7 @@ adt_parser(int cmd UNUSED, const char *arg, void *data) */ static void -initheader(struct set *set, const void *data) +ipportiphash_initheader(struct set *set, const void *data) { const struct ip_set_req_ipportiphash_create *header = data; struct ip_set_ipportiphash *map = set->settype->header; @@ -241,7 +242,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options) +ipportiphash_printheader(struct set *set, unsigned options) { struct ip_set_ipportiphash *mysetdata = set->settype->header; @@ -253,7 +254,8 @@ printheader(struct set *set, unsigned options) } static void -printips(struct set *set, void *data, u_int32_t len, unsigned options) +ipportiphash_printips(struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align) { struct ip_set_ipportiphash *mysetdata = set->settype->header; size_t offset = 0; @@ -272,12 +274,12 @@ printips(struct set *set, void *data, u_int32_t len, unsigned options) printf("%s\n", ip_tostring(ipptr->ip1, options)); } - offset += sizeof(struct ipportip); + offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align); } } static void -saveheader(struct set *set, unsigned options) +ipportiphash_saveheader(struct set *set, unsigned options) { struct ip_set_ipportiphash *mysetdata = set->settype->header; @@ -292,7 +294,8 @@ saveheader(struct set *set, unsigned options) /* Print save for an IP */ static void -saveips(struct set *set, void *data, u_int32_t len, unsigned options) +ipportiphash_saveips(struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align) { struct ip_set_ipportiphash *mysetdata = set->settype->header; size_t offset = 0; @@ -311,11 +314,12 @@ saveips(struct set *set, void *data, u_int32_t len, unsigned options) printf("%s\n", ip_tostring(ipptr->ip1, options)); } - offset += sizeof(struct ipportip); + offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align); } } -static void usage(void) +static void +ipportiphash_usage(void) { printf ("-N set ipportiphash --from IP --to IP\n" @@ -333,25 +337,25 @@ static struct settype settype_ipportiphash = { /* Create */ .create_size = sizeof(struct ip_set_req_ipportiphash_create), - .create_init = &create_init, - .create_parse = &create_parse, - .create_final = &create_final, + .create_init = ipportiphash_create_init, + .create_parse = ipportiphash_create_parse, + .create_final = ipportiphash_create_final, .create_opts = create_opts, /* Add/del/test */ .adt_size = sizeof(struct ip_set_req_ipportiphash), - .adt_parser = &adt_parser, + .adt_parser = ipportiphash_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, + .initheader = ipportiphash_initheader, + .printheader = ipportiphash_printheader, + .printips = ipportiphash_printips, + .printips_sorted = ipportiphash_printips, + .saveheader = ipportiphash_saveheader, + .saveips = ipportiphash_saveips, - .usage = &usage, + .usage = ipportiphash_usage, }; CONSTRUCTOR(ipportiphash) diff --git a/ipset_ipportnethash.c b/ipset_ipportnethash.c index a029343..3485711 100644 --- a/ipset_ipportnethash.c +++ b/ipset_ipportnethash.c @@ -32,7 +32,7 @@ /* Initialize the create. */ static void -create_init(void *data) +ipportnethash_create_init(void *data) { struct ip_set_req_ipportnethash_create *mydata = data; @@ -46,7 +46,8 @@ create_init(void *data) /* Function which parses command options; returns true if it ate an option */ static int -create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) +ipportnethash_create_parse(int c, char *argv[] UNUSED, void *data, + unsigned *flags) { struct ip_set_req_ipportnethash_create *mydata = data; ip_set_ip_t value; @@ -137,7 +138,7 @@ create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data, unsigned int flags) +ipportnethash_create_final(void *data, unsigned int flags) { struct ip_set_req_ipportnethash_create *mydata = data; @@ -189,7 +190,7 @@ static const struct option create_opts[] = { /* Add, del, test parser */ static ip_set_ip_t -adt_parser(int cmd, const char *arg, void *data) +ipportnethash_adt_parser(int cmd, const char *arg, void *data) { struct ip_set_req_ipportnethash *mydata = data; char *saved = ipset_strdup(arg); @@ -238,7 +239,7 @@ adt_parser(int cmd, const char *arg, void *data) */ static void -initheader(struct set *set, const void *data) +ipportnethash_initheader(struct set *set, const void *data) { const struct ip_set_req_ipportnethash_create *header = data; struct ip_set_ipportnethash *map = set->settype->header; @@ -252,7 +253,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options) +ipportnethash_printheader(struct set *set, unsigned options) { struct ip_set_ipportnethash *mysetdata = set->settype->header; @@ -318,7 +319,8 @@ unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED) } static void -printips(struct set *set, void *data, u_int32_t len, unsigned options) +ipportnethash_printips(struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align) { struct ip_set_ipportnethash *mysetdata = set->settype->header; size_t offset = 0; @@ -337,12 +339,12 @@ printips(struct set *set, void *data, u_int32_t len, unsigned options) printf("%s\n", unpack_ip_tostring(ipptr->ip1, options)); } - offset += sizeof(struct ipportip); + offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align); } } static void -saveheader(struct set *set, unsigned options) +ipportnethash_saveheader(struct set *set, unsigned options) { struct ip_set_ipportnethash *mysetdata = set->settype->header; @@ -357,7 +359,8 @@ saveheader(struct set *set, unsigned options) /* Print save for an IP */ static void -saveips(struct set *set, void *data, u_int32_t len, unsigned options) +ipportnethash_saveips(struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align) { struct ip_set_ipportnethash *mysetdata = set->settype->header; size_t offset = 0; @@ -376,11 +379,12 @@ saveips(struct set *set, void *data, u_int32_t len, unsigned options) printf("%s\n", unpack_ip_tostring(ipptr->ip, options)); } - offset += sizeof(struct ipportip); + offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align); } } -static void usage(void) +static void +ipportnethash_usage(void) { printf ("-N set ipportnethash --from IP --to IP\n" @@ -398,25 +402,25 @@ static struct settype settype_ipportnethash = { /* Create */ .create_size = sizeof(struct ip_set_req_ipportnethash_create), - .create_init = &create_init, - .create_parse = &create_parse, - .create_final = &create_final, + .create_init = ipportnethash_create_init, + .create_parse = ipportnethash_create_parse, + .create_final = ipportnethash_create_final, .create_opts = create_opts, /* Add/del/test */ .adt_size = sizeof(struct ip_set_req_ipportnethash), - .adt_parser = &adt_parser, + .adt_parser = ipportnethash_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, + .initheader = ipportnethash_initheader, + .printheader = ipportnethash_printheader, + .printips = ipportnethash_printips, + .printips_sorted = ipportnethash_printips, + .saveheader = ipportnethash_saveheader, + .saveips = ipportnethash_saveips, - .usage = &usage, + .usage = ipportnethash_usage, }; CONSTRUCTOR(ipportnethash) diff --git a/ipset_iptree.c b/ipset_iptree.c index fbde520..508e67a 100644 --- a/ipset_iptree.c +++ b/ipset_iptree.c @@ -29,7 +29,7 @@ /* Initialize the create. */ static void -create_init(void *data) +iptree_create_init(void *data) { struct ip_set_req_iptree_create *mydata = data; @@ -39,7 +39,7 @@ create_init(void *data) /* Function which parses command options; returns true if it ate an option */ static int -create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) +iptree_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_iptree_create *mydata = data; @@ -63,7 +63,7 @@ create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data UNUSED, unsigned int flags UNUSED) +iptree_create_final(void *data UNUSED, unsigned int flags UNUSED) { } @@ -75,7 +75,7 @@ static const struct option create_opts[] = { /* Add, del, test parser */ static ip_set_ip_t -adt_parser(int cmd UNUSED, const char *arg, void *data) +iptree_adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_iptree *mydata = data; char *saved = ipset_strdup(arg); @@ -104,7 +104,7 @@ adt_parser(int cmd UNUSED, const char *arg, void *data) */ static void -initheader(struct set *set, const void *data) +iptree_initheader(struct set *set, const void *data) { const struct ip_set_req_iptree_create *header = data; struct ip_set_iptree *map = set->settype->header; @@ -113,7 +113,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options UNUSED) +iptree_printheader(struct set *set, unsigned options UNUSED) { struct ip_set_iptree *mysetdata = set->settype->header; @@ -123,7 +123,8 @@ printheader(struct set *set, unsigned options UNUSED) } static void -printips_sorted(struct set *set, void *data, u_int32_t len, unsigned options) +iptree_printips_sorted(struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align) { struct ip_set_iptree *mysetdata = set->settype->header; struct ip_set_req_iptree *req; @@ -136,12 +137,12 @@ printips_sorted(struct set *set, void *data, u_int32_t len, unsigned options) req->timeout); else printf("%s\n", ip_tostring(req->ip, options)); - offset += sizeof(struct ip_set_req_iptree); + offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptree), dont_align); } } static void -saveheader(struct set *set, unsigned options UNUSED) +iptree_saveheader(struct set *set, unsigned options UNUSED) { struct ip_set_iptree *mysetdata = set->settype->header; @@ -155,7 +156,8 @@ saveheader(struct set *set, unsigned options UNUSED) } static void -saveips(struct set *set, void *data, u_int32_t len, unsigned options) +iptree_saveips(struct set *set, void *data, u_int32_t len, + unsigned options, char dont_align) { struct ip_set_iptree *mysetdata = set->settype->header; struct ip_set_req_iptree *req; @@ -174,11 +176,12 @@ saveips(struct set *set, void *data, u_int32_t len, unsigned options) printf("-A %s %s\n", set->name, ip_tostring(req->ip, options)); - offset += sizeof(struct ip_set_req_iptree); + offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptree), dont_align); } } -static void usage(void) +static void +iptree_usage(void) { printf ("-N set iptree [--timeout value]\n" @@ -193,29 +196,25 @@ static struct settype settype_iptree = { /* Create */ .create_size = sizeof(struct ip_set_req_iptree_create), - .create_init = &create_init, - .create_parse = &create_parse, - .create_final = &create_final, + .create_init = iptree_create_init, + .create_parse = iptree_create_parse, + .create_final = iptree_create_final, .create_opts = create_opts, /* Add/del/test */ .adt_size = sizeof(struct ip_set_req_iptree), - .adt_parser = &adt_parser, + .adt_parser = iptree_adt_parser, /* Printing */ .header_size = sizeof(struct ip_set_iptree), - .initheader = &initheader, - .printheader = &printheader, - .printips = &printips_sorted, /* We only have sorted version */ - .printips_sorted = &printips_sorted, - .saveheader = &saveheader, - .saveips = &saveips, + .initheader = iptree_initheader, + .printheader = iptree_printheader, + .printips = iptree_printips_sorted, /* We only have sorted version */ + .printips_sorted = iptree_printips_sorted, + .saveheader = iptree_saveheader, + .saveips = iptree_saveips, - /* Bindings */ - .bindip_tostring = &binding_ip_tostring, - .bindip_parse = &parse_ip, - - .usage = &usage, + .usage = iptree_usage, }; CONSTRUCTOR(iptree) diff --git a/ipset_iptreemap.c b/ipset_iptreemap.c index 21948d4..22bdcb3 100644 --- a/ipset_iptreemap.c +++ b/ipset_iptreemap.c @@ -26,7 +26,7 @@ #define OPT_CREATE_GC 0x1 static void -create_init(void *data) +iptreemap_create_init(void *data) { struct ip_set_req_iptreemap_create *mydata = data; @@ -34,7 +34,8 @@ create_init(void *data) } static int -create_parse(int c, char *argv[] UNUSED, void *data, unsigned int *flags) +iptreemap_create_parse(int c, char *argv[] UNUSED, void *data, + unsigned int *flags) { struct ip_set_req_iptreemap_create *mydata = data; @@ -53,7 +54,7 @@ create_parse(int c, char *argv[] UNUSED, void *data, unsigned int *flags) } static void -create_final(void *data UNUSED, unsigned int flags UNUSED) +iptreemap_create_final(void *data UNUSED, unsigned int flags UNUSED) { } @@ -63,7 +64,7 @@ static const struct option create_opts[] = { }; static ip_set_ip_t -adt_parser(int cmd UNUSED, const char *arg, void *data) +iptreemap_adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_iptreemap *mydata = data; ip_set_ip_t mask; @@ -94,7 +95,7 @@ adt_parser(int cmd UNUSED, const char *arg, void *data) } static void -initheader(struct set *set, const void *data) +iptreemap_initheader(struct set *set, const void *data) { const struct ip_set_req_iptreemap_create *header = data; struct ip_set_iptreemap *map = set->settype->header; @@ -103,7 +104,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned int options UNUSED) +iptreemap_printheader(struct set *set, unsigned int options UNUSED) { struct ip_set_iptreemap *mysetdata = set->settype->header; @@ -114,8 +115,8 @@ printheader(struct set *set, unsigned int options UNUSED) } static void -printips_sorted(struct set *set UNUSED, void *data, - u_int32_t len, unsigned int options) +iptreemap_printips_sorted(struct set *set UNUSED, void *data, + u_int32_t len, unsigned int options, char dont_align) { struct ip_set_req_iptreemap *req; size_t offset = 0; @@ -128,12 +129,12 @@ printips_sorted(struct set *set UNUSED, void *data, printf("-%s", ip_tostring(req->end, options)); printf("\n"); - offset += sizeof(struct ip_set_req_iptreemap); + offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptreemap), dont_align); } } static void -saveheader(struct set *set, unsigned int options UNUSED) +iptreemap_saveheader(struct set *set, unsigned int options UNUSED) { struct ip_set_iptreemap *mysetdata = set->settype->header; @@ -146,8 +147,8 @@ saveheader(struct set *set, unsigned int options UNUSED) } static void -saveips(struct set *set UNUSED, void *data, - u_int32_t len, unsigned int options) +iptreemap_saveips(struct set *set UNUSED, void *data, + u_int32_t len, unsigned int options, char dont_align) { struct ip_set_req_iptreemap *req; size_t offset = 0; @@ -162,12 +163,12 @@ saveips(struct set *set UNUSED, void *data, printf("\n"); - offset += sizeof(struct ip_set_req_iptreemap); + offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptreemap), dont_align); } } static void -usage(void) +iptreemap_usage(void) { printf( "-N set iptreemap --gc interval\n" @@ -182,26 +183,23 @@ static struct settype settype_iptreemap = { .protocol_version = IP_SET_PROTOCOL_VERSION, .create_size = sizeof(struct ip_set_req_iptreemap_create), - .create_init = &create_init, - .create_parse = &create_parse, - .create_final = &create_final, + .create_init = iptreemap_create_init, + .create_parse = iptreemap_create_parse, + .create_final = iptreemap_create_final, .create_opts = create_opts, .adt_size = sizeof(struct ip_set_req_iptreemap), - .adt_parser = &adt_parser, + .adt_parser = iptreemap_adt_parser, .header_size = sizeof(struct ip_set_iptreemap), - .initheader = &initheader, - .printheader = &printheader, - .printips = &printips_sorted, - .printips_sorted = &printips_sorted, - .saveheader = &saveheader, - .saveips = &saveips, - - .bindip_tostring = &binding_ip_tostring, - .bindip_parse = &parse_ip, - - .usage = &usage, + .initheader = iptreemap_initheader, + .printheader = iptreemap_printheader, + .printips = iptreemap_printips_sorted, + .printips_sorted = iptreemap_printips_sorted, + .saveheader = iptreemap_saveheader, + .saveips = iptreemap_saveips, + + .usage = iptreemap_usage, }; CONSTRUCTOR(iptreemap) diff --git a/ipset_macipmap.c b/ipset_macipmap.c index 3a47e59..fb97cae 100644 --- a/ipset_macipmap.c +++ b/ipset_macipmap.c @@ -39,7 +39,7 @@ /* Initialize the create. */ static void -create_init(void *data UNUSED) +macipmap_create_init(void *data UNUSED) { DP("create INIT"); /* Nothing */ @@ -47,7 +47,7 @@ create_init(void *data UNUSED) /* Function which parses command options; returns true if it ate an option */ static int -create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) +macipmap_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_macipmap_create *mydata = data; @@ -107,7 +107,7 @@ create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data, unsigned int flags) +macipmap_create_final(void *data, unsigned int flags) { struct ip_set_req_macipmap_create *mydata = data; @@ -176,7 +176,7 @@ parse_mac(const char *mac, unsigned char *ethernet) /* Add, del, test parser */ static ip_set_ip_t -adt_parser(int cmd UNUSED, const char *arg, void *data) +macipmap_adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_macipmap *mydata = data; char *saved = ipset_strdup(arg); @@ -209,7 +209,7 @@ adt_parser(int cmd UNUSED, const char *arg, void *data) */ static void -initheader(struct set *set, const void *data) +macipmap_initheader(struct set *set, const void *data) { const struct ip_set_req_macipmap_create *header = data; struct ip_set_macipmap *map = set->settype->header; @@ -221,7 +221,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options) +macipmap_printheader(struct set *set, unsigned options) { struct ip_set_macipmap *mysetdata = set->settype->header; @@ -243,9 +243,9 @@ print_mac(unsigned char macaddress[ETH_ALEN]) printf(":%02X", macaddress[i]); } -static void -printips_sorted(struct set *set, void *data, - u_int32_t len UNUSED, unsigned options) +static inline void +__macipmap_printips_sorted(struct set *set, void *data, + u_int32_t len UNUSED, unsigned options) { struct ip_set_macipmap *mysetdata = set->settype->header; struct ip_set_macip *table = data; @@ -263,7 +263,27 @@ printips_sorted(struct set *set, void *data, } static void -saveheader(struct set *set, unsigned options) +macipmap_printips_sorted(struct set *set, void *data, + u_int32_t len, unsigned options, + char dont_align) +{ + struct ip_set_req_macipmap *d; + size_t offset = 0; + + if (dont_align) + return __macipmap_printips_sorted(set, data, len, options); + + while (offset < len) { + d = data + offset; + printf("%s,", ip_tostring(d->ip, options)); + print_mac(d->ethernet); + printf("\n"); + offset += IPSET_ALIGN(sizeof(struct ip_set_req_macipmap)); + } +} + +static void +macipmap_saveheader(struct set *set, unsigned options) { struct ip_set_macipmap *mysetdata = set->settype->header; @@ -277,9 +297,9 @@ saveheader(struct set *set, unsigned options) printf("\n"); } -static void -saveips(struct set *set, void *data, - u_int32_t len UNUSED, unsigned options) +static inline void +__macipmap_saveips(struct set *set, void *data, + u_int32_t len UNUSED, unsigned options) { struct ip_set_macipmap *mysetdata = set->settype->header; struct ip_set_macip *table = data; @@ -297,7 +317,28 @@ saveips(struct set *set, void *data, } } -static void usage(void) +static void +macipmap_saveips(struct set *set, void *data, + u_int32_t len, unsigned options, + char dont_align) +{ + struct ip_set_req_macipmap *d; + size_t offset = 0; + + if (dont_align) + return __macipmap_saveips(set, data, len, options); + + while (offset < len) { + d = data + offset; + printf("-A %s %s,", set->name, ip_tostring(d->ip, options)); + print_mac(d->ethernet); + printf("\n"); + offset += IPSET_ALIGN(sizeof(struct ip_set_req_macipmap)); + } +} + +static void +macipmap_usage(void) { printf ("-N set macipmap --from IP --to IP [--matchunset]\n" @@ -313,29 +354,25 @@ static struct settype settype_macipmap = { /* Create */ .create_size = sizeof(struct ip_set_req_macipmap_create), - .create_init = &create_init, - .create_parse = &create_parse, - .create_final = &create_final, + .create_init = macipmap_create_init, + .create_parse = macipmap_create_parse, + .create_final = macipmap_create_final, .create_opts = create_opts, /* Add/del/test */ .adt_size = sizeof(struct ip_set_req_macipmap), - .adt_parser = &adt_parser, + .adt_parser = macipmap_adt_parser, /* Printing */ .header_size = sizeof(struct ip_set_macipmap), - .initheader = &initheader, - .printheader = &printheader, - .printips = &printips_sorted, /* We only have sorted version */ - .printips_sorted = &printips_sorted, - .saveheader = &saveheader, - .saveips = &saveips, - - /* Bindings */ - .bindip_tostring = &binding_ip_tostring, - .bindip_parse = &parse_ip, - - .usage = &usage, + .initheader = macipmap_initheader, + .printheader = macipmap_printheader, + .printips = macipmap_printips_sorted, + .printips_sorted = macipmap_printips_sorted, + .saveheader = macipmap_saveheader, + .saveips = macipmap_saveips, + + .usage = macipmap_usage, }; CONSTRUCTOR(macipmap) diff --git a/ipset_nethash.c b/ipset_nethash.c index c73e382..50ca1bd 100644 --- a/ipset_nethash.c +++ b/ipset_nethash.c @@ -31,7 +31,7 @@ /* Initialize the create. */ static void -create_init(void *data) +nethash_create_init(void *data) { struct ip_set_req_nethash_create *mydata = data; @@ -45,7 +45,7 @@ create_init(void *data) /* Function which parses command options; returns true if it ate an option */ static int -create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) +nethash_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_nethash_create *mydata = data; ip_set_ip_t value; @@ -97,7 +97,7 @@ create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data UNUSED, unsigned int flags UNUSED) +nethash_create_final(void *data UNUSED, unsigned int flags UNUSED) { } @@ -111,7 +111,7 @@ static const struct option create_opts[] = { /* Add, del, test parser */ static ip_set_ip_t -adt_parser(int cmd, const char *arg, void *data) +nethash_adt_parser(int cmd, const char *arg, void *data) { struct ip_set_req_nethash *mydata = data; char *saved = ipset_strdup(arg); @@ -148,7 +148,7 @@ adt_parser(int cmd, const char *arg, void *data) */ static void -initheader(struct set *set, const void *data) +nethash_initheader(struct set *set, const void *data) { const struct ip_set_req_nethash_create *header = data; struct ip_set_nethash *map = set->settype->header; @@ -160,7 +160,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options UNUSED) +nethash_printheader(struct set *set, unsigned options UNUSED) { struct ip_set_nethash *mysetdata = set->settype->header; @@ -224,7 +224,8 @@ unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED) } static void -printips(struct set *set UNUSED, void *data, u_int32_t len, unsigned options) +nethash_printips(struct set *set UNUSED, void *data, u_int32_t len, + unsigned options, char dont_align) { size_t offset = 0; ip_set_ip_t *ip; @@ -233,12 +234,12 @@ printips(struct set *set UNUSED, void *data, u_int32_t len, unsigned options) ip = data + offset; if (*ip) printf("%s\n", unpack_ip_tostring(*ip, options)); - offset += sizeof(ip_set_ip_t); + offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align); } } static void -saveheader(struct set *set, unsigned options UNUSED) +nethash_saveheader(struct set *set, unsigned options UNUSED) { struct ip_set_nethash *mysetdata = set->settype->header; @@ -249,7 +250,8 @@ saveheader(struct set *set, unsigned options UNUSED) /* Print save for an IP */ static void -saveips(struct set *set UNUSED, void *data, u_int32_t len, unsigned options) +nethash_saveips(struct set *set UNUSED, void *data, u_int32_t len, + unsigned options, char dont_align) { size_t offset = 0; ip_set_ip_t *ip; @@ -259,40 +261,12 @@ saveips(struct set *set UNUSED, void *data, u_int32_t len, unsigned options) if (*ip) printf("-A %s %s\n", set->name, unpack_ip_tostring(*ip, options)); - offset += sizeof(ip_set_ip_t); + offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align); } } -static char * -net_tostring(struct set *set UNUSED, ip_set_ip_t ip, unsigned options) -{ - return unpack_ip_tostring(ip, options); -} - static void -parse_net(const char *str, ip_set_ip_t *ip) -{ - char *saved = ipset_strdup(str); - char *ptr, *tmp = saved; - ip_set_ip_t cidr; - - ptr = strsep(&tmp, "/"); - - if (tmp == NULL) - exit_error(PARAMETER_PROBLEM, - "Missing cidr from `%s'", str); - - if (string_to_number(tmp, 1, 31, &cidr)) - exit_error(PARAMETER_PROBLEM, - "Out of range cidr `%s' specified", str); - - parse_ip(ptr, ip); - ipset_free(saved); - - *ip = pack_ip_cidr(*ip, cidr); -} - -static void usage(void) +nethash_usage(void) { printf ("-N set nethash [--hashsize hashsize] [--probes probes ]\n" @@ -308,29 +282,25 @@ static struct settype settype_nethash = { /* Create */ .create_size = sizeof(struct ip_set_req_nethash_create), - .create_init = &create_init, - .create_parse = &create_parse, - .create_final = &create_final, + .create_init = nethash_create_init, + .create_parse = nethash_create_parse, + .create_final = nethash_create_final, .create_opts = create_opts, /* Add/del/test */ .adt_size = sizeof(struct ip_set_req_nethash), - .adt_parser = &adt_parser, + .adt_parser = nethash_adt_parser, /* Printing */ .header_size = sizeof(struct ip_set_nethash), - .initheader = &initheader, - .printheader = &printheader, - .printips = &printips, /* We only have the unsorted version */ - .printips_sorted = &printips, - .saveheader = &saveheader, - .saveips = &saveips, + .initheader = nethash_initheader, + .printheader = nethash_printheader, + .printips = nethash_printips, + .printips_sorted = nethash_printips, + .saveheader = nethash_saveheader, + .saveips = nethash_saveips, - /* Bindings */ - .bindip_tostring = &net_tostring, - .bindip_parse = &parse_net, - - .usage = &usage, + .usage = nethash_usage, }; CONSTRUCTOR(nethash) diff --git a/ipset_portmap.c b/ipset_portmap.c index 96e87c2..a1065ae 100644 --- a/ipset_portmap.c +++ b/ipset_portmap.c @@ -32,7 +32,7 @@ /* Initialize the create. */ static void -create_init(void *data UNUSED) +portmap_create_init(void *data UNUSED) { DP("create INIT"); /* Nothing */ @@ -40,7 +40,7 @@ create_init(void *data UNUSED) /* Function which parses command options; returns true if it ate an option */ static int -create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) +portmap_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_portmap_create *mydata = data; @@ -76,7 +76,7 @@ create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data, unsigned int flags) +portmap_create_final(void *data, unsigned int flags) { struct ip_set_req_portmap_create *mydata = data; @@ -113,7 +113,7 @@ static const struct option create_opts[] = { /* Add, del, test parser */ static ip_set_ip_t -adt_parser(int cmd UNUSED, const char *arg, void *data) +portmap_adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_portmap *mydata = data; @@ -128,7 +128,7 @@ adt_parser(int cmd UNUSED, const char *arg, void *data) */ static void -initheader(struct set *set, const void *data) +portmap_initheader(struct set *set, const void *data) { const struct ip_set_req_portmap_create *header = data; struct ip_set_portmap *map = set->settype->header; @@ -139,7 +139,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options) +portmap_printheader(struct set *set, unsigned options) { struct ip_set_portmap *mysetdata = set->settype->header; @@ -147,12 +147,12 @@ printheader(struct set *set, unsigned options) printf(" to: %s\n", port_tostring(mysetdata->last_ip, options)); } -static void -printports_sorted(struct set *set, void *data, - u_int32_t len UNUSED, unsigned options) +static inline void +__portmap_printips_sorted(struct set *set, void *data, + u_int32_t len UNUSED, unsigned options) { struct ip_set_portmap *mysetdata = set->settype->header; - u_int32_t addr = mysetdata->first_ip; + ip_set_ip_t addr = mysetdata->first_ip; DP("%u -- %u", mysetdata->first_ip, mysetdata->last_ip); while (addr <= mysetdata->last_ip) { @@ -162,15 +162,26 @@ printports_sorted(struct set *set, void *data, } } -static char * -binding_port_tostring(struct set *set UNUSED, - ip_set_ip_t ip, unsigned options) +static void +portmap_printips_sorted(struct set *set, void *data, + u_int32_t len, unsigned options, + char dont_align) { - return port_tostring(ip, options); + ip_set_ip_t *ip; + size_t offset = 0; + + if (dont_align) + return __portmap_printips_sorted(set, data, len, options); + + while (offset < len) { + ip = data + offset; + printf("%s\n", port_tostring(*ip, options)); + offset += IPSET_ALIGN(sizeof(ip_set_ip_t)); + } } static void -saveheader(struct set *set, unsigned options) +portmap_saveheader(struct set *set, unsigned options) { struct ip_set_portmap *mysetdata = set->settype->header; @@ -182,14 +193,15 @@ saveheader(struct set *set, unsigned options) port_tostring(mysetdata->last_ip, options)); } -static void -saveports(struct set *set, void *data, - u_int32_t len UNUSED, unsigned options) +static inline void +__portmap_saveips(struct set *set, void *data, + u_int32_t len UNUSED, unsigned options) { struct ip_set_portmap *mysetdata = set->settype->header; - u_int32_t addr = mysetdata->first_ip; + ip_set_ip_t addr = mysetdata->first_ip; while (addr <= mysetdata->last_ip) { + DP("addr: %lu, last_ip %lu", (long unsigned)addr, (long unsigned)mysetdata->last_ip); if (test_bit(addr - mysetdata->first_ip, data)) printf("-A %s %s\n", set->name, @@ -198,7 +210,26 @@ saveports(struct set *set, void *data, } } -static void usage(void) +static void +portmap_saveips(struct set *set, void *data, + u_int32_t len, unsigned options, + char dont_align) +{ + ip_set_ip_t *ip; + size_t offset = 0; + + if (dont_align) + return __portmap_saveips(set, data, len, options); + + while (offset < len) { + ip = data + offset; + printf("-A %s %s\n", set->name, port_tostring(*ip, options)); + offset += IPSET_ALIGN(sizeof(ip_set_ip_t)); + } +} + +static void +portmap_usage(void) { printf ("-N set portmap --from PORT --to PORT\n" @@ -213,29 +244,25 @@ static struct settype settype_portmap = { /* Create */ .create_size = sizeof(struct ip_set_req_portmap_create), - .create_init = &create_init, - .create_parse = &create_parse, - .create_final = &create_final, + .create_init = portmap_create_init, + .create_parse = portmap_create_parse, + .create_final = portmap_create_final, .create_opts = create_opts, /* Add/del/test */ .adt_size = sizeof(struct ip_set_req_portmap), - .adt_parser = &adt_parser, + .adt_parser = portmap_adt_parser, /* Printing */ .header_size = sizeof(struct ip_set_portmap), - .initheader = &initheader, - .printheader = &printheader, - .printips = &printports_sorted, /* We only have sorted version */ - .printips_sorted = &printports_sorted, - .saveheader = &saveheader, - .saveips = &saveports, + .initheader = portmap_initheader, + .printheader = portmap_printheader, + .printips = portmap_printips_sorted, + .printips_sorted = portmap_printips_sorted, + .saveheader = portmap_saveheader, + .saveips = portmap_saveips, - /* Bindings */ - .bindip_tostring = &binding_port_tostring, - .bindip_parse = &parse_port, - - .usage = &usage, + .usage = portmap_usage, }; CONSTRUCTOR(portmap) diff --git a/ipset_setlist.c b/ipset_setlist.c index d5d65d7..de16c44 100644 --- a/ipset_setlist.c +++ b/ipset_setlist.c @@ -27,7 +27,7 @@ /* Initialize the create. */ static void -create_init(void *data) +setlist_create_init(void *data) { struct ip_set_req_setlist_create *mydata = data; @@ -36,7 +36,8 @@ create_init(void *data) /* Function which parses command options; returns true if it ate an option */ static int -create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags UNUSED) +setlist_create_parse(int c, char *argv[] UNUSED, void *data, + unsigned *flags UNUSED) { struct ip_set_req_setlist_create *mydata = data; unsigned int size; @@ -57,7 +58,7 @@ create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags UNUSED) /* Final check; exit if not ok. */ static void -create_final(void *data UNUSED, unsigned int flags UNUSED) +setlist_create_final(void *data UNUSED, unsigned int flags UNUSED) { } @@ -67,7 +68,8 @@ static const struct option create_opts[] = { {NULL}, }; -static void check_setname(const char *name) +static void +check_setname(const char *name) { if (strlen(name) > IP_SET_MAXNAMELEN - 1) exit_error(PARAMETER_PROBLEM, @@ -77,7 +79,7 @@ static void check_setname(const char *name) /* Add, del, test parser */ static ip_set_ip_t -adt_parser(int cmd UNUSED, const char *arg, void *data) +setlist_adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_setlist *mydata = data; char *saved = ipset_strdup(arg); @@ -115,7 +117,7 @@ adt_parser(int cmd UNUSED, const char *arg, void *data) */ static void -initheader(struct set *set, const void *data) +setlist_initheader(struct set *set, const void *data) { const struct ip_set_req_setlist_create *header = data; struct ip_set_setlist *map = set->settype->header; @@ -125,7 +127,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options UNUSED) +setlist_printheader(struct set *set, unsigned options UNUSED) { struct ip_set_setlist *mysetdata = set->settype->header; @@ -133,25 +135,29 @@ printheader(struct set *set, unsigned options UNUSED) } static void -printips_sorted(struct set *set, void *data, - u_int32_t len UNUSED, unsigned options UNUSED) +setlist_printips_sorted(struct set *set, void *data, + u_int32_t len UNUSED, unsigned options UNUSED, + char dont_align) { struct ip_set_setlist *mysetdata = set->settype->header; - int i; - ip_set_id_t id; + int i, asize; + ip_set_id_t *id; struct set *elem; + asize = IPSET_VALIGN(sizeof(ip_set_id_t), dont_align); for (i = 0; i < mysetdata->size; i++ ) { - id = *((ip_set_id_t *)data + i); - if (id == IP_SET_INVALID_ID) + DP("Try %u", i); + id = (ip_set_id_t *)(data + i * asize); + DP("Try %u, check", i); + if (*id == IP_SET_INVALID_ID) return; - elem = set_find_byid(id); + elem = set_find_byid(*id); printf("%s\n", elem->name); } } static void -saveheader(struct set *set, unsigned options UNUSED) +setlist_saveheader(struct set *set, unsigned options UNUSED) { struct ip_set_setlist *mysetdata = set->settype->header; @@ -161,24 +167,26 @@ saveheader(struct set *set, unsigned options UNUSED) } static void -saveips(struct set *set, void *data, - u_int32_t len UNUSED, unsigned options UNUSED) +setlist_saveips(struct set *set, void *data, + u_int32_t len UNUSED, unsigned options UNUSED, char dont_align) { struct ip_set_setlist *mysetdata = set->settype->header; - int i; - ip_set_id_t id; + int i, asize; + ip_set_id_t *id; struct set *elem; + asize = IPSET_VALIGN(sizeof(ip_set_id_t), dont_align); for (i = 0; i < mysetdata->size; i++ ) { - id = *((ip_set_id_t *)data + i); - if (id == IP_SET_INVALID_ID) + id = (ip_set_id_t *)(data + i * asize); + if (*id == IP_SET_INVALID_ID) return; - elem = set_find_byid(id); + elem = set_find_byid(*id); printf("-A %s %s\n", set->name, elem->name); } } -static void usage(void) +static void +setlist_usage(void) { printf ("-N set setlist --size size\n" @@ -193,25 +201,25 @@ static struct settype settype_setlist = { /* Create */ .create_size = sizeof(struct ip_set_req_setlist_create), - .create_init = &create_init, - .create_parse = &create_parse, - .create_final = &create_final, + .create_init = setlist_create_init, + .create_parse = setlist_create_parse, + .create_final = setlist_create_final, .create_opts = create_opts, /* Add/del/test */ .adt_size = sizeof(struct ip_set_req_setlist), - .adt_parser = &adt_parser, + .adt_parser = setlist_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, + .initheader = setlist_initheader, + .printheader = setlist_printheader, + .printips = setlist_printips_sorted, + .printips_sorted = setlist_printips_sorted, + .saveheader = setlist_saveheader, + .saveips = setlist_saveips, - .usage = &usage, + .usage = setlist_usage, }; CONSTRUCTOR(setlist) diff --git a/kernel/ChangeLog b/kernel/ChangeLog index 849e98e..192f689 100644 --- a/kernel/ChangeLog +++ b/kernel/ChangeLog @@ -1,5 +1,13 @@ +4.0 - Compilation of ip_set_iptree.c fails with kernel 2.6.20 due to missing include of linux/jiffies.h (Jan Engelhardt) + - Do not use DECLARE_MUTEX (compatibility fix on 2.6.31-rt, Jan + Engelhardt) + - Flushing iptreemap type of sets caused high ksoftirqd load due to + zeroed out timeout parameter (bug reported by Georg Chini) + - New protocol is introduced to handle aligment issues properly + (bug reported by Georg Chini) + - Binding support is removed 3.2 - Mixed up formats in ip_set_iptree.c (Rob Sterenborg) diff --git a/kernel/include/linux/netfilter_ipv4/ip_set.h b/kernel/include/linux/netfilter_ipv4/ip_set.h index 3667352..da17319 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set.h @@ -40,7 +40,8 @@ /* * Used so that the kernel module and ipset-binary can match their versions */ -#define IP_SET_PROTOCOL_VERSION 3 +#define IP_SET_PROTOCOL_UNALIGNED 3 +#define IP_SET_PROTOCOL_VERSION 4 #define IP_SET_MAXNAMELEN 32 /* set names and set typenames */ @@ -228,7 +229,7 @@ struct ip_set_req_max_sets { struct ip_set_req_setnames { unsigned op; ip_set_id_t index; /* set to list/save */ - u_int32_t size; /* size to get setdata/bindings */ + u_int32_t size; /* size to get setdata */ /* followed by sets number of struct ip_set_name_list */ }; @@ -302,6 +303,11 @@ static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b) /* General limit for the elements in a set */ #define MAX_RANGE 0x0000FFFF +/* Alignment: 'unsigned long' unsupported */ +#define IPSET_ALIGNTO 4 +#define IPSET_ALIGN(len) (((len) + IPSET_ALIGNTO - 1) & ~(IPSET_ALIGNTO - 1)) +#define IPSET_VALIGN(len, old) ((old) ? (len) : IPSET_ALIGN(len)) + #ifdef __KERNEL__ #include <linux/netfilter_ipv4/ip_set_compat.h> #include <linux/netfilter_ipv4/ip_set_malloc.h> @@ -350,16 +356,13 @@ struct ip_set_type { */ int (*testip_kernel) (struct ip_set *set, const struct sk_buff * skb, - ip_set_ip_t *ip, - const u_int32_t *flags, - unsigned char index); + const u_int32_t *flags); /* test for IP in set (userspace: ipset -T set IP) * return 0 if not in set, 1 if in set. */ int (*testip) (struct ip_set *set, - const void *data, u_int32_t size, - ip_set_ip_t *ip); + const void *data, u_int32_t size); /* * Size of the data structure passed by when @@ -373,8 +376,7 @@ struct ip_set_type { * If the address was not already in the set, 0 is returned. */ int (*addip) (struct ip_set *set, - const void *data, u_int32_t size, - ip_set_ip_t *ip); + const void *data, u_int32_t size); /* Add IP into set (kernel: iptables ... -j SET set src|dst) * Return -EEXIST if the address is already in the set, @@ -382,10 +384,8 @@ struct ip_set_type { * If the address was not already in the set, 0 is returned. */ int (*addip_kernel) (struct ip_set *set, - const struct sk_buff * skb, - ip_set_ip_t *ip, - const u_int32_t *flags, - unsigned char index); + const struct sk_buff * skb, + const u_int32_t *flags); /* remove IP from set (userspace: ipset -D set --entry x) * Return -EEXIST if the address is NOT in the set, @@ -393,8 +393,7 @@ struct ip_set_type { * If the address really was in the set, 0 is returned. */ int (*delip) (struct ip_set *set, - const void *data, u_int32_t size, - ip_set_ip_t *ip); + const void *data, u_int32_t size); /* remove IP from set (kernel: iptables ... -j SET --entry x) * Return -EEXIST if the address is NOT in the set, @@ -402,10 +401,8 @@ struct ip_set_type { * If the address really was in the set, 0 is returned. */ int (*delip_kernel) (struct ip_set *set, - const struct sk_buff * skb, - ip_set_ip_t *ip, - const u_int32_t *flags, - unsigned char index); + const struct sk_buff * skb, + const u_int32_t *flags); /* new set creation - allocated type specific items */ @@ -443,7 +440,7 @@ struct ip_set_type { /* Listing: Get the size for the set members */ - int (*list_members_size) (const struct ip_set *set); + int (*list_members_size) (const struct ip_set *set, char dont_align); /* Listing: Get the set members * @@ -453,7 +450,7 @@ struct ip_set_type { * correct. */ void (*list_members) (const struct ip_set *set, - void *data); + void *data, char dont_align); char typename[IP_SET_MAXNAMELEN]; unsigned char features; @@ -471,20 +468,11 @@ struct ip_set { char name[IP_SET_MAXNAMELEN]; /* the name of the set */ rwlock_t lock; /* lock for concurrency control */ ip_set_id_t id; /* set id for swapping */ - ip_set_id_t binding; /* default binding for the set */ atomic_t ref; /* in kernel and in hash references */ struct ip_set_type *type; /* the set types */ void *data; /* pooltype specific data */ }; -/* Structure to bind set elements to sets */ -struct ip_set_hash { - struct list_head list; /* list of clashing entries in hash */ - ip_set_ip_t ip; /* ip from set */ - ip_set_id_t id; /* set id */ - ip_set_id_t binding; /* set we bind the element to */ -}; - /* register and unregister set references */ 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 index); @@ -515,12 +503,11 @@ extern int ip_set_testip_kernel(ip_set_id_t id, #define UADT0(type, adt, args...) \ static int \ -FNAME(type,_u,adt)(struct ip_set *set, const void *data, u_int32_t size,\ - ip_set_ip_t *hash_ip) \ +FNAME(type,_u,adt)(struct ip_set *set, const void *data, u_int32_t size)\ { \ const STRUCT(ip_set_req_,type) *req = data; \ \ - return FNAME(type,_,adt)(set, hash_ip , ## args); \ + return FNAME(type,_,adt)(set , ## args); \ } #define UADT(type, adt, args...) \ @@ -530,14 +517,12 @@ FNAME(type,_u,adt)(struct ip_set *set, const void *data, u_int32_t size,\ 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) \ + const u_int32_t *flags) \ { \ - ip_set_ip_t ip = getfn(skb, flags[index]); \ + ip_set_ip_t ip = getfn(skb, flags); \ \ KADT_CONDITION \ - return FNAME(type,_,adt)(set, hash_ip, ip , ##args); \ + return FNAME(type,_,adt)(set, ip , ##args); \ } #define REGISTER_MODULE(type) \ @@ -559,9 +544,9 @@ module_exit(ip_set_##type##_fini); /* Common functions */ static inline ip_set_ip_t -ipaddr(const struct sk_buff *skb, u_int32_t flag) +ipaddr(const struct sk_buff *skb, const u_int32_t *flags) { - return ntohl(flag & IPSET_SRC ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr); + return ntohl(flags[0] & IPSET_SRC ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr); } #define jhash_ip(map, i, ip) jhash_1word(ip, *(map->initval + i)) @@ -571,4 +556,6 @@ ipaddr(const struct sk_buff *skb, u_int32_t flag) #endif /* __KERNEL__ */ +#define UNUSED __attribute__ ((unused)) + #endif /*_IP_SET_H*/ diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_bitmaps.h b/kernel/include/linux/netfilter_ipv4/ip_set_bitmaps.h index 90e87e3..da3493f 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_bitmaps.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_bitmaps.h @@ -77,22 +77,21 @@ type##_list_header(const struct ip_set *set, void *data) \ __##type##_list_header(map, header); \ } -#define BITMAP_LIST_MEMBERS_SIZE(type) \ +#define BITMAP_LIST_MEMBERS_SIZE(type, dtype, sizeid, testfn) \ static int \ -type##_list_members_size(const struct ip_set *set) \ +type##_list_members_size(const struct ip_set *set, char dont_align) \ { \ const struct ip_set_##type *map = set->data; \ + ip_set_ip_t i, elements = 0; \ \ - 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; \ + if (dont_align) \ + return map->size; \ + \ + for (i = 0; i < sizeid; i++) \ + if (testfn) \ + elements++; \ \ - memcpy(data, map->members, map->size); \ + return elements * IPSET_ALIGN(sizeof(dtype)); \ } #define IP_SET_TYPE(type, __features) \ diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_compat.h b/kernel/include/linux/netfilter_ipv4/ip_set_compat.h index 96c2024..9f17397 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_compat.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_compat.h @@ -65,7 +65,28 @@ static inline void *kzalloc(size_t size, gfp_t flags) #define KMEM_CACHE_CREATE(name, size) \ kmem_cache_create(name, size, 0, 0, NULL) #endif - + +#ifndef NIPQUAD +#define NIPQUAD(addr) \ + ((unsigned char *)&addr)[0], \ + ((unsigned char *)&addr)[1], \ + ((unsigned char *)&addr)[2], \ + ((unsigned char *)&addr)[3] +#endif + +#ifndef HIPQUAD +#if defined(__LITTLE_ENDIAN) +#define HIPQUAD(addr) \ + ((unsigned char *)&addr)[3], \ + ((unsigned char *)&addr)[2], \ + ((unsigned char *)&addr)[1], \ + ((unsigned char *)&addr)[0] +#elif defined(__BIG_ENDIAN) +#define HIPQUAD NIPQUAD +#else +#error "Please fix asm/byteorder.h" +#endif /* __LITTLE_ENDIAN */ +#endif #endif /* __KERNEL__ */ #endif /* _IP_SET_COMPAT_H */ diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_getport.h b/kernel/include/linux/netfilter_ipv4/ip_set_getport.h index 9e322bf..18ed729 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_getport.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_getport.h @@ -7,7 +7,7 @@ /* We must handle non-linear skbs */ static inline ip_set_ip_t -get_port(const struct sk_buff *skb, u_int32_t flags) +get_port(const struct sk_buff *skb, const u_int32_t *flags) { struct iphdr *iph = ip_hdr(skb); u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET; @@ -23,7 +23,7 @@ get_port(const struct sk_buff *skb, u_int32_t flags) /* No choice either */ return INVALID_PORT; - return ntohs(flags & IPSET_SRC ? + return ntohs(flags[0] & IPSET_SRC ? tcph.source : tcph.dest); } case IPPROTO_UDP: { @@ -36,7 +36,7 @@ get_port(const struct sk_buff *skb, u_int32_t flags) /* No choice either */ return INVALID_PORT; - return ntohs(flags & IPSET_SRC ? + return ntohs(flags[0] & IPSET_SRC ? udph.source : udph.dest); } default: diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_hashes.h b/kernel/include/linux/netfilter_ipv4/ip_set_hashes.h index f7d6a69..f62ae37 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_hashes.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_hashes.h @@ -182,30 +182,31 @@ type##_list_header(const struct ip_set *set, void *data) \ #define HASH_LIST_MEMBERS_SIZE(type, dtype) \ static int \ -type##_list_members_size(const struct ip_set *set) \ +type##_list_members_size(const struct ip_set *set, char dont_align) \ { \ const struct ip_set_##type *map = set->data; \ \ - return (map->hashsize * sizeof(dtype)); \ + return (map->hashsize * IPSET_VALIGN(sizeof(dtype), dont_align));\ } #define HASH_LIST_MEMBERS(type, dtype) \ static void \ -type##_list_members(const struct ip_set *set, void *data) \ +type##_list_members(const struct ip_set *set, void *data, char dont_align)\ { \ const struct ip_set_##type *map = set->data; \ - dtype *elem; \ + dtype *elem, *d; \ uint32_t i; \ \ for (i = 0; i < map->hashsize; i++) { \ elem = HARRAY_ELEM(map->members, dtype *, i); \ - ((dtype *)data)[i] = *elem; \ + d = data + i * IPSET_VALIGN(sizeof(dtype), dont_align); \ + *d = *elem; \ } \ } #define HASH_LIST_MEMBERS_MEMCPY(type, dtype) \ static void \ -type##_list_members(const struct ip_set *set, void *data) \ +type##_list_members(const struct ip_set *set, void *data, char dont_align)\ { \ const struct ip_set_##type *map = set->data; \ dtype *elem; \ @@ -213,7 +214,8 @@ type##_list_members(const struct ip_set *set, void *data) \ \ for (i = 0; i < map->hashsize; i++) { \ elem = HARRAY_ELEM(map->members, dtype *, i); \ - memcpy((((dtype *)data)+i), elem, sizeof(dtype)); \ + memcpy(data + i * IPSET_VALIGN(sizeof(dtype), dont_align),\ + elem, sizeof(dtype)); \ } \ } diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_iphash.h b/kernel/include/linux/netfilter_ipv4/ip_set_iphash.h index 277bc8c..0a0c7e8 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_iphash.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_iphash.h @@ -4,7 +4,7 @@ #include <linux/netfilter_ipv4/ip_set.h> #include <linux/netfilter_ipv4/ip_set_hashes.h> -#define SETTYPE_NAME "iphash" +#define SETTYPE_NAME "iphash" struct ip_set_iphash { ip_set_ip_t *members; /* the iphash proper */ diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h b/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h index ce4b29b..d16c0ae 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h @@ -4,7 +4,7 @@ #include <linux/netfilter_ipv4/ip_set.h> #include <linux/netfilter_ipv4/ip_set_bitmaps.h> -#define SETTYPE_NAME "ipmap" +#define SETTYPE_NAME "ipmap" struct ip_set_ipmap { void *members; /* the ipmap proper */ diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_ipporthash.h b/kernel/include/linux/netfilter_ipv4/ip_set_ipporthash.h index b5db5f5..a3b781a 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_ipporthash.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_ipporthash.h @@ -4,7 +4,7 @@ #include <linux/netfilter_ipv4/ip_set.h> #include <linux/netfilter_ipv4/ip_set_hashes.h> -#define SETTYPE_NAME "ipporthash" +#define SETTYPE_NAME "ipporthash" struct ip_set_ipporthash { ip_set_ip_t *members; /* the ipporthash proper */ diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_ipportiphash.h b/kernel/include/linux/netfilter_ipv4/ip_set_ipportiphash.h index eb6cf55..2202c51 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_ipportiphash.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_ipportiphash.h @@ -4,7 +4,7 @@ #include <linux/netfilter_ipv4/ip_set.h> #include <linux/netfilter_ipv4/ip_set_hashes.h> -#define SETTYPE_NAME "ipportiphash" +#define SETTYPE_NAME "ipportiphash" struct ipportip { ip_set_ip_t ip; diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_ipportnethash.h b/kernel/include/linux/netfilter_ipv4/ip_set_ipportnethash.h index 951da92..73b2430 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_ipportnethash.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_ipportnethash.h @@ -4,7 +4,7 @@ #include <linux/netfilter_ipv4/ip_set.h> #include <linux/netfilter_ipv4/ip_set_hashes.h> -#define SETTYPE_NAME "ipportnethash" +#define SETTYPE_NAME "ipportnethash" struct ipportip { ip_set_ip_t ip; diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_iptree.h b/kernel/include/linux/netfilter_ipv4/ip_set_iptree.h index de5cf47..36bf5ac 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_iptree.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_iptree.h @@ -3,7 +3,7 @@ #include <linux/netfilter_ipv4/ip_set.h> -#define SETTYPE_NAME "iptree" +#define SETTYPE_NAME "iptree" struct ip_set_iptreed { unsigned long expires[256]; /* x.x.x.ADDR */ diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_iptreemap.h b/kernel/include/linux/netfilter_ipv4/ip_set_iptreemap.h index a58bc4e..6ea771a 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_iptreemap.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_iptreemap.h @@ -3,7 +3,7 @@ #include <linux/netfilter_ipv4/ip_set.h> -#define SETTYPE_NAME "iptreemap" +#define SETTYPE_NAME "iptreemap" #ifdef __KERNEL__ struct ip_set_iptreemap_d { diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_macipmap.h b/kernel/include/linux/netfilter_ipv4/ip_set_macipmap.h index 19418f3..0615e9f 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_macipmap.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_macipmap.h @@ -4,7 +4,7 @@ #include <linux/netfilter_ipv4/ip_set.h> #include <linux/netfilter_ipv4/ip_set_bitmaps.h> -#define SETTYPE_NAME "macipmap" +#define SETTYPE_NAME "macipmap" /* general flags */ #define IPSET_MACIP_MATCHUNSET 1 diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_nethash.h b/kernel/include/linux/netfilter_ipv4/ip_set_nethash.h index b2d006f..cf0b794 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_nethash.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_nethash.h @@ -4,7 +4,7 @@ #include <linux/netfilter_ipv4/ip_set.h> #include <linux/netfilter_ipv4/ip_set_hashes.h> -#define SETTYPE_NAME "nethash" +#define SETTYPE_NAME "nethash" struct ip_set_nethash { ip_set_ip_t *members; /* the nethash proper */ diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_portmap.h b/kernel/include/linux/netfilter_ipv4/ip_set_portmap.h index 8ea6ba2..37f411e 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_portmap.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_portmap.h @@ -4,7 +4,7 @@ #include <linux/netfilter_ipv4/ip_set.h> #include <linux/netfilter_ipv4/ip_set_bitmaps.h> -#define SETTYPE_NAME "portmap" +#define SETTYPE_NAME "portmap" struct ip_set_portmap { void *members; /* the portmap proper */ diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_setlist.h b/kernel/include/linux/netfilter_ipv4/ip_set_setlist.h index ca044d8..7cc6ed0 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_setlist.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_setlist.h @@ -3,7 +3,7 @@ #include <linux/netfilter_ipv4/ip_set.h> -#define SETTYPE_NAME "setlist" +#define SETTYPE_NAME "setlist" #define IP_SET_SETLIST_ADD_AFTER 0 #define IP_SET_SETLIST_ADD_BEFORE 1 diff --git a/kernel/ip_set.c b/kernel/ip_set.c index c836d85..30185c5 100644 --- a/kernel/ip_set.c +++ b/kernel/ip_set.c @@ -39,19 +39,18 @@ static struct list_head set_type_list; /* all registered sets */ static struct ip_set **ip_set_list; /* all individual sets */ static DEFINE_RWLOCK(ip_set_lock); /* protects the lists and the hash */ -static DECLARE_MUTEX(ip_set_app_mutex); /* serializes user access */ +static struct semaphore ip_set_app_mutex; /* serializes user access */ static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX; -static ip_set_id_t ip_set_bindings_hash_size = CONFIG_IP_NF_SET_HASHSIZE; -static struct list_head *ip_set_hash; /* hash of bindings */ -static unsigned int ip_set_hash_random; /* random seed */ +static int protocol_version = IP_SET_PROTOCOL_VERSION; -#define SETNAME_EQ(a,b) (strncmp(a,b,IP_SET_MAXNAMELEN) == 0) +#define STREQ(a,b) (strncmp(a,b,IP_SET_MAXNAMELEN) == 0) +#define DONT_ALIGN (protocol_version == IP_SET_PROTOCOL_UNALIGNED) +#define ALIGNED(len) IPSET_VALIGN(len, DONT_ALIGN) /* * Sets are identified either by the index in ip_set_list or by id. - * The id never changes and is used to find a key in the hash. - * The index may change by swapping and used at all other places - * (set/SET netfilter modules, binding value, etc.) + * The id never changes. The index may change by swapping and used + * by external references (set/SET netfilter modules, etc.) * * Userspace requests are serialized by ip_set_mutex and sets can * be deleted only from userspace. Therefore ip_set_list locking @@ -73,166 +72,25 @@ __ip_set_put(ip_set_id_t index) atomic_dec(&ip_set_list[index]->ref); } -/* - * Binding routines - */ - -static inline struct ip_set_hash * -__ip_set_find(u_int32_t key, ip_set_id_t id, ip_set_ip_t ip) -{ - struct ip_set_hash *set_hash; - - list_for_each_entry(set_hash, &ip_set_hash[key], list) - if (set_hash->id == id && set_hash->ip == ip) - return set_hash; - - return NULL; -} - -static ip_set_id_t -ip_set_find_in_hash(ip_set_id_t id, ip_set_ip_t ip) -{ - u_int32_t key = jhash_2words(id, ip, ip_set_hash_random) - % ip_set_bindings_hash_size; - struct ip_set_hash *set_hash; - - ASSERT_READ_LOCK(&ip_set_lock); - IP_SET_ASSERT(ip_set_list[id]); - DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip)); - - set_hash = __ip_set_find(key, id, ip); - - DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, - HIPQUAD(ip), - set_hash != NULL ? ip_set_list[set_hash->binding]->name : ""); - - return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID); -} - -static inline void -__set_hash_del(struct ip_set_hash *set_hash) -{ - ASSERT_WRITE_LOCK(&ip_set_lock); - IP_SET_ASSERT(ip_set_list[set_hash->binding]); - - __ip_set_put(set_hash->binding); - list_del(&set_hash->list); - kfree(set_hash); -} - -static int -ip_set_hash_del(ip_set_id_t id, ip_set_ip_t ip) -{ - u_int32_t key = jhash_2words(id, ip, ip_set_hash_random) - % ip_set_bindings_hash_size; - struct ip_set_hash *set_hash; - - IP_SET_ASSERT(ip_set_list[id]); - DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip)); - write_lock_bh(&ip_set_lock); - set_hash = __ip_set_find(key, id, ip); - DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, - HIPQUAD(ip), - set_hash != NULL ? ip_set_list[set_hash->binding]->name : ""); - - if (set_hash != NULL) - __set_hash_del(set_hash); - write_unlock_bh(&ip_set_lock); - return 0; -} - -static int -ip_set_hash_add(ip_set_id_t id, ip_set_ip_t ip, ip_set_id_t binding) -{ - u_int32_t key = jhash_2words(id, ip, ip_set_hash_random) - % ip_set_bindings_hash_size; - struct ip_set_hash *set_hash; - int ret = 0; - - IP_SET_ASSERT(ip_set_list[id]); - IP_SET_ASSERT(ip_set_list[binding]); - DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, - HIPQUAD(ip), ip_set_list[binding]->name); - write_lock_bh(&ip_set_lock); - set_hash = __ip_set_find(key, id, ip); - if (!set_hash) { - set_hash = kmalloc(sizeof(struct ip_set_hash), GFP_ATOMIC); - if (!set_hash) { - ret = -ENOMEM; - goto unlock; - } - INIT_LIST_HEAD(&set_hash->list); - set_hash->id = id; - set_hash->ip = ip; - list_add(&set_hash->list, &ip_set_hash[key]); - } else { - IP_SET_ASSERT(ip_set_list[set_hash->binding]); - DP("overwrite binding: %s", - ip_set_list[set_hash->binding]->name); - __ip_set_put(set_hash->binding); - } - set_hash->binding = binding; - __ip_set_get(set_hash->binding); - DP("stored: key %u, id %u (%s), ip %u.%u.%u.%u, binding %u (%s)", - key, id, ip_set_list[id]->name, - HIPQUAD(ip), binding, ip_set_list[binding]->name); - unlock: - write_unlock_bh(&ip_set_lock); - return ret; -} - -#define FOREACH_HASH_DO(fn, args...) \ -({ \ - ip_set_id_t __key; \ - struct ip_set_hash *__set_hash; \ - \ - for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \ - list_for_each_entry(__set_hash, &ip_set_hash[__key], list) \ - fn(__set_hash , ## args); \ - } \ -}) - -#define FOREACH_HASH_RW_DO(fn, args...) \ -({ \ - ip_set_id_t __key; \ - struct ip_set_hash *__set_hash, *__n; \ - \ - ASSERT_WRITE_LOCK(&ip_set_lock); \ - for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \ - list_for_each_entry_safe(__set_hash, __n, &ip_set_hash[__key], list)\ - fn(__set_hash , ## args); \ - } \ -}) - /* Add, del and test set entries from kernel */ -#define follow_bindings(index, set, ip) \ -((index = ip_set_find_in_hash((set)->id, ip)) != IP_SET_INVALID_ID \ - || (index = (set)->binding) != IP_SET_INVALID_ID) - int ip_set_testip_kernel(ip_set_id_t index, const struct sk_buff *skb, const u_int32_t *flags) { struct ip_set *set; - ip_set_ip_t ip; int res; - unsigned char i = 0; - - IP_SET_ASSERT(flags[i]); + read_lock_bh(&ip_set_lock); - do { - set = ip_set_list[index]; - IP_SET_ASSERT(set); - DP("set %s, index %u", set->name, index); - read_lock_bh(&set->lock); - res = set->type->testip_kernel(set, skb, &ip, flags, i++); - read_unlock_bh(&set->lock); - i += !!(set->type->features & IPSET_DATA_DOUBLE); - } while (res > 0 - && flags[i] - && follow_bindings(index, set, ip)); + set = ip_set_list[index]; + IP_SET_ASSERT(set); + DP("set %s, index %u", set->name, index); + + read_lock_bh(&set->lock); + res = set->type->testip_kernel(set, skb, flags); + read_unlock_bh(&set->lock); + read_unlock_bh(&ip_set_lock); return (res < 0 ? 0 : res); @@ -244,26 +102,20 @@ ip_set_addip_kernel(ip_set_id_t index, const u_int32_t *flags) { struct ip_set *set; - ip_set_ip_t ip; int res; - unsigned char i = 0; - IP_SET_ASSERT(flags[i]); retry: read_lock_bh(&ip_set_lock); - do { - set = ip_set_list[index]; - IP_SET_ASSERT(set); - DP("set %s, index %u", set->name, index); - write_lock_bh(&set->lock); - res = set->type->addip_kernel(set, skb, &ip, flags, i++); - write_unlock_bh(&set->lock); - i += !!(set->type->features & IPSET_DATA_DOUBLE); - } while ((res == 0 || res == -EEXIST) - && flags[i] - && follow_bindings(index, set, ip)); - read_unlock_bh(&ip_set_lock); + set = ip_set_list[index]; + IP_SET_ASSERT(set); + DP("set %s, index %u", set->name, index); + write_lock_bh(&set->lock); + res = set->type->addip_kernel(set, skb, flags); + write_unlock_bh(&set->lock); + + read_unlock_bh(&ip_set_lock); + /* Retry function called without holding any lock */ if (res == -EAGAIN && set->type->retry && (res = set->type->retry(set)) == 0) @@ -278,23 +130,17 @@ ip_set_delip_kernel(ip_set_id_t index, const u_int32_t *flags) { struct ip_set *set; - ip_set_ip_t ip; int res; - unsigned char i = 0; - IP_SET_ASSERT(flags[i]); read_lock_bh(&ip_set_lock); - do { - set = ip_set_list[index]; - IP_SET_ASSERT(set); - DP("set %s, index %u", set->name, index); - write_lock_bh(&set->lock); - res = set->type->delip_kernel(set, skb, &ip, flags, i++); - write_unlock_bh(&set->lock); - i += !!(set->type->features & IPSET_DATA_DOUBLE); - } while ((res == 0 || res == -EEXIST) - && flags[i] - && follow_bindings(index, set, ip)); + set = ip_set_list[index]; + IP_SET_ASSERT(set); + DP("set %s, index %u", set->name, index); + + write_lock_bh(&set->lock); + res = set->type->delip_kernel(set, skb, flags); + write_unlock_bh(&set->lock); + read_unlock_bh(&ip_set_lock); return res; @@ -308,7 +154,7 @@ find_set_type(const char *name) struct ip_set_type *set_type; list_for_each_entry(set_type, &set_type_list, list) - if (!strncmp(set_type->typename, name, IP_SET_MAXNAMELEN - 1)) + if (STREQ(set_type->typename, name)) return set_type; return NULL; } @@ -369,7 +215,7 @@ __ip_set_get_byname(const char *name, struct ip_set **set) for (i = 0; i < ip_set_max; i++) { if (ip_set_list[i] != NULL - && SETNAME_EQ(ip_set_list[i]->name, name)) { + && STREQ(ip_set_list[i]->name, name)) { __ip_set_get(i); index = i; *set = ip_set_list[i]; @@ -379,7 +225,8 @@ __ip_set_get_byname(const char *name, struct ip_set **set) return index; } -void __ip_set_put_byindex(ip_set_id_t index) +void +__ip_set_put_byindex(ip_set_id_t index) { if (ip_set_list[index]) __ip_set_put(index); @@ -402,7 +249,7 @@ ip_set_get_byname(const char *name) down(&ip_set_app_mutex); for (i = 0; i < ip_set_max; i++) { if (ip_set_list[i] != NULL - && SETNAME_EQ(ip_set_list[i]->name, name)) { + && STREQ(ip_set_list[i]->name, name)) { __ip_set_get(i); index = i; break; @@ -453,7 +300,8 @@ ip_set_id(ip_set_id_t index) * reference count by 1. The caller shall not assume the index * to be valid, after calling this function. */ -void ip_set_put_byindex(ip_set_id_t index) +void +ip_set_put_byindex(ip_set_id_t index) { down(&ip_set_app_mutex); if (ip_set_list[index]) @@ -469,7 +317,7 @@ ip_set_find_byname(const char *name) for (i = 0; i < ip_set_max; i++) { if (ip_set_list[i] != NULL - && SETNAME_EQ(ip_set_list[i]->name, name)) { + && STREQ(ip_set_list[i]->name, name)) { index = i; break; } @@ -487,37 +335,18 @@ ip_set_find_byindex(ip_set_id_t index) } /* - * Add, del, test, bind and unbind + * Add, del and test */ -static inline int -__ip_set_testip(struct ip_set *set, - const void *data, - u_int32_t size, - ip_set_ip_t *ip) -{ - int res; - - read_lock_bh(&set->lock); - res = set->type->testip(set, data, size, ip); - read_unlock_bh(&set->lock); - - return res; -} - static int -__ip_set_addip(ip_set_id_t index, - const void *data, - u_int32_t size) +ip_set_addip(struct ip_set *set, const void *data, u_int32_t size) { - struct ip_set *set = ip_set_list[index]; - ip_set_ip_t ip; int res; IP_SET_ASSERT(set); do { write_lock_bh(&set->lock); - res = set->type->addip(set, data, size, &ip); + res = set->type->addip(set, data, size); write_unlock_bh(&set->lock); } while (res == -EAGAIN && set->type->retry @@ -527,289 +356,33 @@ __ip_set_addip(ip_set_id_t index, } static int -ip_set_addip(ip_set_id_t index, - const void *data, - u_int32_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 %lu, have %zu)", - (long unsigned)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)); -} - -static int -ip_set_delip(ip_set_id_t index, - const void *data, - u_int32_t size) +ip_set_delip(struct ip_set *set, const void *data, u_int32_t size) { - struct ip_set *set = ip_set_list[index]; - ip_set_ip_t ip; int res; IP_SET_ASSERT(set); - if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) { - ip_set_printk("data length wrong (want %lu, have %zu)", - (long unsigned)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), - size - sizeof(struct ip_set_req_adt), - &ip); + res = set->type->delip(set, data, size); write_unlock_bh(&set->lock); return res; } static int -ip_set_testip(ip_set_id_t index, - const void *data, - u_int32_t size) +ip_set_testip(struct ip_set *set, const void *data, u_int32_t size) { - struct ip_set *set = ip_set_list[index]; - ip_set_ip_t ip; int res; IP_SET_ASSERT(set); - if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) { - ip_set_printk("data length wrong (want %lu, have %zu)", - (long unsigned)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), - &ip); + read_lock_bh(&set->lock); + res = set->type->testip(set, data, size); + read_unlock_bh(&set->lock); return (res > 0 ? -EEXIST : res); } -static int -ip_set_bindip(ip_set_id_t index, - const void *data, - u_int32_t size) -{ - struct ip_set *set = ip_set_list[index]; - const struct ip_set_req_bind *req_bind; - ip_set_id_t binding; - ip_set_ip_t ip; - int res; - - IP_SET_ASSERT(set); - if (size < sizeof(struct ip_set_req_bind)) - return -EINVAL; - - req_bind = data; - - if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) { - /* Default binding of a set */ - const char *binding_name; - - if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN) - return -EINVAL; - - binding_name = data + sizeof(struct ip_set_req_bind); - - binding = ip_set_find_byname(binding_name); - if (binding == IP_SET_INVALID_ID) - return -ENOENT; - - write_lock_bh(&ip_set_lock); - /* Sets as binding values are referenced */ - if (set->binding != IP_SET_INVALID_ID) - __ip_set_put(set->binding); - set->binding = binding; - __ip_set_get(set->binding); - write_unlock_bh(&ip_set_lock); - - return 0; - } - binding = ip_set_find_byname(req_bind->binding); - if (binding == IP_SET_INVALID_ID) - return -ENOENT; - - res = __ip_set_testip(set, - data + sizeof(struct ip_set_req_bind), - size - sizeof(struct ip_set_req_bind), - &ip); - DP("set %s, ip: %u.%u.%u.%u, binding %s", - set->name, HIPQUAD(ip), ip_set_list[binding]->name); - - if (res >= 0) - res = ip_set_hash_add(set->id, ip, binding); - - return res; -} - -#define FOREACH_SET_DO(fn, args...) \ -({ \ - ip_set_id_t __i; \ - struct ip_set *__set; \ - \ - for (__i = 0; __i < ip_set_max; __i++) { \ - __set = ip_set_list[__i]; \ - if (__set != NULL) \ - fn(__set , ##args); \ - } \ -}) - -static inline void -__set_hash_del_byid(struct ip_set_hash *set_hash, ip_set_id_t id) -{ - if (set_hash->id == id) - __set_hash_del(set_hash); -} - -static inline void -__unbind_default(struct ip_set *set) -{ - if (set->binding != IP_SET_INVALID_ID) { - /* Sets as binding values are referenced */ - __ip_set_put(set->binding); - set->binding = IP_SET_INVALID_ID; - } -} - -static int -ip_set_unbindip(ip_set_id_t index, - const void *data, - u_int32_t size) -{ - struct ip_set *set; - const struct ip_set_req_bind *req_bind; - ip_set_ip_t ip; - int res; - - DP(""); - if (size < sizeof(struct ip_set_req_bind)) - return -EINVAL; - - req_bind = data; - - DP("%u %s", index, req_bind->binding); - if (index == IP_SET_INVALID_ID) { - /* unbind :all: */ - if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) { - /* Default binding of sets */ - write_lock_bh(&ip_set_lock); - FOREACH_SET_DO(__unbind_default); - write_unlock_bh(&ip_set_lock); - return 0; - } else if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_ALL)) { - /* Flush all bindings of all sets*/ - write_lock_bh(&ip_set_lock); - FOREACH_HASH_RW_DO(__set_hash_del); - write_unlock_bh(&ip_set_lock); - return 0; - } - DP("unreachable reached!"); - return -EINVAL; - } - - set = ip_set_list[index]; - IP_SET_ASSERT(set); - if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) { - /* Default binding of set */ - ip_set_id_t binding = ip_set_find_byindex(set->binding); - - if (binding == IP_SET_INVALID_ID) - return -ENOENT; - - write_lock_bh(&ip_set_lock); - /* Sets in hash values are referenced */ - __ip_set_put(set->binding); - set->binding = IP_SET_INVALID_ID; - write_unlock_bh(&ip_set_lock); - - return 0; - } else if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_ALL)) { - /* Flush all bindings */ - - write_lock_bh(&ip_set_lock); - FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id); - write_unlock_bh(&ip_set_lock); - return 0; - } - - res = __ip_set_testip(set, - data + sizeof(struct ip_set_req_bind), - size - sizeof(struct ip_set_req_bind), - &ip); - - DP("set %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip)); - if (res >= 0) - res = ip_set_hash_del(set->id, ip); - - return res; -} - -static int -ip_set_testbind(ip_set_id_t index, - const void *data, - u_int32_t size) -{ - struct ip_set *set = ip_set_list[index]; - const struct ip_set_req_bind *req_bind; - ip_set_id_t binding; - ip_set_ip_t ip; - int res; - - IP_SET_ASSERT(set); - if (size < sizeof(struct ip_set_req_bind)) - return -EINVAL; - - req_bind = data; - - if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) { - /* Default binding of set */ - const char *binding_name; - - if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN) - return -EINVAL; - - binding_name = data + sizeof(struct ip_set_req_bind); - - binding = ip_set_find_byname(binding_name); - if (binding == IP_SET_INVALID_ID) - return -ENOENT; - - res = (set->binding == binding) ? -EEXIST : 0; - - return res; - } - binding = ip_set_find_byname(req_bind->binding); - if (binding == IP_SET_INVALID_ID) - return -ENOENT; - - - res = __ip_set_testip(set, - data + sizeof(struct ip_set_req_bind), - size - sizeof(struct ip_set_req_bind), - &ip); - DP("set %s, ip: %u.%u.%u.%u, binding %s", - set->name, HIPQUAD(ip), ip_set_list[binding]->name); - - if (res >= 0) - res = (ip_set_find_in_hash(set->id, ip) == binding) - ? -EEXIST : 0; - - return res; -} - static struct ip_set_type * find_set_type_rlock(const char *typename) { @@ -835,7 +408,7 @@ find_free_id(const char *name, if (ip_set_list[i] == NULL) { if (*id == IP_SET_INVALID_ID) *id = *index = i; - } else if (SETNAME_EQ(name, ip_set_list[i]->name)) + } else if (STREQ(name, ip_set_list[i]->name)) /* Name clash */ return -EEXIST; } @@ -879,7 +452,6 @@ ip_set_create(const char *name, return -ENOMEM; rwlock_init(&set->lock); strncpy(set->name, name, IP_SET_MAXNAMELEN); - set->binding = IP_SET_INVALID_ID; atomic_set(&set->ref, 0); /* @@ -978,9 +550,6 @@ ip_set_destroy_set(ip_set_id_t index) IP_SET_ASSERT(set); DP("set: %s", set->name); write_lock_bh(&ip_set_lock); - FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id); - if (set->binding != IP_SET_INVALID_ID) - __ip_set_put(set->binding); ip_set_list[index] = NULL; write_unlock_bh(&ip_set_lock); @@ -1038,8 +607,13 @@ ip_set_flush(ip_set_id_t index) if (index != IP_SET_INVALID_ID) { IP_SET_ASSERT(ip_set_list[index]); ip_set_flush_set(ip_set_list[index]); - } else - FOREACH_SET_DO(ip_set_flush_set); + } else { + ip_set_id_t i; + + for (i = 0; i < ip_set_max; i++) + if (ip_set_list[i] != NULL) + ip_set_flush_set(ip_set_list[i]); + } return 0; } @@ -1056,7 +630,7 @@ ip_set_rename(ip_set_id_t index, const char *name) write_lock_bh(&ip_set_lock); for (i = 0; i < ip_set_max; i++) { if (ip_set_list[i] != NULL - && SETNAME_EQ(ip_set_list[i]->name, name)) { + && STREQ(ip_set_list[i]->name, name)) { res = -EEXIST; goto unlock; } @@ -1107,39 +681,8 @@ ip_set_swap(ip_set_id_t from_index, ip_set_id_t to_index) * List set data */ -static inline void -__set_hash_bindings_size_list(struct ip_set_hash *set_hash, - ip_set_id_t id, u_int32_t *size) -{ - if (set_hash->id == id) - *size += sizeof(struct ip_set_hash_list); -} - -static inline void -__set_hash_bindings_size_save(struct ip_set_hash *set_hash, - ip_set_id_t id, u_int32_t *size) -{ - if (set_hash->id == id) - *size += sizeof(struct ip_set_hash_save); -} - -static inline void -__set_hash_bindings(struct ip_set_hash *set_hash, - ip_set_id_t id, void *data, int *used) -{ - if (set_hash->id == id) { - struct ip_set_hash_list *hash_list = data + *used; - - hash_list->ip = set_hash->ip; - hash_list->binding = set_hash->binding; - *used += sizeof(struct ip_set_hash_list); - } -} - -static int ip_set_list_set(ip_set_id_t index, - void *data, - int *used, - int len) +static int +ip_set_list_set(ip_set_id_t index, void *data, int *used, int len) { struct ip_set *set = ip_set_list[index]; struct ip_set_list *set_list; @@ -1147,22 +690,22 @@ static int ip_set_list_set(ip_set_id_t index, /* Pointer to our header */ set_list = data + *used; - DP("set: %s, used: %d %p %p", set->name, *used, data, data + *used); + DP("set: %s, used: %d len %u %p %p", set->name, *used, len, data, data + *used); /* Get and ensure header size */ - if (*used + sizeof(struct ip_set_list) > len) + if (*used + ALIGNED(sizeof(struct ip_set_list)) > len) goto not_enough_mem; - *used += sizeof(struct ip_set_list); + *used += ALIGNED(sizeof(struct ip_set_list)); read_lock_bh(&set->lock); /* Get and ensure set specific header size */ - set_list->header_size = set->type->header_size; + set_list->header_size = ALIGNED(set->type->header_size); if (*used + set_list->header_size > len) goto unlock_set; /* Fill in the header */ set_list->index = index; - set_list->binding = set->binding; + set_list->binding = IP_SET_INVALID_ID; set_list->ref = atomic_read(&set->ref); /* Fill in set spefific header data */ @@ -1170,27 +713,18 @@ static int ip_set_list_set(ip_set_id_t index, *used += set_list->header_size; /* Get and ensure set specific members size */ - set_list->members_size = set->type->list_members_size(set); + set_list->members_size = set->type->list_members_size(set, DONT_ALIGN); if (*used + set_list->members_size > len) goto unlock_set; /* Fill in set spefific members data */ - set->type->list_members(set, data + *used); + set->type->list_members(set, data + *used, DONT_ALIGN); *used += set_list->members_size; read_unlock_bh(&set->lock); /* Bindings */ - - /* Get and ensure set specific bindings size */ set_list->bindings_size = 0; - FOREACH_HASH_DO(__set_hash_bindings_size_list, - set->id, &set_list->bindings_size); - if (*used + set_list->bindings_size > len) - goto not_enough_mem; - /* Fill in set spefific bindings data */ - FOREACH_HASH_DO(__set_hash_bindings, set->id, data, used); - return 0; unlock_set: @@ -1203,10 +737,28 @@ static int ip_set_list_set(ip_set_id_t index, /* * Save sets */ -static int ip_set_save_set(ip_set_id_t index, - void *data, - int *used, - int len) +static inline int +ip_set_save_marker(void *data, int *used, int len) +{ + struct ip_set_save *set_save; + + DP("used %u, len %u", *used, len); + /* Get and ensure header size */ + if (*used + ALIGNED(sizeof(struct ip_set_save)) > len) + return -ENOMEM; + + /* Marker: just for backward compatibility */ + set_save = data + *used; + set_save->index = IP_SET_INVALID_ID; + set_save->header_size = 0; + set_save->members_size = 0; + *used += ALIGNED(sizeof(struct ip_set_save)); + + return 0; +} + +static int +ip_set_save_set(ip_set_id_t index, void *data, int *used, int len) { struct ip_set *set; struct ip_set_save *set_save; @@ -1215,9 +767,9 @@ static int ip_set_save_set(ip_set_id_t index, set_save = data + *used; /* Get and ensure header size */ - if (*used + sizeof(struct ip_set_save) > len) + if (*used + ALIGNED(sizeof(struct ip_set_save)) > len) goto not_enough_mem; - *used += sizeof(struct ip_set_save); + *used += ALIGNED(sizeof(struct ip_set_save)); set = ip_set_list[index]; DP("set: %s, used: %d(%d) %p %p", set->name, *used, len, @@ -1225,13 +777,13 @@ static int ip_set_save_set(ip_set_id_t index, read_lock_bh(&set->lock); /* Get and ensure set specific header size */ - set_save->header_size = set->type->header_size; + set_save->header_size = ALIGNED(set->type->header_size); if (*used + set_save->header_size > len) goto unlock_set; /* Fill in the header */ set_save->index = index; - set_save->binding = set->binding; + set_save->binding = IP_SET_INVALID_ID; /* Fill in set spefific header data */ set->type->list_header(set, data + *used); @@ -1240,12 +792,12 @@ static int ip_set_save_set(ip_set_id_t index, DP("set header filled: %s, used: %d(%lu) %p %p", set->name, *used, (unsigned long)set_save->header_size, data, data + *used); /* Get and ensure set specific members size */ - set_save->members_size = set->type->list_members_size(set); + set_save->members_size = set->type->list_members_size(set, DONT_ALIGN); if (*used + set_save->members_size > len) goto unlock_set; /* Fill in set spefific members data */ - set->type->list_members(set, data + *used); + set->type->list_members(set, data + *used, DONT_ALIGN); *used += set_save->members_size; read_unlock_bh(&set->lock); DP("set members filled: %s, used: %d(%lu) %p %p", set->name, *used, @@ -1259,69 +811,15 @@ static int ip_set_save_set(ip_set_id_t index, return -EAGAIN; } -static inline void -__set_hash_save_bindings(struct ip_set_hash *set_hash, - ip_set_id_t id, - void *data, - int *used, - int len, - int *res) -{ - if (*res == 0 - && (id == IP_SET_INVALID_ID || set_hash->id == id)) { - struct ip_set_hash_save *hash_save = data + *used; - /* Ensure bindings size */ - if (*used + sizeof(struct ip_set_hash_save) > len) { - *res = -ENOMEM; - return; - } - hash_save->id = set_hash->id; - hash_save->ip = set_hash->ip; - hash_save->binding = set_hash->binding; - *used += sizeof(struct ip_set_hash_save); - } -} - -static int ip_set_save_bindings(ip_set_id_t index, - void *data, - int *used, - int len) -{ - int res = 0; - struct ip_set_save *set_save; - - DP("used %u, len %u", *used, len); - /* Get and ensure header size */ - if (*used + sizeof(struct ip_set_save) > len) - return -ENOMEM; - - /* Marker */ - set_save = data + *used; - set_save->index = IP_SET_INVALID_ID; - set_save->header_size = 0; - set_save->members_size = 0; - *used += sizeof(struct ip_set_save); - - DP("marker added used %u, len %u", *used, len); - /* Fill in bindings data */ - if (index != IP_SET_INVALID_ID) - /* Sets are identified by id in hash */ - index = ip_set_list[index]->id; - FOREACH_HASH_DO(__set_hash_save_bindings, index, data, used, len, &res); - - return res; -} - /* * Restore sets */ -static int ip_set_restore(void *data, - int len) +static int +ip_set_restore(void *data, int len) { int res = 0; int line = 0, used = 0, members_size; struct ip_set *set; - struct ip_set_hash_save *hash_save; struct ip_set_restore *set_restore; ip_set_id_t index; @@ -1329,12 +827,12 @@ static int ip_set_restore(void *data, while (1) { line++; - DP("%d %zu %d", used, sizeof(struct ip_set_restore), len); + DP("%d %zu %d", used, ALIGNED(sizeof(struct ip_set_restore)), len); /* Get and ensure header size */ - if (used + sizeof(struct ip_set_restore) > len) + if (used + ALIGNED(sizeof(struct ip_set_restore)) > len) return line; set_restore = data + used; - used += sizeof(struct ip_set_restore); + used += ALIGNED(sizeof(struct ip_set_restore)); /* Ensure data size */ if (used @@ -1345,7 +843,7 @@ static int ip_set_restore(void *data, /* Check marker */ if (set_restore->index == IP_SET_INVALID_ID) { line--; - goto bindings; + goto finish; } /* Try to create the set */ @@ -1358,7 +856,7 @@ static int ip_set_restore(void *data, if (res != 0) return line; - used += set_restore->header_size; + used += ALIGNED(set_restore->header_size); index = ip_set_find_byindex(set_restore->index); DP("index %u, restore_index %u", index, set_restore->index); @@ -1370,16 +868,16 @@ static int ip_set_restore(void *data, DP("members_size %lu reqsize %lu", (unsigned long)set_restore->members_size, (unsigned long)set->type->reqsize); - while (members_size + set->type->reqsize <= + while (members_size + ALIGNED(set->type->reqsize) <= set_restore->members_size) { line++; DP("members: %d, line %d", members_size, line); - res = __ip_set_addip(index, + res = ip_set_addip(set, data + used + members_size, set->type->reqsize); if (!(res == 0 || res == -EEXIST)) return line; - members_size += set->type->reqsize; + members_size += ALIGNED(set->type->reqsize); } DP("members_size %lu %d", @@ -1389,45 +887,7 @@ static int ip_set_restore(void *data, used += set_restore->members_size; } - bindings: - /* Loop to restore bindings */ - while (used < len) { - line++; - - DP("restore binding, line %u", line); - /* Get and ensure size */ - if (used + sizeof(struct ip_set_hash_save) > len) - return line; - hash_save = data + used; - used += sizeof(struct ip_set_hash_save); - - /* hash_save->id is used to store the index */ - index = ip_set_find_byindex(hash_save->id); - DP("restore binding index %u, id %u, %u -> %u", - index, hash_save->id, hash_save->ip, hash_save->binding); - if (index != hash_save->id) - return line; - if (ip_set_find_byindex(hash_save->binding) == IP_SET_INVALID_ID) { - DP("corrupt binding set index %u", hash_save->binding); - return line; - } - set = ip_set_list[hash_save->id]; - /* Null valued IP means default binding */ - if (hash_save->ip) - res = ip_set_hash_add(set->id, - hash_save->ip, - hash_save->binding); - else { - IP_SET_ASSERT(set->binding == IP_SET_INVALID_ID); - write_lock_bh(&ip_set_lock); - set->binding = hash_save->binding; - __ip_set_get(set->binding); - write_unlock_bh(&ip_set_lock); - DP("default binding: %u", set->binding); - } - if (res != 0) - return line; - } + finish: if (used != len) return line; @@ -1439,17 +899,17 @@ ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len) { void *data; int res = 0; /* Assume OK */ + size_t offset; unsigned *op; struct ip_set_req_adt *req_adt; ip_set_id_t index = IP_SET_INVALID_ID; - int (*adtfn)(ip_set_id_t index, + int (*adtfn)(struct ip_set *set, const void *data, u_int32_t size); struct fn_table { - int (*fn)(ip_set_id_t index, + int (*fn)(struct ip_set *set, const void *data, u_int32_t size); } adtfn_table[] = - { { ip_set_addip }, { ip_set_delip }, { ip_set_testip}, - { ip_set_bindip}, { ip_set_unbindip }, { ip_set_testbind }, + { { ip_set_addip }, { ip_set_delip }, { ip_set_testip}, }; DP("optval=%d, user=%p, len=%d", optval, user, len); @@ -1482,19 +942,22 @@ ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len) if (*op < IP_SET_OP_VERSION) { /* Check the version at the beginning of operations */ struct ip_set_req_version *req_version = data; - if (req_version->version != IP_SET_PROTOCOL_VERSION) { + if (!(req_version->version == IP_SET_PROTOCOL_UNALIGNED + || req_version->version == IP_SET_PROTOCOL_VERSION)) { res = -EPROTO; goto done; } + protocol_version = req_version->version; } switch (*op) { case IP_SET_OP_CREATE:{ struct ip_set_req_create *req_create = data; + offset = ALIGNED(sizeof(struct ip_set_req_create)); - if (len < sizeof(struct ip_set_req_create)) { + if (len < offset) { ip_set_printk("short CREATE data (want >=%zu, got %u)", - sizeof(struct ip_set_req_create), len); + offset, len); res = -EINVAL; goto done; } @@ -1503,8 +966,8 @@ ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len) res = ip_set_create(req_create->name, req_create->typename, IP_SET_INVALID_ID, - data + sizeof(struct ip_set_req_create), - len - sizeof(struct ip_set_req_create)); + data + offset, + len - offset); goto done; } case IP_SET_OP_DESTROY:{ @@ -1516,7 +979,7 @@ ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len) res = -EINVAL; goto done; } - if (SETNAME_EQ(req_destroy->name, IPSET_TOKEN_ALL)) { + if (STREQ(req_destroy->name, IPSET_TOKEN_ALL)) { /* Destroy all sets */ index = IP_SET_INVALID_ID; } else { @@ -1541,7 +1004,7 @@ ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len) res = -EINVAL; goto done; } - if (SETNAME_EQ(req_flush->name, IPSET_TOKEN_ALL)) { + if (STREQ(req_flush->name, IPSET_TOKEN_ALL)) { /* Flush all sets */ index = IP_SET_INVALID_ID; } else { @@ -1609,30 +1072,40 @@ ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len) } /* There we may have add/del/test/bind/unbind/test_bind operations */ - if (*op < IP_SET_OP_ADD_IP || *op > IP_SET_OP_TEST_BIND_SET) { + if (*op < IP_SET_OP_ADD_IP || *op > IP_SET_OP_TEST_IP) { res = -EBADMSG; goto done; } adtfn = adtfn_table[*op - IP_SET_OP_ADD_IP].fn; - if (len < sizeof(struct ip_set_req_adt)) { + if (len < ALIGNED(sizeof(struct ip_set_req_adt))) { ip_set_printk("short data in adt request (want >=%zu, got %u)", - sizeof(struct ip_set_req_adt), len); + ALIGNED(sizeof(struct ip_set_req_adt)), len); res = -EINVAL; goto done; } req_adt = data; - /* -U :all: :all:|:default: uses IP_SET_INVALID_ID */ - if (!(*op == IP_SET_OP_UNBIND_SET - && req_adt->index == IP_SET_INVALID_ID)) { - index = ip_set_find_byindex(req_adt->index); - if (index == IP_SET_INVALID_ID) { - res = -ENOENT; + index = ip_set_find_byindex(req_adt->index); + if (index == IP_SET_INVALID_ID) { + res = -ENOENT; + goto done; + } + do { + struct ip_set *set = ip_set_list[index]; + size_t offset = ALIGNED(sizeof(struct ip_set_req_adt)); + + IP_SET_ASSERT(set); + + if (len - offset != set->type->reqsize) { + ip_set_printk("data length wrong (want %lu, have %zu)", + (long unsigned)set->type->reqsize, + len - offset); + res = -EINVAL; goto done; } - } - res = adtfn(index, data, len); + res = adtfn(set, data + offset, len - offset); + } while (0); done: up(&ip_set_app_mutex); @@ -1682,10 +1155,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len) if (*op < IP_SET_OP_VERSION) { /* Check the version at the beginning of operations */ struct ip_set_req_version *req_version = data; - if (req_version->version != IP_SET_PROTOCOL_VERSION) { + if (!(req_version->version == IP_SET_PROTOCOL_UNALIGNED + || req_version->version == IP_SET_PROTOCOL_VERSION)) { res = -EPROTO; goto done; } + protocol_version = req_version->version; } switch (*op) { @@ -1768,7 +1243,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len) goto done; } - if (SETNAME_EQ(req_max_sets->set.name, IPSET_TOKEN_ALL)) { + if (STREQ(req_max_sets->set.name, IPSET_TOKEN_ALL)) { req_max_sets->set.index = IP_SET_INVALID_ID; } else { req_max_sets->set.name[IP_SET_MAXNAMELEN - 1] = '\0'; @@ -1795,20 +1270,21 @@ ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len) ip_set_id_t i; int used; - if (*len < sizeof(struct ip_set_req_setnames)) { + if (*len < ALIGNED(sizeof(struct ip_set_req_setnames))) { ip_set_printk("short LIST_SIZE (want >=%zu, got %d)", - sizeof(struct ip_set_req_setnames), *len); + ALIGNED(sizeof(struct ip_set_req_setnames)), + *len); res = -EINVAL; goto done; } req_setnames->size = 0; - used = sizeof(struct ip_set_req_setnames); + used = ALIGNED(sizeof(struct ip_set_req_setnames)); for (i = 0; i < ip_set_max; i++) { if (ip_set_list[i] == NULL) continue; name_list = data + used; - used += sizeof(struct ip_set_name_list); + used += ALIGNED(sizeof(struct ip_set_name_list)); if (used > copylen) { res = -EAGAIN; goto done; @@ -1830,27 +1306,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len) || req_setnames->index == i)) continue; /* Update size */ - switch (*op) { - case IP_SET_OP_LIST_SIZE: { - req_setnames->size += sizeof(struct ip_set_list) - + set->type->header_size - + set->type->list_members_size(set); - /* Sets are identified by id in the hash */ - FOREACH_HASH_DO(__set_hash_bindings_size_list, - set->id, &req_setnames->size); - break; - } - case IP_SET_OP_SAVE_SIZE: { - req_setnames->size += sizeof(struct ip_set_save) - + set->type->header_size - + set->type->list_members_size(set); - FOREACH_HASH_DO(__set_hash_bindings_size_save, - set->id, &req_setnames->size); - break; - } - default: - break; - } + req_setnames->size += + (*op == IP_SET_OP_LIST_SIZE ? + ALIGNED(sizeof(struct ip_set_list)) : + ALIGNED(sizeof(struct ip_set_save))) + + ALIGNED(set->type->header_size) + + set->type->list_members_size(set, DONT_ALIGN); } if (copylen != used) { res = -EAGAIN; @@ -1933,7 +1394,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len) res = ip_set_save_set(index, data, &used, *len); } if (res == 0) - res = ip_set_save_bindings(index, data, &used, *len); + res = ip_set_save_marker(data, &used, *len); if (res != 0) goto done; @@ -1945,17 +1406,16 @@ ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len) } case IP_SET_OP_RESTORE: { struct ip_set_req_setnames *req_restore = data; + size_t offset = ALIGNED(sizeof(struct ip_set_req_setnames)); int line; - if (*len < sizeof(struct ip_set_req_setnames) - || *len != req_restore->size) { + if (*len < offset || *len != req_restore->size) { ip_set_printk("invalid RESTORE (want =%lu, got %d)", (long unsigned)req_restore->size, *len); res = -EINVAL; goto done; } - line = ip_set_restore(data + sizeof(struct ip_set_req_setnames), - req_restore->size - sizeof(struct ip_set_req_setnames)); + line = ip_set_restore(data + offset, req_restore->size - offset); DP("ip_set_restore: %d", line); if (line != 0) { res = -EAGAIN; @@ -2001,40 +1461,32 @@ static struct nf_sockopt_ops so_set = { #endif }; -static int max_sets, hash_size; +static int max_sets; module_param(max_sets, int, 0600); MODULE_PARM_DESC(max_sets, "maximal number of sets"); -module_param(hash_size, int, 0600); -MODULE_PARM_DESC(hash_size, "hash size for bindings"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); MODULE_DESCRIPTION("module implementing core IP set support"); -static int __init ip_set_init(void) +static int __init +ip_set_init(void) { int res; - ip_set_id_t i; - get_random_bytes(&ip_set_hash_random, 4); + init_MUTEX(&ip_set_app_mutex); + if (max_sets) ip_set_max = max_sets; + if (ip_set_max >= IP_SET_INVALID_ID) + ip_set_max = IP_SET_INVALID_ID - 1; + ip_set_list = vmalloc(sizeof(struct ip_set *) * ip_set_max); if (!ip_set_list) { printk(KERN_ERR "Unable to create ip_set_list\n"); return -ENOMEM; } memset(ip_set_list, 0, sizeof(struct ip_set *) * ip_set_max); - if (hash_size) - ip_set_bindings_hash_size = hash_size; - ip_set_hash = vmalloc(sizeof(struct list_head) * ip_set_bindings_hash_size); - if (!ip_set_hash) { - printk(KERN_ERR "Unable to create ip_set_hash\n"); - vfree(ip_set_list); - return -ENOMEM; - } - for (i = 0; i < ip_set_bindings_hash_size; i++) - INIT_LIST_HEAD(&ip_set_hash[i]); INIT_LIST_HEAD(&set_type_list); @@ -2042,19 +1494,19 @@ static int __init ip_set_init(void) if (res != 0) { ip_set_printk("SO_SET registry failed: %d", res); vfree(ip_set_list); - vfree(ip_set_hash); return res; } - + + printk("ip_set version %u loaded\n", IP_SET_PROTOCOL_VERSION); return 0; } -static void __exit ip_set_fini(void) +static void __exit +ip_set_fini(void) { /* There can't be any existing set or binding */ nf_unregister_sockopt(&so_set); vfree(ip_set_list); - vfree(ip_set_hash); DP("these are the famous last words"); } diff --git a/kernel/ip_set_iphash.c b/kernel/ip_set_iphash.c index aac3eec..1accbe3 100644 --- a/kernel/ip_set_iphash.c +++ b/kernel/ip_set_iphash.c @@ -25,22 +25,21 @@ static int limit = MAX_RANGE; static inline __u32 -iphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +iphash_id(struct ip_set *set, ip_set_ip_t ip) { struct ip_set_iphash *map = set->data; __u32 id; u_int16_t i; ip_set_ip_t *elem; - *hash_ip = ip & map->netmask; - DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u", - set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask)); - + + ip &= map->netmask; + DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(ip)); for (i = 0; i < map->probes; i++) { - id = jhash_ip(map, i, *hash_ip) % map->hashsize; + id = jhash_ip(map, i, ip) % map->hashsize; DP("hash key: %u", id); elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); - if (*elem == *hash_ip) + if (*elem == ip) return id; /* No shortcut - there can be deleted entries. */ } @@ -48,9 +47,9 @@ iphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) } static inline int -iphash_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +iphash_test(struct ip_set *set, ip_set_ip_t ip) { - return (ip && iphash_id(set, hash_ip, ip) != UINT_MAX); + return (ip && iphash_id(set, ip) != UINT_MAX); } #define KADT_CONDITION @@ -84,16 +83,15 @@ __iphash_add(struct ip_set_iphash *map, ip_set_ip_t *ip) } static inline int -iphash_add(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +iphash_add(struct ip_set *set, ip_set_ip_t ip) { struct ip_set_iphash *map = set->data; if (!ip || map->elements >= limit) return -ERANGE; - *hash_ip = ip & map->netmask; - - return __iphash_add(map, hash_ip); + ip &= map->netmask; + return __iphash_add(map, &ip); } UADT(iphash, add) @@ -108,7 +106,7 @@ __iphash_retry(struct ip_set_iphash *tmp, struct ip_set_iphash *map) HASH_RETRY(iphash, ip_set_ip_t) static inline int -iphash_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +iphash_del(struct ip_set *set, ip_set_ip_t ip) { struct ip_set_iphash *map = set->data; ip_set_ip_t id, *elem; @@ -116,7 +114,7 @@ iphash_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) if (!ip) return -ERANGE; - id = iphash_id(set, hash_ip, ip); + id = iphash_id(set, ip); if (id == UINT_MAX) return -EEXIST; diff --git a/kernel/ip_set_ipmap.c b/kernel/ip_set_ipmap.c index 442f0d3..be3c538 100644 --- a/kernel/ip_set_ipmap.c +++ b/kernel/ip_set_ipmap.c @@ -22,21 +22,19 @@ static inline ip_set_ip_t ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip) { - return (ip - map->first_ip)/map->hosts; + return ((ip & map->netmask) - map->first_ip)/map->hosts; } static inline int -ipmap_test(const struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +ipmap_test(const struct ip_set *set, ip_set_ip_t ip) { const struct ip_set_ipmap *map = set->data; if (ip < map->first_ip || ip > map->last_ip) return -ERANGE; - *hash_ip = ip & map->netmask; - DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u", - set->name, HIPQUAD(ip), HIPQUAD(*hash_ip)); - return !!test_bit(ip_to_id(map, *hash_ip), map->members); + DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(ip)); + return !!test_bit(ip_to_id(map, ip), map->members); } #define KADT_CONDITION @@ -45,16 +43,15 @@ UADT(ipmap, test) KADT(ipmap, test, ipaddr) static inline int -ipmap_add(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +ipmap_add(struct ip_set *set, ip_set_ip_t ip) { struct ip_set_ipmap *map = set->data; if (ip < map->first_ip || ip > map->last_ip) return -ERANGE; - *hash_ip = ip & map->netmask; - DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip)); - if (test_and_set_bit(ip_to_id(map, *hash_ip), map->members)) + DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(ip)); + if (test_and_set_bit(ip_to_id(map, ip), map->members)) return -EEXIST; return 0; @@ -64,16 +61,15 @@ UADT(ipmap, add) KADT(ipmap, add, ipaddr) static inline int -ipmap_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +ipmap_del(struct ip_set *set, ip_set_ip_t ip) { struct ip_set_ipmap *map = set->data; if (ip < map->first_ip || ip > map->last_ip) return -ERANGE; - *hash_ip = ip & map->netmask; - DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip)); - if (!test_and_clear_bit(ip_to_id(map, *hash_ip), map->members)) + DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(ip)); + if (!test_and_clear_bit(ip_to_id(map, ip), map->members)) return -EEXIST; return 0; @@ -130,8 +126,28 @@ __ipmap_list_header(const struct ip_set_ipmap *map, } BITMAP_LIST_HEADER(ipmap) -BITMAP_LIST_MEMBERS_SIZE(ipmap) -BITMAP_LIST_MEMBERS(ipmap) +BITMAP_LIST_MEMBERS_SIZE(ipmap, ip_set_ip_t, map->sizeid, + test_bit(i, map->members)) + +static void +ipmap_list_members(const struct ip_set *set, void *data, char dont_align) +{ + const struct ip_set_ipmap *map = set->data; + uint32_t i, n = 0; + ip_set_ip_t *d; + + if (dont_align) { + memcpy(data, map->members, map->size); + return; + } + + for (i = 0; i < map->sizeid; i++) + if (test_bit(i, map->members)) { + d = data + n * IPSET_ALIGN(sizeof(ip_set_ip_t)); + *d = map->first_ip + i * map->hosts; + n++; + } +} IP_SET_TYPE(ipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE) diff --git a/kernel/ip_set_ipporthash.c b/kernel/ip_set_ipporthash.c index c41c0a8..36e68b0 100644 --- a/kernel/ip_set_ipporthash.c +++ b/kernel/ip_set_ipporthash.c @@ -28,26 +28,23 @@ static int limit = MAX_RANGE; static inline __u32 -ipporthash_id(struct ip_set *set, ip_set_ip_t *hash_ip, - ip_set_ip_t ip, ip_set_ip_t port) +ipporthash_id(struct ip_set *set, 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 = pack_ip_port(map, ip, port); + 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)); - if (!*hash_ip) + if (!ip) return UINT_MAX; for (i = 0; i < map->probes; i++) { - id = jhash_ip(map, i, *hash_ip) % map->hashsize; + id = jhash_ip(map, i, ip) % map->hashsize; DP("hash key: %u", id); elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); - if (*elem == *hash_ip) + if (*elem == ip) return id; /* No shortcut - there can be deleted entries. */ } @@ -55,24 +52,23 @@ ipporthash_id(struct ip_set *set, ip_set_ip_t *hash_ip, } static inline int -ipporthash_test(struct ip_set *set, ip_set_ip_t *hash_ip, - ip_set_ip_t ip, ip_set_ip_t port) +ipporthash_test(struct ip_set *set, 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 (ipporthash_id(set, hash_ip, ip, port) != UINT_MAX); + return (ipporthash_id(set, ip, port) != UINT_MAX); } #define KADT_CONDITION \ ip_set_ip_t port; \ \ - if (flags[index+1] == 0) \ + if (flags[1] == 0) \ return 0; \ \ - port = get_port(skb, flags[index+1]); \ + port = get_port(skb, flags++); \ \ if (port == INVALID_PORT) \ return 0; @@ -106,8 +102,7 @@ __ipporthash_add(struct ip_set_ipporthash *map, ip_set_ip_t *ip) } static inline int -ipporthash_add(struct ip_set *set, ip_set_ip_t *hash_ip, - ip_set_ip_t ip, ip_set_ip_t port) +ipporthash_add(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port) { struct ip_set_ipporthash *map = set->data; if (map->elements > limit) @@ -115,12 +110,12 @@ ipporthash_add(struct ip_set *set, ip_set_ip_t *hash_ip, if (ip < map->first_ip || ip > map->last_ip) return -ERANGE; - *hash_ip = pack_ip_port(map, ip, port); + ip = pack_ip_port(map, ip, port); - if (!*hash_ip) + if (!ip) return -ERANGE; - return __ipporthash_add(map, hash_ip); + return __ipporthash_add(map, &ip); } UADT(ipporthash, add, req->port) @@ -137,8 +132,7 @@ __ipporthash_retry(struct ip_set_ipporthash *tmp, HASH_RETRY(ipporthash, ip_set_ip_t) static inline int -ipporthash_del(struct ip_set *set, ip_set_ip_t *hash_ip, - ip_set_ip_t ip, ip_set_ip_t port) +ipporthash_del(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port) { struct ip_set_ipporthash *map = set->data; ip_set_ip_t id; @@ -147,7 +141,7 @@ ipporthash_del(struct ip_set *set, ip_set_ip_t *hash_ip, if (ip < map->first_ip || ip > map->last_ip) return -ERANGE; - id = ipporthash_id(set, hash_ip, ip, port); + id = ipporthash_id(set, ip, port); if (id == UINT_MAX) return -EEXIST; diff --git a/kernel/ip_set_ipportiphash.c b/kernel/ip_set_ipportiphash.c index 166bec4..5fe00f1 100644 --- a/kernel/ip_set_ipportiphash.c +++ b/kernel/ip_set_ipportiphash.c @@ -31,7 +31,7 @@ static int limit = MAX_RANGE; jhash_2words(ipport, ip1, *(map->initval + i)) static inline __u32 -ipportiphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, +ipportiphash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) { struct ip_set_ipportiphash *map = set->data; @@ -39,17 +39,15 @@ ipportiphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, 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)); - if (!(*hash_ip || ip1)) + ip = pack_ip_port(map, ip, port); + if (!(ip || ip1)) return UINT_MAX; for (i = 0; i < map->probes; i++) { - id = jhash_ip2(map, i, *hash_ip, ip1) % map->hashsize; + id = jhash_ip2(map, i, 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) + if (elem->ip == ip && elem->ip1 == ip1) return id; /* No shortcut - there can be deleted entries. */ } @@ -57,7 +55,7 @@ ipportiphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, } static inline int -ipportiphash_test(struct ip_set *set, ip_set_ip_t *hash_ip, +ipportiphash_test(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) { struct ip_set_ipportiphash *map = set->data; @@ -65,17 +63,17 @@ ipportiphash_test(struct ip_set *set, ip_set_ip_t *hash_ip, if (ip < map->first_ip || ip > map->last_ip) return -ERANGE; - return (ipportiphash_id(set, hash_ip, ip, port, ip1) != UINT_MAX); + return (ipportiphash_id(set, ip, port, ip1) != UINT_MAX); } #define KADT_CONDITION \ ip_set_ip_t port, ip1; \ \ - if (flags[index+2] == 0) \ + if (flags[2] == 0) \ return 0; \ \ - port = get_port(skb, flags[index+1]); \ - ip1 = ipaddr(skb, flags[index+2]); \ + port = get_port(skb, flags++); \ + ip1 = ipaddr(skb, flags++); \ \ if (port == INVALID_PORT) \ return 0; @@ -85,23 +83,23 @@ 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) + ip_set_ip_t ip, ip_set_ip_t ip1) { __u32 probe; u_int16_t i; struct ipportip *elem, *slot = NULL; for (i = 0; i < map->probes; i++) { - probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize; + probe = jhash_ip2(map, i, ip, ip1) % map->hashsize; elem = HARRAY_ELEM(map->members, struct ipportip *, probe); - if (elem->ip == hash_ip && elem->ip1 == ip1) + if (elem->ip == ip && elem->ip1 == ip1) return -EEXIST; if (!(slot || elem->ip || elem->ip1)) slot = elem; /* There can be deleted entries, must check all slots */ } if (slot) { - slot->ip = hash_ip; + slot->ip = ip; slot->ip1 = ip1; map->elements++; return 0; @@ -118,7 +116,7 @@ __ipportiphash_add(struct ip_set_ipportiphash *map, } static inline int -ipportiphash_add(struct ip_set *set, ip_set_ip_t *hash_ip, +ipportiphash_add(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) { struct ip_set_ipportiphash *map = set->data; @@ -128,11 +126,11 @@ ipportiphash_add(struct ip_set *set, ip_set_ip_t *hash_ip, if (ip < map->first_ip || ip > map->last_ip) return -ERANGE; - *hash_ip = pack_ip_port(map, ip, port); - if (!(*hash_ip || ip1)) + ip = pack_ip_port(map, ip, port); + if (!(ip || ip1)) return -ERANGE; - return __ipportip_add(map, *hash_ip, ip1); + return __ipportip_add(map, ip, ip1); } UADT(ipportiphash, add, req->port, req->ip1) @@ -149,7 +147,7 @@ __ipportiphash_retry(struct ip_set_ipportiphash *tmp, HASH_RETRY2(ipportiphash, struct ipportip) static inline int -ipportiphash_del(struct ip_set *set, ip_set_ip_t *hash_ip, +ipportiphash_del(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) { struct ip_set_ipportiphash *map = set->data; @@ -159,7 +157,7 @@ ipportiphash_del(struct ip_set *set, ip_set_ip_t *hash_ip, if (ip < map->first_ip || ip > map->last_ip) return -ERANGE; - id = ipportiphash_id(set, hash_ip, ip, port, ip1); + id = ipportiphash_id(set, ip, port, ip1); if (id == UINT_MAX) return -EEXIST; diff --git a/kernel/ip_set_ipportnethash.c b/kernel/ip_set_ipportnethash.c index 45e53ed..9179184 100644 --- a/kernel/ip_set_ipportnethash.c +++ b/kernel/ip_set_ipportnethash.c @@ -31,7 +31,7 @@ static int limit = MAX_RANGE; jhash_2words(ipport, ip1, *(map->initval + i)) static inline __u32 -ipportnethash_id_cidr(struct ip_set *set, ip_set_ip_t *hash_ip, +ipportnethash_id_cidr(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1, uint8_t cidr) { @@ -40,18 +40,16 @@ ipportnethash_id_cidr(struct ip_set *set, ip_set_ip_t *hash_ip, 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)); + ip = pack_ip_port(map, ip, port); ip1 = pack_ip_cidr(ip1, cidr); - if (!(*hash_ip || ip1)) + if (!(ip || ip1)) return UINT_MAX; for (i = 0; i < map->probes; i++) { - id = jhash_ip2(map, i, *hash_ip, ip1) % map->hashsize; + id = jhash_ip2(map, i, 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) + if (elem->ip == ip && elem->ip1 == ip1) return id; /* No shortcut - there can be deleted entries. */ } @@ -59,7 +57,7 @@ ipportnethash_id_cidr(struct ip_set *set, ip_set_ip_t *hash_ip, } static inline __u32 -ipportnethash_id(struct ip_set *set, ip_set_ip_t *hash_ip, +ipportnethash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) { struct ip_set_ipportnethash *map = set->data; @@ -67,8 +65,7 @@ ipportnethash_id(struct ip_set *set, ip_set_ip_t *hash_ip, int i; for (i = 0; i < 30 && map->cidr[i]; i++) { - id = ipportnethash_id_cidr(set, hash_ip, ip, port, ip1, - map->cidr[i]); + id = ipportnethash_id_cidr(set, ip, port, ip1, map->cidr[i]); if (id != UINT_MAX) break; } @@ -76,7 +73,7 @@ ipportnethash_id(struct ip_set *set, ip_set_ip_t *hash_ip, } static inline int -ipportnethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip, +ipportnethash_test_cidr(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1, uint8_t cidr) { @@ -85,12 +82,11 @@ ipportnethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip, if (ip < map->first_ip || ip > map->last_ip) return -ERANGE; - return (ipportnethash_id_cidr(set, hash_ip, ip, port, ip1, - cidr) != UINT_MAX); + return (ipportnethash_id_cidr(set, ip, port, ip1, cidr) != UINT_MAX); } static inline int -ipportnethash_test(struct ip_set *set, ip_set_ip_t *hash_ip, +ipportnethash_test(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) { struct ip_set_ipportnethash *map = set->data; @@ -98,32 +94,30 @@ ipportnethash_test(struct ip_set *set, ip_set_ip_t *hash_ip, if (ip < map->first_ip || ip > map->last_ip) return -ERANGE; - return (ipportnethash_id(set, hash_ip, ip, port, ip1) != UINT_MAX); + return (ipportnethash_id(set, ip, port, ip1) != UINT_MAX); } static int -ipportnethash_utest(struct ip_set *set, const void *data, u_int32_t size, - ip_set_ip_t *hash_ip) +ipportnethash_utest(struct ip_set *set, const void *data, u_int32_t size) { 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, + ? ipportnethash_test(set, req->ip, req->port, req->ip1) + : ipportnethash_test_cidr(set, req->ip, req->port, req->ip1, req->cidr)); } #define KADT_CONDITION \ ip_set_ip_t port, ip1; \ \ - if (flags[index+2] == 0) \ + if (flags[2] == 0) \ return 0; \ \ - port = get_port(skb, flags[index+1]); \ - ip1 = ipaddr(skb, flags[index+2]); \ + port = get_port(skb, flags++); \ + ip1 = ipaddr(skb, flags++); \ \ if (port == INVALID_PORT) \ return 0; @@ -132,23 +126,23 @@ 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) + ip_set_ip_t ip, ip_set_ip_t ip1) { __u32 probe; u_int16_t i; struct ipportip *elem, *slot = NULL; for (i = 0; i < map->probes; i++) { - probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize; + probe = jhash_ip2(map, i, ip, ip1) % map->hashsize; elem = HARRAY_ELEM(map->members, struct ipportip *, probe); - if (elem->ip == hash_ip && elem->ip1 == ip1) + if (elem->ip == ip && elem->ip1 == ip1) return -EEXIST; if (!(slot || elem->ip || elem->ip1)) slot = elem; /* There can be deleted entries, must check all slots */ } if (slot) { - slot->ip = hash_ip; + slot->ip = ip; slot->ip1 = ip1; map->elements++; return 0; @@ -165,7 +159,7 @@ __ipportnethash_add(struct ip_set_ipportnethash *map, } static inline int -ipportnethash_add(struct ip_set *set, ip_set_ip_t *hash_ip, +ipportnethash_add(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1, uint8_t cidr) { @@ -182,12 +176,12 @@ ipportnethash_add(struct ip_set *set, ip_set_ip_t *hash_ip, if (map->nets[cidr-1] == UINT16_MAX) return -ERANGE; - *hash_ip = pack_ip_port(map, ip, port); + ip = pack_ip_port(map, ip, port); ip1 = pack_ip_cidr(ip1, cidr); - if (!(*hash_ip || ip1)) + if (!(ip || ip1)) return -ERANGE; - ret =__ipportnet_add(map, *hash_ip, ip1); + ret =__ipportnet_add(map, ip, ip1); if (ret == 0) { if (!map->nets[cidr-1]++) add_cidr_size(map->cidr, cidr); @@ -202,11 +196,11 @@ ipportnethash_add(struct ip_set *set, ip_set_ip_t *hash_ip, uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31; \ ip_set_ip_t port, ip1; \ \ - if (flags[index+2] == 0) \ + if (flags[2] == 0) \ return 0; \ \ - port = get_port(skb, flags[index+1]); \ - ip1 = ipaddr(skb, flags[index+2]); \ + port = get_port(skb, flags++); \ + ip1 = ipaddr(skb, flags++); \ \ if (port == INVALID_PORT) \ return 0; @@ -227,7 +221,7 @@ __ipportnethash_retry(struct ip_set_ipportnethash *tmp, HASH_RETRY2(ipportnethash, struct ipportip) static inline int -ipportnethash_del(struct ip_set *set, ip_set_ip_t *hash_ip, +ipportnethash_del(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1, uint8_t cidr) { @@ -242,7 +236,7 @@ ipportnethash_del(struct ip_set *set, ip_set_ip_t *hash_ip, if (cidr <= 0 || cidr >= 32) return -EINVAL; - id = ipportnethash_id_cidr(set, hash_ip, ip, port, ip1, cidr); + id = ipportnethash_id_cidr(set, ip, port, ip1, cidr); if (id == UINT_MAX) return -EEXIST; diff --git a/kernel/ip_set_iptree.c b/kernel/ip_set_iptree.c index cdb3404..77eb180 100644 --- a/kernel/ip_set_iptree.c +++ b/kernel/ip_set_iptree.c @@ -62,7 +62,7 @@ static __KMEM_CACHE_T__ *leaf_cachep; } while (0) static inline int -iptree_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +iptree_test(struct ip_set *set, ip_set_ip_t ip) { struct ip_set_iptree *map = set->data; struct ip_set_iptreeb *btree; @@ -73,8 +73,7 @@ iptree_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) if (!ip) return -ERANGE; - *hash_ip = ip; - ABCD(a, b, c, d, hash_ip); + ABCD(a, b, c, d, &ip); DP("%u %u %u %u timeout %u", a, b, c, d, map->timeout); TESTIP_WALK(map, a, btree); TESTIP_WALK(btree, b, ctree); @@ -106,8 +105,7 @@ KADT(iptree, test, ipaddr) } while (0) static inline int -iptree_add(struct ip_set *set, ip_set_ip_t *hash_ip, - ip_set_ip_t ip, unsigned int timeout) +iptree_add(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout) { struct ip_set_iptree *map = set->data; struct ip_set_iptreeb *btree; @@ -121,8 +119,7 @@ iptree_add(struct ip_set *set, ip_set_ip_t *hash_ip, * but it's probably overkill */ return -ERANGE; - *hash_ip = ip; - ABCD(a, b, c, d, hash_ip); + ABCD(a, b, c, d, &ip); DP("%u %u %u %u timeout %u", a, b, c, d, timeout); ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep); ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep); @@ -153,7 +150,7 @@ KADT(iptree, add, ipaddr, 0) } while (0) static inline int -iptree_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +iptree_del(struct ip_set *set, ip_set_ip_t ip) { struct ip_set_iptree *map = set->data; struct ip_set_iptreeb *btree; @@ -164,8 +161,7 @@ iptree_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) if (!ip) return -ERANGE; - *hash_ip = ip; - ABCD(a, b, c, d, hash_ip); + ABCD(a, b, c, d, &ip); DELIP_WALK(map, a, btree); DELIP_WALK(btree, b, ctree); DELIP_WALK(ctree, c, dtree); @@ -364,7 +360,7 @@ iptree_list_header(const struct ip_set *set, void *data) } static int -iptree_list_members_size(const struct ip_set *set) +iptree_list_members_size(const struct ip_set *set, char dont_align) { const struct ip_set_iptree *map = set->data; struct ip_set_iptreeb *btree; @@ -386,20 +382,21 @@ iptree_list_members_size(const struct ip_set *set) LOOP_WALK_END; DP("members %u", count); - return (count * sizeof(struct ip_set_req_iptree)); + return (count * IPSET_VALIGN(sizeof(struct ip_set_req_iptree), dont_align)); } static void -iptree_list_members(const struct ip_set *set, void *data) +iptree_list_members(const struct ip_set *set, void *data, char dont_align) { const struct ip_set_iptree *map = set->data; struct ip_set_iptreeb *btree; struct ip_set_iptreec *ctree; struct ip_set_iptreed *dtree; unsigned int a,b,c,d; - size_t offset = 0; + size_t offset = 0, datasize; struct ip_set_req_iptree *entry; + datasize = IPSET_VALIGN(sizeof(struct ip_set_req_iptree), dont_align); LOOP_WALK_BEGIN(map, a, btree); LOOP_WALK_BEGIN(btree, b, ctree); LOOP_WALK_BEGIN(ctree, c, dtree); @@ -410,7 +407,7 @@ iptree_list_members(const struct ip_set *set, void *data) entry->ip = ((a << 24) | (b << 16) | (c << 8) | d); entry->timeout = !map->timeout ? 0 : (dtree->expires[d] - jiffies)/HZ; - offset += sizeof(struct ip_set_req_iptree); + offset += datasize; } } LOOP_WALK_END; diff --git a/kernel/ip_set_iptreemap.c b/kernel/ip_set_iptreemap.c index 7c8c517..02f657e 100644 --- a/kernel/ip_set_iptreemap.c +++ b/kernel/ip_set_iptreemap.c @@ -14,6 +14,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/ip.h> +#include <linux/jiffies.h> #include <linux/skbuff.h> #include <linux/slab.h> #include <linux/delay.h> @@ -250,7 +251,7 @@ free_b(struct ip_set_iptreemap_b *map) } static inline int -iptreemap_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +iptreemap_test(struct ip_set *set, ip_set_ip_t ip) { struct ip_set_iptreemap *map = set->data; struct ip_set_iptreemap_b *btree; @@ -258,9 +259,7 @@ iptreemap_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) struct ip_set_iptreemap_d *dtree; unsigned char a, b, c, d; - *hash_ip = ip; - - ABCD(a, b, c, d, hash_ip); + ABCD(a, b, c, d, &ip); TESTIP_WALK(map, a, btree, fullbitmap_b); TESTIP_WALK(btree, b, ctree, fullbitmap_c); @@ -275,7 +274,7 @@ UADT(iptreemap, test) KADT(iptreemap, test, ipaddr) static inline int -__addip_single(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +__addip_single(struct ip_set *set, ip_set_ip_t ip) { struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data; struct ip_set_iptreemap_b *btree; @@ -283,9 +282,7 @@ __addip_single(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) struct ip_set_iptreemap_d *dtree; unsigned char a, b, c, d; - *hash_ip = ip; - - ABCD(a, b, c, d, hash_ip); + ABCD(a, b, c, d, &ip); ADDIP_WALK(map, a, btree, struct ip_set_iptreemap_b, cachep_b, fullbitmap_b); ADDIP_WALK(btree, b, ctree, struct ip_set_iptreemap_c, cachep_c, fullbitmap_c); @@ -300,8 +297,7 @@ __addip_single(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) } static inline int -iptreemap_add(struct ip_set *set, ip_set_ip_t *hash_ip, - ip_set_ip_t start, ip_set_ip_t end) +iptreemap_add(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end) { struct ip_set_iptreemap *map = set->data; struct ip_set_iptreemap_b *btree; @@ -312,9 +308,7 @@ iptreemap_add(struct ip_set *set, ip_set_ip_t *hash_ip, unsigned char a2, b2, c2, d2; if (start == end) - return __addip_single(set, hash_ip, start); - - *hash_ip = start; + return __addip_single(set, start); ABCD(a1, b1, c1, d1, &start); ABCD(a2, b2, c2, d2, &end); @@ -337,8 +331,7 @@ 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 *hash_ip, - ip_set_ip_t ip, gfp_t flags) +__delip_single(struct ip_set *set, ip_set_ip_t ip, gfp_t flags) { struct ip_set_iptreemap *map = set->data; struct ip_set_iptreemap_b *btree; @@ -346,9 +339,7 @@ __delip_single(struct ip_set *set, ip_set_ip_t *hash_ip, struct ip_set_iptreemap_d *dtree; unsigned char a,b,c,d; - *hash_ip = ip; - - ABCD(a, b, c, d, hash_ip); + ABCD(a, b, c, d, &ip); DELIP_WALK(map, a, btree, cachep_b, fullbitmap_b, flags); DELIP_WALK(btree, b, ctree, cachep_c, fullbitmap_c, flags); @@ -363,7 +354,7 @@ __delip_single(struct ip_set *set, ip_set_ip_t *hash_ip, } static inline int -iptreemap_del(struct ip_set *set, ip_set_ip_t *hash_ip, +iptreemap_del(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, gfp_t flags) { struct ip_set_iptreemap *map = set->data; @@ -375,9 +366,7 @@ iptreemap_del(struct ip_set *set, ip_set_ip_t *hash_ip, unsigned char a2, b2, c2, d2; if (start == end) - return __delip_single(set, hash_ip, start, flags); - - *hash_ip = start; + return __delip_single(set, start, flags); ABCD(a1, b1, c1, d1, &start); ABCD(a2, b2, c2, d2, &end); @@ -517,6 +506,7 @@ static void iptreemap_flush(struct ip_set *set) { struct ip_set_iptreemap *map = set->data; + unsigned int gc_interval = map->gc_interval; while (!del_timer(&map->gc)) msleep(IPTREEMAP_DESTROY_SLEEP); @@ -524,6 +514,7 @@ iptreemap_flush(struct ip_set *set) __flush(map); memset(map, 0, sizeof(*map)); + map->gc_interval = gc_interval; init_gc_timer(set); } @@ -538,7 +529,7 @@ iptreemap_list_header(const struct ip_set *set, void *data) } static int -iptreemap_list_members_size(const struct ip_set *set) +iptreemap_list_members_size(const struct ip_set *set, char dont_align) { struct ip_set_iptreemap *map = set->data; struct ip_set_iptreemap_b *btree; @@ -564,31 +555,30 @@ iptreemap_list_members_size(const struct ip_set *set) if (inrange) count++; - return (count * sizeof(struct ip_set_req_iptreemap)); + return (count * IPSET_VALIGN(sizeof(struct ip_set_req_iptreemap), dont_align)); } -static inline u_int32_t +static inline void 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->ip = start; entry->end = end; - - return sizeof(*entry); } static void -iptreemap_list_members(const struct ip_set *set, void *data) +iptreemap_list_members(const struct ip_set *set, void *data, char dont_align) { struct ip_set_iptreemap *map = set->data; struct ip_set_iptreemap_b *btree; struct ip_set_iptreemap_c *ctree; struct ip_set_iptreemap_d *dtree; unsigned int a, b, c, d, inrange = 0; - size_t offset = 0; + size_t offset = 0, datasize; ip_set_ip_t start = 0, end = 0, ip; + datasize = IPSET_VALIGN(sizeof(struct ip_set_req_iptreemap), dont_align); LOOP_WALK_BEGIN(map, a, btree) { LOOP_WALK_BEGIN(btree, b, ctree) { LOOP_WALK_BEGIN(ctree, c, dtree) { @@ -599,12 +589,14 @@ iptreemap_list_members(const struct ip_set *set, void *data) inrange = 1; start = ip; } else if (end < ip - 1) { - offset += add_member(data, offset, start, end); + add_member(data, offset, start, end); + offset += datasize; start = ip; } end = ip; } else if (inrange) { - offset += add_member(data, offset, start, end); + add_member(data, offset, start, end); + offset += datasize; inrange = 0; } } diff --git a/kernel/ip_set_macipmap.c b/kernel/ip_set_macipmap.c index 464106e..89e907b 100644 --- a/kernel/ip_set_macipmap.c +++ b/kernel/ip_set_macipmap.c @@ -22,8 +22,7 @@ #include <linux/netfilter_ipv4/ip_set_macipmap.h> static int -macipmap_utest(struct ip_set *set, const void *data, u_int32_t size, - ip_set_ip_t *hash_ip) +macipmap_utest(struct ip_set *set, const void *data, u_int32_t size) { const struct ip_set_macipmap *map = set->data; const struct ip_set_macip *table = map->members; @@ -32,9 +31,7 @@ macipmap_utest(struct ip_set *set, const void *data, u_int32_t size, if (req->ip < map->first_ip || req->ip > map->last_ip) return -ERANGE; - *hash_ip = req->ip; - DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u", - set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip)); + DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(req->ip)); if (table[req->ip - map->first_ip].match) { return (memcmp(req->ethernet, &table[req->ip - map->first_ip].ethernet, @@ -47,22 +44,18 @@ macipmap_utest(struct ip_set *set, const void *data, u_int32_t size, static int 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) + const u_int32_t *flags) { const struct ip_set_macipmap *map = set->data; const struct ip_set_macip *table = map->members; ip_set_ip_t ip; - ip = ipaddr(skb, flags[index]); + ip = ipaddr(skb, flags); if (ip < map->first_ip || ip > map->last_ip) return 0; - *hash_ip = ip; - DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u", - set->name, HIPQUAD(ip), HIPQUAD(*hash_ip)); + DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(ip)); if (table[ip - map->first_ip].match) { /* Is mac pointer valid? * If so, compare... */ @@ -78,7 +71,7 @@ macipmap_ktest(struct ip_set *set, /* returns 0 on success */ static inline int -macipmap_add(struct ip_set *set, ip_set_ip_t *hash_ip, +macipmap_add(struct ip_set *set, ip_set_ip_t ip, const unsigned char *ethernet) { struct ip_set_macipmap *map = set->data; @@ -89,8 +82,7 @@ macipmap_add(struct ip_set *set, ip_set_ip_t *hash_ip, if (table[ip - map->first_ip].match) return -EEXIST; - *hash_ip = ip; - DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip)); + DP("set: %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip)); memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN); table[ip - map->first_ip].match = IPSET_MACIP_ISSET; return 0; @@ -105,7 +97,7 @@ UADT(macipmap, add, req->ethernet) KADT(macipmap, add, ipaddr, eth_hdr(skb)->h_source) static inline int -macipmap_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +macipmap_del(struct ip_set *set, ip_set_ip_t ip) { struct ip_set_macipmap *map = set->data; struct ip_set_macip *table = map->members; @@ -115,9 +107,8 @@ macipmap_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) if (!table[ip - map->first_ip].match) return -EEXIST; - *hash_ip = ip; table[ip - map->first_ip].match = 0; - DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip)); + DP("set: %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip)); return 0; } @@ -152,8 +143,32 @@ __macipmap_list_header(const struct ip_set_macipmap *map, } BITMAP_LIST_HEADER(macipmap) -BITMAP_LIST_MEMBERS_SIZE(macipmap) -BITMAP_LIST_MEMBERS(macipmap) +BITMAP_LIST_MEMBERS_SIZE(macipmap, struct ip_set_req_macipmap, + (map->last_ip - map->first_ip + 1), + ((const struct ip_set_macip *)map->members)[i].match) + + +static void +macipmap_list_members(const struct ip_set *set, void *data, char dont_align) +{ + const struct ip_set_macipmap *map = set->data; + const struct ip_set_macip *table = map->members; + uint32_t i, n = 0; + struct ip_set_req_macipmap *d; + + if (dont_align) { + memcpy(data, map->members, map->size); + return; + } + + for (i = 0; i < map->last_ip - map->first_ip + 1; i++) + if (table[i].match) { + d = data + n * IPSET_ALIGN(sizeof(struct ip_set_req_macipmap)); + d->ip = map->first_ip + i; + memcpy(d->ethernet, &table[i].ethernet, ETH_ALEN); + n++; + } +} IP_SET_TYPE(macipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE) diff --git a/kernel/ip_set_nethash.c b/kernel/ip_set_nethash.c index d68a015..bf87f5c 100644 --- a/kernel/ip_set_nethash.c +++ b/kernel/ip_set_nethash.c @@ -26,7 +26,6 @@ static int limit = MAX_RANGE; static inline __u32 nethash_id_cidr(const struct ip_set_nethash *map, - ip_set_ip_t *hash_ip, ip_set_ip_t ip, uint8_t cidr) { @@ -34,15 +33,15 @@ nethash_id_cidr(const struct ip_set_nethash *map, u_int16_t i; ip_set_ip_t *elem; - *hash_ip = pack_ip_cidr(ip, cidr); - if (!*hash_ip) + ip = pack_ip_cidr(ip, cidr); + if (!ip) return MAX_RANGE; for (i = 0; i < map->probes; i++) { - id = jhash_ip(map, i, *hash_ip) % map->hashsize; + id = jhash_ip(map, i, ip) % map->hashsize; DP("hash key: %u", id); elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); - if (*elem == *hash_ip) + if (*elem == ip) return id; /* No shortcut - there can be deleted entries. */ } @@ -50,14 +49,14 @@ nethash_id_cidr(const struct ip_set_nethash *map, } static inline __u32 -nethash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +nethash_id(struct ip_set *set, ip_set_ip_t ip) { const struct ip_set_nethash *map = set->data; __u32 id = UINT_MAX; int i; for (i = 0; i < 30 && map->cidr[i]; i++) { - id = nethash_id_cidr(map, hash_ip, ip, map->cidr[i]); + id = nethash_id_cidr(map, ip, map->cidr[i]); if (id != UINT_MAX) break; } @@ -65,30 +64,28 @@ nethash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) } static inline int -nethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip, - ip_set_ip_t ip, uint8_t cidr) +nethash_test_cidr(struct ip_set *set, ip_set_ip_t ip, uint8_t cidr) { const struct ip_set_nethash *map = set->data; - return (nethash_id_cidr(map, hash_ip, ip, cidr) != UINT_MAX); + return (nethash_id_cidr(map, ip, cidr) != UINT_MAX); } static inline int -nethash_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) +nethash_test(struct ip_set *set, ip_set_ip_t ip) { - return (nethash_id(set, hash_ip, ip) != UINT_MAX); + return (nethash_id(set, ip) != UINT_MAX); } static int -nethash_utest(struct ip_set *set, const void *data, u_int32_t size, - ip_set_ip_t *hash_ip) +nethash_utest(struct ip_set *set, const void *data, u_int32_t size) { const struct ip_set_req_nethash *req = data; if (req->cidr <= 0 || req->cidr > 32) return -EINVAL; - return (req->cidr == 32 ? nethash_test(set, hash_ip, req->ip) - : nethash_test_cidr(set, hash_ip, req->ip, req->cidr)); + return (req->cidr == 32 ? nethash_test(set, req->ip) + : nethash_test_cidr(set, req->ip, req->cidr)); } #define KADT_CONDITION @@ -121,8 +118,7 @@ __nethash_add(struct ip_set_nethash *map, ip_set_ip_t *ip) } static inline int -nethash_add(struct ip_set *set, ip_set_ip_t *hash_ip, - ip_set_ip_t ip, uint8_t cidr) +nethash_add(struct ip_set *set, ip_set_ip_t ip, uint8_t cidr) { struct ip_set_nethash *map = set->data; int ret; @@ -132,12 +128,11 @@ nethash_add(struct ip_set *set, ip_set_ip_t *hash_ip, if (cidr <= 0 || cidr >= 32) return -EINVAL; - *hash_ip = pack_ip_cidr(ip, cidr); - DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip)); - if (!*hash_ip) + ip = pack_ip_cidr(ip, cidr); + if (!ip) return -ERANGE; - ret = __nethash_add(map, hash_ip); + ret = __nethash_add(map, &ip); if (ret == 0) { if (!map->nets[cidr-1]++) add_cidr_size(map->cidr, cidr); @@ -165,8 +160,7 @@ __nethash_retry(struct ip_set_nethash *tmp, struct ip_set_nethash *map) HASH_RETRY(nethash, ip_set_ip_t) static inline int -nethash_del(struct ip_set *set, ip_set_ip_t *hash_ip, - ip_set_ip_t ip, uint8_t cidr) +nethash_del(struct ip_set *set, ip_set_ip_t ip, uint8_t cidr) { struct ip_set_nethash *map = set->data; ip_set_ip_t id, *elem; @@ -174,7 +168,7 @@ nethash_del(struct ip_set *set, ip_set_ip_t *hash_ip, if (cidr <= 0 || cidr >= 32) return -EINVAL; - id = nethash_id_cidr(map, hash_ip, ip, cidr); + id = nethash_id_cidr(map, ip, cidr); if (id == UINT_MAX) return -EEXIST; diff --git a/kernel/ip_set_portmap.c b/kernel/ip_set_portmap.c index 8b0ec0a..8bb6e76 100644 --- a/kernel/ip_set_portmap.c +++ b/kernel/ip_set_portmap.c @@ -23,16 +23,14 @@ #include <linux/netfilter_ipv4/ip_set_getport.h> static inline int -portmap_test(const struct ip_set *set, ip_set_ip_t *hash_port, - ip_set_ip_t port) +portmap_test(const struct ip_set *set, ip_set_ip_t port) { const struct ip_set_portmap *map = set->data; 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); + DP("set: %s, port: %u", set->name, port); return !!test_bit(port - map->first_ip, map->members); } @@ -44,7 +42,7 @@ UADT(portmap, test) KADT(portmap, test, get_port) static inline int -portmap_add(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port) +portmap_add(struct ip_set *set, ip_set_ip_t port) { struct ip_set_portmap *map = set->data; @@ -52,9 +50,8 @@ portmap_add(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port) return -ERANGE; if (test_and_set_bit(port - map->first_ip, map->members)) return -EEXIST; - - *hash_port = port; - DP("port %u", port); + + DP("set: %s, port %u", set->name, port); return 0; } @@ -62,7 +59,7 @@ UADT(portmap, add) KADT(portmap, add, get_port) static inline int -portmap_del(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port) +portmap_del(struct ip_set *set, ip_set_ip_t port) { struct ip_set_portmap *map = set->data; @@ -70,9 +67,8 @@ portmap_del(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port) return -ERANGE; if (!test_and_clear_bit(port - map->first_ip, map->members)) return -EEXIST; - - *hash_port = port; - DP("port %u", port); + + DP("set: %s, port %u", set->name, port); return 0; } @@ -102,8 +98,28 @@ __portmap_list_header(const struct ip_set_portmap *map, } BITMAP_LIST_HEADER(portmap) -BITMAP_LIST_MEMBERS_SIZE(portmap) -BITMAP_LIST_MEMBERS(portmap) +BITMAP_LIST_MEMBERS_SIZE(portmap, ip_set_ip_t, (map->last_ip - map->first_ip + 1), + test_bit(i, map->members)) + +static void +portmap_list_members(const struct ip_set *set, void *data, char dont_align) +{ + const struct ip_set_portmap *map = set->data; + uint32_t i, n = 0; + ip_set_ip_t *d; + + if (dont_align) { + memcpy(data, map->members, map->size); + return; + } + + for (i = 0; i < map->last_ip - map->first_ip + 1; i++) + if (test_bit(i, map->members)) { + d = data + n * IPSET_ALIGN(sizeof(ip_set_ip_t)); + *d = map->first_ip + i; + n++; + } +} IP_SET_TYPE(portmap, IPSET_TYPE_PORT | IPSET_DATA_SINGLE) diff --git a/kernel/ip_set_setlist.c b/kernel/ip_set_setlist.c index 2b1c6b6..3cfdae8 100644 --- a/kernel/ip_set_setlist.c +++ b/kernel/ip_set_setlist.c @@ -28,8 +28,7 @@ next_index_eq(const struct ip_set_setlist *map, int i, ip_set_id_t index) } static int -setlist_utest(struct ip_set *set, const void *data, u_int32_t size, - ip_set_ip_t *hash_ip) +setlist_utest(struct ip_set *set, const void *data, u_int32_t size) { const struct ip_set_setlist *map = set->data; const struct ip_set_req_setlist *req = data; @@ -72,10 +71,8 @@ finish: 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) + const struct sk_buff *skb, + const u_int32_t *flags) { struct ip_set_setlist *map = set->data; int i, res = 0; @@ -107,8 +104,7 @@ insert_setlist(struct ip_set_setlist *map, int i, ip_set_id_t index) } static int -setlist_uadd(struct ip_set *set, const void *data, u_int32_t size, - ip_set_ip_t *hash_ip) +setlist_uadd(struct ip_set *set, const void *data, u_int32_t size) { struct ip_set_setlist *map = set->data; const struct ip_set_req_setlist *req = data; @@ -156,9 +152,7 @@ finish: 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) + const u_int32_t *flags) { struct ip_set_setlist *map = set->data; int i, res = -EINVAL; @@ -182,8 +176,7 @@ unshift_setlist(struct ip_set_setlist *map, int i) } static int -setlist_udel(struct ip_set *set, const void *data, u_int32_t size, - ip_set_ip_t *hash_ip) +setlist_udel(struct ip_set *set, const void *data, u_int32_t size) { struct ip_set_setlist *map = set->data; const struct ip_set_req_setlist *req = data; @@ -234,9 +227,7 @@ finish: 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) + const u_int32_t *flags) { struct ip_set_setlist *map = set->data; int i, res = -EINVAL; @@ -304,21 +295,24 @@ setlist_list_header(const struct ip_set *set, void *data) } static int -setlist_list_members_size(const struct ip_set *set) +setlist_list_members_size(const struct ip_set *set, char dont_align) { const struct ip_set_setlist *map = set->data; - return map->size * sizeof(ip_set_id_t); + return map->size * IPSET_VALIGN(sizeof(ip_set_id_t), dont_align); } static void -setlist_list_members(const struct ip_set *set, void *data) +setlist_list_members(const struct ip_set *set, void *data, char dont_align) { struct ip_set_setlist *map = set->data; + ip_set_id_t *d; int i; - for (i = 0; i < map->size; i++) - *((ip_set_id_t *)data + i) = ip_set_id(map->index[i]); + for (i = 0; i < map->size; i++) { + d = data + i * IPSET_VALIGN(sizeof(ip_set_id_t), dont_align); + *d = ip_set_id(map->index[i]); + } } IP_SET_TYPE(setlist, IPSET_TYPE_SETNAME | IPSET_DATA_SINGLE) diff --git a/tests/iphash.t b/tests/iphash.t index 4c33ce3..7a3ce1f 100644 --- a/tests/iphash.t +++ b/tests/iphash.t @@ -14,6 +14,10 @@ 0 ipset -T test 192.168.68.69 # IP: Test value not added to the set 1 ipset -T test 2.0.0.2 +# IP: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# IP: Check listing +0 diff .foo iphash.t.list0 && rm .foo # IP: Flush test set 0 ipset -F test # IP: Delete test set @@ -28,11 +32,11 @@ 0 ipset -X test # Network: Create a set 0 ipset -N test iphash --hashsize 128 --netmask 24 -# Range: Add zero valued element +# Network: Add zero valued element 2 ipset -A test 0.0.0.0 -# Range: Test zero valued element +# Network: Test zero valued element 2 ipset -T test 0.0.0.0 -# Range: Delete zero valued element +# Network: Delete zero valued element 2 ipset -D test 0.0.0.0 # Network: Add first random network 0 ipset -A test 2.0.0.1 @@ -44,6 +48,10 @@ 0 ipset -T test 192.168.68.95 # Network: Test value not added to the set 1 ipset -T test 2.0.1.0 +# Network: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Network: Check listing +0 diff .foo iphash.t.list1 && rm .foo # Network: Flush test set 0 ipset -F test # Network: Delete test set diff --git a/tests/iphash.t.list0 b/tests/iphash.t.list0 new file mode 100644 index 0000000..93d51c2 --- /dev/null +++ b/tests/iphash.t.list0 @@ -0,0 +1,7 @@ +Name: test +Type: iphash +References: 0 +Header: hashsize: 128 probes: 8 resize: 50 +Members: +192.168.68.69 +2.0.0.1 diff --git a/tests/iphash.t.list1 b/tests/iphash.t.list1 new file mode 100644 index 0000000..7f13c1c --- /dev/null +++ b/tests/iphash.t.list1 @@ -0,0 +1,7 @@ +Name: test +Type: iphash +References: 0 +Header: hashsize: 128 probes: 8 resize: 50 netmask: 24 +Members: +192.168.68.0 +2.0.0.0 diff --git a/tests/ipmap.t b/tests/ipmap.t index 58b913a..239cef9 100644 --- a/tests/ipmap.t +++ b/tests/ipmap.t @@ -20,6 +20,10 @@ 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: List set +0 ipset -L test > .foo +# Range: Check listing +0 diff .foo ipmap.t.list0 && rm .foo # Range: Flush test set 0 ipset -F test # Range: Delete test set @@ -46,6 +50,10 @@ 1 ipset -A test 1.255.255.255 # Network: Try to add value after upper boundary 1 ipset -A test 2.1.0.0 +# Network: List set +0 ipset -L test > .foo +# Network: Check listing +0 diff .foo ipmap.t.list1 && rm .foo # Network: Flush test set 0 ipset -F test # Network: Delete test set @@ -70,6 +78,10 @@ 1 ipset -A test 9.255.255.255 # Subnets: Try to add value after upper boundary 1 ipset -A test 11.0.0.0 +# Subnets: List set +0 ipset -L test > .foo +# Subnets: Check listing +0 diff .foo ipmap.t.list2 && rm .foo # Subnets: FLush test set 0 ipset -F test # Subnets: Delete test set @@ -86,6 +98,10 @@ 0 ipset -T test 255.255.255.255 # Full: Test value not added to the set 1 ipset -T test 0.1.0.0 +# Full: List set +0 ipset -L test > .foo +# Full: Check listing +0 diff .foo ipmap.t.list3 && rm .foo # Full: Delete test set 0 ipset -X test # eof diff --git a/tests/ipmap.t.list0 b/tests/ipmap.t.list0 new file mode 100644 index 0000000..aeaa4fb --- /dev/null +++ b/tests/ipmap.t.list0 @@ -0,0 +1,8 @@ +Name: test +Type: ipmap +References: 0 +Header: from: 2.0.0.1 to: 2.1.0.0 +Members: +2.0.0.1 +2.1.0.0 + diff --git a/tests/ipmap.t.list1 b/tests/ipmap.t.list1 new file mode 100644 index 0000000..53b76b6 --- /dev/null +++ b/tests/ipmap.t.list1 @@ -0,0 +1,8 @@ +Name: test +Type: ipmap +References: 0 +Header: from: 2.0.0.0 to: 2.0.255.255 +Members: +2.0.0.0 +2.0.255.255 + diff --git a/tests/ipmap.t.list2 b/tests/ipmap.t.list2 new file mode 100644 index 0000000..695254b --- /dev/null +++ b/tests/ipmap.t.list2 @@ -0,0 +1,8 @@ +Name: test +Type: ipmap +References: 0 +Header: from: 10.0.0.0 to: 10.255.255.255 netmask: 24 +Members: +10.0.0.0 +10.255.255.0 + diff --git a/tests/ipmap.t.list3 b/tests/ipmap.t.list3 new file mode 100644 index 0000000..3d95091 --- /dev/null +++ b/tests/ipmap.t.list3 @@ -0,0 +1,8 @@ +Name: test +Type: ipmap +References: 0 +Header: from: 0.0.0.0 to: 255.255.255.255 netmask: 16 +Members: +0.0.0.0 +255.255.0.0 + diff --git a/tests/ipporthash.t b/tests/ipporthash.t index 74fed1a..7c622bb 100644 --- a/tests/ipporthash.t +++ b/tests/ipporthash.t @@ -28,6 +28,10 @@ 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 +# Range: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Range: Check listing +0 diff .foo ipporthash.t.list0 && rm .foo # Range: Flush test set 0 ipset -F test # Range: Delete test set @@ -56,6 +60,10 @@ 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 +# Network: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Network: Check listing +0 diff .foo ipporthash.t.list1 && rm .foo # Network: Flush test set 0 ipset -F test # Network: Delete test set diff --git a/tests/ipporthash.t.list0 b/tests/ipporthash.t.list0 new file mode 100644 index 0000000..b840a94 --- /dev/null +++ b/tests/ipporthash.t.list0 @@ -0,0 +1,7 @@ +Name: test +Type: ipporthash +References: 0 +Header: from: 2.0.0.1 to: 2.1.0.0 hashsize: 1024 probes: 8 resize: 50 +Members: +2.0.0.1,5 +2.1.0.0,128 diff --git a/tests/ipporthash.t.list1 b/tests/ipporthash.t.list1 new file mode 100644 index 0000000..be86cda --- /dev/null +++ b/tests/ipporthash.t.list1 @@ -0,0 +1,7 @@ +Name: test +Type: ipporthash +References: 0 +Header: from: 2.0.0.0 to: 2.0.255.255 hashsize: 1024 probes: 8 resize: 50 +Members: +2.0.0.0,5 +2.0.255.255,128 diff --git a/tests/ipportiphash.t b/tests/ipportiphash.t index c7c25e5..860d5a6 100644 --- a/tests/ipportiphash.t +++ b/tests/ipportiphash.t @@ -36,6 +36,10 @@ 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: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Range: Check listing +0 diff .foo ipportiphash.t.list0 && rm .foo # Range: Flush test set 0 ipset -F test # Range: Delete test set @@ -64,6 +68,10 @@ 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: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Network: Check listing +0 diff .foo ipportiphash.t.list1 && rm .foo # Network: Flush test set 0 ipset -F test # Network: Delete test set diff --git a/tests/ipportiphash.t.list0 b/tests/ipportiphash.t.list0 new file mode 100644 index 0000000..acb1041 --- /dev/null +++ b/tests/ipportiphash.t.list0 @@ -0,0 +1,7 @@ +Name: test +Type: ipportiphash +References: 0 +Header: from: 2.0.0.1 to: 2.1.0.0 hashsize: 1024 probes: 8 resize: 50 +Members: +2.0.0.1,5,1.1.1.1 +2.1.0.0,128,2.2.2.2 diff --git a/tests/ipportiphash.t.list1 b/tests/ipportiphash.t.list1 new file mode 100644 index 0000000..5545078 --- /dev/null +++ b/tests/ipportiphash.t.list1 @@ -0,0 +1,7 @@ +Name: test +Type: ipportiphash +References: 0 +Header: from: 2.0.0.0 to: 2.0.255.255 hashsize: 1024 probes: 8 resize: 50 +Members: +2.0.0.0,5,1.1.1.1 +2.0.255.255,128,2.2.2.2 diff --git a/tests/ipportnethash.t b/tests/ipportnethash.t index 0b87dad..93369ef 100644 --- a/tests/ipportnethash.t +++ b/tests/ipportnethash.t @@ -36,6 +36,10 @@ 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: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Range: Check listing +0 diff .foo ipportnethash.t.list0 && rm .foo # Range: Flush test set 0 ipset -F test # Range: Delete test set @@ -64,6 +68,10 @@ 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: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Network: Check listing +0 diff .foo ipportnethash.t.list1 && rm .foo # Network: Flush test set 0 ipset -F test # Network: Delete test set diff --git a/tests/ipportnethash.t.list0 b/tests/ipportnethash.t.list0 new file mode 100644 index 0000000..9727d20 --- /dev/null +++ b/tests/ipportnethash.t.list0 @@ -0,0 +1,7 @@ +Name: test +Type: ipportnethash +References: 0 +Header: from: 2.0.0.1 to: 2.1.0.0 hashsize: 1024 probes: 8 resize: 50 +Members: +2.0.0.1,5,1.1.1.0/24 +2.1.0.0,128,2.0.0.0/12 diff --git a/tests/ipportnethash.t.list1 b/tests/ipportnethash.t.list1 new file mode 100644 index 0000000..ad861d4 --- /dev/null +++ b/tests/ipportnethash.t.list1 @@ -0,0 +1,7 @@ +Name: test +Type: ipportnethash +References: 0 +Header: from: 2.0.0.0 to: 2.0.255.255 hashsize: 1024 probes: 8 resize: 50 +Members: +2.0.0.0,5,1.1.1.0/24 +2.0.255.255,128,2.0.0.0/12 diff --git a/tests/iptree.t b/tests/iptree.t index 746baed..3cb0e00 100644 --- a/tests/iptree.t +++ b/tests/iptree.t @@ -12,6 +12,10 @@ 1 ipset -T test 2.0.0.2 # Static: Test value not added to the set 1 ipset -T test 192.168.68.70 +# Static: List set +0 ipset -L test > .foo +# Static: Check listing +0 diff .foo iptree.t.list0 && rm .foo # Static: Flush test set 0 ipset -F test # Static: Delete test set diff --git a/tests/iptree.t.list0 b/tests/iptree.t.list0 new file mode 100644 index 0000000..07433b9 --- /dev/null +++ b/tests/iptree.t.list0 @@ -0,0 +1,8 @@ +Name: test +Type: iptree +References: 0 +Header: +Members: +2.0.0.1 +192.168.68.69 + diff --git a/tests/iptreemap.t b/tests/iptreemap.t index b563522..2e9fce7 100644 --- a/tests/iptreemap.t +++ b/tests/iptreemap.t @@ -46,6 +46,10 @@ 0 ipset -T test 192.168.68.67 # Test element after upper bound of deleted network 0 ipset -T test 192.168.68.72 +# List set +0 ipset -L test > .foo +# Check listing +0 diff .foo iptreemap.t.list0 && rm .foo # Flush test set 0 ipset -F test # Delete test set diff --git a/tests/iptreemap.t.list0 b/tests/iptreemap.t.list0 new file mode 100644 index 0000000..6e783a0 --- /dev/null +++ b/tests/iptreemap.t.list0 @@ -0,0 +1,11 @@ +Name: test +Type: iptreemap +References: 0 +Header: gc: 300 +Members: +2.0.0.1 +3.0.0.0 +3.0.0.2 +192.168.68.64-192.168.68.67 +192.168.68.72-192.168.68.95 + diff --git a/tests/macipmap.t b/tests/macipmap.t index a498a4f..d088958 100644 --- a/tests/macipmap.t +++ b/tests/macipmap.t @@ -26,6 +26,10 @@ 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: List set +0 ipset -L test > .foo +# Range: Check listing +0 diff .foo macipmap.t.list0 && rm .foo # Range: Flush test set 0 ipset -F test # Range: Delete test set @@ -52,6 +56,10 @@ 1 ipset -A test 1.255.255.255 # Network: Try to add value after upper boundary 1 ipset -A test 2.1.0.0 +# Network: List set +0 ipset -L test > .foo +# Network: Check listing +0 diff .foo macipmap.t.list1 && rm .foo # Network: Flush test set 0 ipset -F test # Network: Delete test set diff --git a/tests/macipmap.t.list0 b/tests/macipmap.t.list0 new file mode 100644 index 0000000..157ba53 --- /dev/null +++ b/tests/macipmap.t.list0 @@ -0,0 +1,9 @@ +Name: test +Type: macipmap +References: 0 +Header: from: 2.0.0.1 to: 2.1.0.0 +Members: +2.0.0.1,00:00:00:00:00:00 +2.0.0.2,00:11:22:33:44:55 +2.1.0.0,00:00:00:00:00:00 + diff --git a/tests/macipmap.t.list1 b/tests/macipmap.t.list1 new file mode 100644 index 0000000..dc0dc75 --- /dev/null +++ b/tests/macipmap.t.list1 @@ -0,0 +1,8 @@ +Name: test +Type: macipmap +References: 0 +Header: from: 2.0.0.0 to: 2.0.255.255 +Members: +2.0.0.0,00:00:00:00:00:00 +2.0.255.255,00:00:00:00:00:00 + diff --git a/tests/nethash.t b/tests/nethash.t index b2f234e..cedcfde 100644 --- a/tests/nethash.t +++ b/tests/nethash.t @@ -16,18 +16,22 @@ 0 ipset -T test 0.0.0.0/1 # Range: Delete almost zero valued element 0 ipset -D test 0.0.0.0/1 -# Add first random network +# Range: Add first random network 0 ipset -A test 2.0.0.1/24 -# Add second random network +# Range: Add second random network 0 ipset -A test 192.168.68.69/27 -# Test first random value +# Range: Test first random value 0 ipset -T test 2.0.0.255 -# Test second random value +# Range: Test second random value 0 ipset -T test 192.168.68.95 -# Test value not added to the set +# Range: Test value not added to the set 1 ipset -T test 2.0.1.0 -# Try to add IP address +# Range: Try to add IP address 2 ipset -A test 2.0.0.1 +# Range: List set +0 ipset -L test > .foo0 && ./sort.sh .foo0 +# Range: Check listing +0 diff .foo nethash.t.list0 && rm .foo # Flush test set 0 ipset -F test # Delete test set diff --git a/tests/nethash.t.list0 b/tests/nethash.t.list0 new file mode 100644 index 0000000..0b008b8 --- /dev/null +++ b/tests/nethash.t.list0 @@ -0,0 +1,7 @@ +Name: test +Type: nethash +References: 0 +Header: hashsize: 128 probes: 4 resize: 50 +Members: +192.168.68.64/27 +2.0.0.0/24 diff --git a/tests/portmap.t b/tests/portmap.t index 299877a..12cdc1f 100644 --- a/tests/portmap.t +++ b/tests/portmap.t @@ -18,6 +18,10 @@ 1 ipset -A test 0 # Range: Try to add value after upper boundary 1 ipset -A test 1025 +# Range: List set +0 ipset -L test > .foo +# Range: Check listing +0 diff .foo portmap.t.list0 && rm .foo # Range: Flush test set 0 ipset -F test # Range: Delete test set @@ -34,6 +38,10 @@ 0 ipset -T test 65535 # Full: Test value not added to the set 1 ipset -T test 1 +# Full: List set +0 ipset -L test > .foo +# Full: Check listing +0 diff .foo portmap.t.list1 && rm .foo # Full: Flush test set 0 ipset -F test # Full: Delete test set diff --git a/tests/portmap.t.list0 b/tests/portmap.t.list0 new file mode 100644 index 0000000..809ffe1 --- /dev/null +++ b/tests/portmap.t.list0 @@ -0,0 +1,8 @@ +Name: test +Type: portmap +References: 0 +Header: from: 1 to: 1024 +Members: +1 +1024 + diff --git a/tests/portmap.t.list1 b/tests/portmap.t.list1 new file mode 100644 index 0000000..9c9b38d --- /dev/null +++ b/tests/portmap.t.list1 @@ -0,0 +1,8 @@ +Name: test +Type: portmap +References: 0 +Header: from: 0 to: 65535 +Members: +0 +65535 + diff --git a/tests/setlist.t b/tests/setlist.t index d677863..ed21396 100644 --- a/tests/setlist.t +++ b/tests/setlist.t @@ -38,6 +38,10 @@ 0 ipset -X # Setlist: Restore saved sets 0 ipset -R < setlist.t.restore +# Setlist: List set +0 ipset -L test > .foo +# Setlist: Check listing +0 diff .foo setlist.t.list0 && rm .foo # Setlist: Flush all sets 0 ipset -F # Setlist: Delete all sets diff --git a/tests/setlist.t.list0 b/tests/setlist.t.list0 new file mode 100644 index 0000000..9b70446 --- /dev/null +++ b/tests/setlist.t.list0 @@ -0,0 +1,8 @@ +Name: test +Type: setlist +References: 0 +Header: size: 8 +Members: +foo +bar + diff --git a/tests/sort.sh b/tests/sort.sh new file mode 100755 index 0000000..a01d066 --- /dev/null +++ b/tests/sort.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +awk '/^[A-Za-z]+:/ { print $0 }' $1 > .foo +awk '!/^[A-Za-z]+:/ && !/inding/ { print $0 }' | sort >> .foo +rm $1 |