From 4eec8b3824d49c1c0503ebbf7844a4e312bc29e1 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu" Date: Thu, 13 Nov 2008 09:36:37 +0000 Subject: 2.4.4 - Premature checking prevents to add valid elements to hash types, fixed (bug reported by JC Janos). - Local variable shadows another variable, fixed (reported by Jan Engelhardt). - More compiler warning options added and warnings fixed. --- ChangeLog | 7 ++ Makefile | 30 ++++++- ipset.c | 97 +++++++++++----------- ipset.h | 20 +++-- ipset_iphash.c | 30 +++---- ipset_ipmap.c | 17 ++-- ipset_ipporthash.c | 16 ++-- ipset_ipportiphash.c | 15 ++-- ipset_ipportnethash.c | 20 ++--- ipset_iptree.c | 18 ++-- ipset_iptreemap.c | 23 ++--- ipset_macipmap.c | 21 +++-- ipset_nethash.c | 40 ++++----- ipset_portmap.c | 21 +++-- ipset_setlist.c | 24 +++--- kernel/ChangeLog | 4 + kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h | 4 +- kernel/ip_set_ipportnethash.c | 11 +-- kernel/ip_set_nethash.c | 18 ++-- tests/iphash.t | 6 ++ tests/ipporthash.t | 2 + tests/ipportiphash.t | 8 ++ tests/ipportnethash.t | 12 ++- tests/nethash.t | 12 +++ 24 files changed, 277 insertions(+), 199 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9cc30a9..b1cbd1a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2.4.4 + - Premature checking prevents to add valid elements to hash + types, fixed (bug reported by JC Janos). + - Local variable shadows another variable, fixed (reported + by Jan Engelhardt). + - More compiler warning options added and warnings fixed. + 2.4.3 - Include file was missing from userspace set type modules, reported by Krzysztof Oledzki and Sven Wegener. diff --git a/Makefile b/Makefile index 7dfd819..aa05b58 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ ifndef V V=0 endif -IPSET_VERSION:=2.4.3 +IPSET_VERSION:=2.4.4 PREFIX:=/usr/local LIBDIR:=$(PREFIX)/lib @@ -33,7 +33,31 @@ IPSET_LIB_DIR:=$(LIBDIR)/ipset RELEASE_DIR:=/tmp COPT_FLAGS:=-O2 -CFLAGS:=$(COPT_FLAGS) -Wall -Wunused -Ikernel/include -I. # -g -DIPSET_DEBUG #-pg # -DIPTC_DEBUG +WARN_FLAGS:=-Wall \ + -Wextra \ + -Waggregate-return \ + -Wbad-function-cast \ + -Wcast-align \ + -Wformat=2 \ + -Wfloat-equal \ + -Winit-self \ + -Winline \ + -Wmissing-declarations \ + -Wmissing-prototypes \ + -Wnested-externs \ + -Wold-style-definition \ + -Wpacked \ + -Wredundant-decls \ + -Wshadow \ + -Wsign-compare \ + -Wstrict-prototypes \ + -Wswitch-default \ + -Wswitch-enum \ + -Wundef \ + -Wwrite-strings \ + -Werror + +CFLAGS:=$(COPT_FLAGS) $(WARN_FLAGS) -Ikernel/include -I. # -g -DIPSET_DEBUG #-pg SH_CFLAGS:=$(CFLAGS) -fPIC SETTYPES:=ipmap portmap macipmap SETTYPES+=iptree iptreemap @@ -87,7 +111,7 @@ ipset_%.o: ipset_%.c ipset.h $(CC) $(SH_CFLAGS) -o $@ -c $< libipset_%.so: ipset_%.o - $(LD) -shared -o $@ $< + $(CC) -shared -o $@ $< $(DESTDIR)$(LIBDIR)/ipset/libipset_%.so: libipset_%.so @[ -d $(DESTDIR)$(LIBDIR)/ipset ] || mkdir -p $(DESTDIR)$(LIBDIR)/ipset diff --git a/ipset.c b/ipset.c index 8b906aa..6a204b9 100644 --- a/ipset.c +++ b/ipset.c @@ -118,7 +118,7 @@ static struct option opts_long[] = { {"help", 2, 0, 'H'}, /* end */ - {NULL}, + {0, 0, 0, 0}, }; static char opts_short[] = @@ -162,11 +162,11 @@ static void exit_tryhelp(int status) exit(status); } -void exit_error(enum exittype status, const char *msg, ...) +void exit_error(int status, const char *msg, ...) { - va_list args; - if (!option_quiet) { + va_list args; + va_start(args, msg); fprintf(stderr, "%s v%s: ", program_name, program_version); vfprintf(stderr, msg, args); @@ -185,11 +185,11 @@ void exit_error(enum exittype status, const char *msg, ...) exit(status); } -static void ipset_printf(char *msg, ...) +static void ipset_printf(const char *msg, ...) { - va_list args; - if (!option_quiet) { + va_list args; + va_start(args, msg); vfprintf(stdout, msg, args); va_end(args); @@ -197,7 +197,7 @@ static void ipset_printf(char *msg, ...) } } -static void generic_opt_check(int command, int options) +static void generic_opt_check(int command, unsigned int options) { int i, j, legal = 0; @@ -232,7 +232,7 @@ static void generic_opt_check(int command, int options) } } -static char opt2char(int option) +static char opt2char(unsigned int option) { const char *ptr; for (ptr = optflags; option > 1; option >>= 1, ptr++); @@ -240,12 +240,12 @@ static char opt2char(int option) return *ptr; } -static char cmd2char(int option) +static char cmd2char(int cmd) { - if (option <= CMD_NONE || option > NUMBER_OF_CMD) + if (cmd <= CMD_NONE || cmd > NUMBER_OF_CMD) return ' '; - return cmdflags[option]; + return cmdflags[cmd]; } /* From iptables.c ... */ @@ -265,6 +265,7 @@ static char *get_modprobe(void) switch (read(procfile, ret, PROCFILE_BUFSIZ)) { case -1: goto fail; case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ + default: ; /* nothing */ } if (ret[strlen(ret)-1]=='\n') ret[strlen(ret)-1]=0; @@ -294,8 +295,8 @@ static int ipset_insmod(const char *modname, const char *modprobe) switch (fork()) { case 0: - argv[0] = (char *)modprobe; - argv[1] = (char *)modname; + argv[0] = (char *) modprobe; + argv[1] = (char *) modname; argv[2] = NULL; execv(argv[0], argv); @@ -333,7 +334,7 @@ static void kernel_error(unsigned cmd, int err) struct translate_error { int err; unsigned cmd; - char *message; + const char *message; } table[] = { /* Generic error codes */ { EPERM, 0, "Missing capability" }, @@ -409,7 +410,7 @@ static void kernel_getfrom(unsigned cmd, void *data, socklen_t * size) kernel_error(cmd, errno); } -static int kernel_sendto_handleerrno(unsigned cmd, unsigned op, +static int kernel_sendto_handleerrno(unsigned cmd, void *data, socklen_t size) { int res = wrapped_setsockopt(data, size); @@ -471,7 +472,7 @@ static void check_protocolversion(void) req_version.version, IP_SET_PROTOCOL_VERSION); } -static void set_command(unsigned *cmd, const int newcmd) +static void set_command(int *cmd, int newcmd) { if (*cmd != CMD_NONE) exit_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n", @@ -523,7 +524,7 @@ void ipset_free(void *data) static struct option *merge_options(struct option *oldopts, const struct option *newopts, - unsigned int *option_offset) + int *option_offset) { unsigned int num_old, num_new, i; struct option *merge; @@ -563,7 +564,7 @@ static char *ip_tonetwork(const struct in_addr *addr) { struct netent *net; - if ((net = getnetbyaddr((long) ntohl(addr->s_addr), + if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL) { DP("%s", net->n_name); return (char *) net->n_name; @@ -590,7 +591,8 @@ char *ip_tostring(ip_set_ip_t ip, unsigned options) return inet_ntoa(addr); } -char *binding_ip_tostring(struct set *set, ip_set_ip_t ip, unsigned options) +char *binding_ip_tostring(struct set *set UNUSED, + ip_set_ip_t ip, unsigned options) { return ip_tostring(ip, options); } @@ -635,7 +637,7 @@ void parse_ip(const char *str, ip_set_ip_t * ip) void parse_mask(const char *str, ip_set_ip_t * mask) { struct in_addr addr; - unsigned int bits; + int bits; DP("%s", str); @@ -710,12 +712,12 @@ int string_to_number(const char *str, unsigned int min, unsigned int max, ip_set_ip_t *port) { - long number; + unsigned long number; char *end; /* Handle hex, octal, etc. */ errno = 0; - number = strtol(str, &end, 0); + number = strtoul(str, &end, 0); if (*end == '\0' && end != str) { /* we parsed a number, let's see if we want this */ if (errno != ERANGE && min <= number && number <= max) { @@ -729,14 +731,13 @@ string_to_number(const char *str, unsigned int min, unsigned int max, static int string_to_port(const char *str, ip_set_ip_t *port) { - struct servent *service; - + struct servent *service = getservbyname(str, "tcp"); + if ((service = getservbyname(str, "tcp")) != NULL) { - *port = ntohs((unsigned short) service->s_port); + *port = ntohs((uint16_t) service->s_port); return 0; } - - return -1; + return - 1; } /* Fills the 'ip' with the parsed port in host byte order */ @@ -1301,7 +1302,7 @@ static char *newargv[255]; static int newargc = 0; /* Build faked argv from parsed line */ -static void build_argv(int line, char *buffer) { +static void build_argv(unsigned line, char *buffer) { char *ptr; int i; @@ -1313,7 +1314,7 @@ static void build_argv(int line, char *buffer) { ptr = strtok(buffer, " \t\n"); newargv[newargc++] = ipset_strdup(ptr); while ((ptr = strtok(NULL, " \t\n")) != NULL) { - if ((newargc + 1) < sizeof(newargv)/sizeof(char *)) + if ((newargc + 1) < (int)(sizeof(newargv)/sizeof(char *))) newargv[newargc++] = ipset_strdup(ptr); else exit_error(PARAMETER_PROBLEM, @@ -1323,14 +1324,14 @@ static void build_argv(int line, char *buffer) { static FILE *create_tempfile(void) { - char buffer[1024]; + char buffer[1024], __tmpdir[] = "/tmp"; char *tmpdir = NULL; char *filename; int fd; FILE *file; if (!(tmpdir = getenv("TMPDIR")) && !(tmpdir = getenv("TMP"))) - tmpdir = "/tmp"; + tmpdir = __tmpdir; filename = ipset_malloc(strlen(tmpdir) + strlen(TEMPFILE_PATTERN) + 1); strcpy(filename, tmpdir); strcat(filename, TEMPFILE_PATTERN); @@ -1361,7 +1362,7 @@ static void set_restore(char *argv0) char buffer[1024]; char *ptr, *name = NULL; char cmd = ' '; - int restore_line = 0, first_pass, i, bindings = 0; + int first_pass, i, bindings = 0; struct settype *settype = NULL; struct ip_set_req_setnames *header; ip_set_id_t idx; @@ -1375,6 +1376,7 @@ static void set_restore(char *argv0) load_set_list(IPSET_TOKEN_ALL, &idx, 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 */ DP("restore_size: %u", restore_size); @@ -1584,7 +1586,7 @@ static int set_adtip(struct set *set, const char *adt, memcpy(data + sizeof(struct ip_set_req_adt), set->settype->data, set->settype->adt_size); - if (kernel_sendto_handleerrno(cmd, op, data, size) == -1) + if (kernel_sendto_handleerrno(cmd, data, size) == -1) switch (op) { case IP_SET_OP_ADD_IP: exit_error(OTHER_PROBLEM, "%s is already in set %s.", @@ -1615,7 +1617,7 @@ static int set_adtip(struct set *set, const char *adt, return res; } -static void set_restore_add(struct set *set, const char *adt) +static void set_restore_add(struct set *set, const char *adt UNUSED) { DP("%s %s", set->name, adt); /* Sanity checking */ @@ -1680,7 +1682,7 @@ static int set_bind(struct set *set, const char *adt, } if (op == IP_SET_OP_TEST_BIND_SET) { - if (kernel_sendto_handleerrno(cmd, op, data, size) == -1) { + if (kernel_sendto_handleerrno(cmd, data, size) == -1) { ipset_printf("%s in set %s is bound to %s.", adt, set->name, binding); res = 0; @@ -1879,13 +1881,6 @@ static void list_sets(const char name[IP_SET_MAXNAMELEN], unsigned options) */ static void set_help(const struct settype *settype) { -#ifdef IPSET_DEBUG - char debughelp[] = - " --debug -z Enable debugging\n\n"; -#else - char debughelp[] = "\n"; -#endif - printf("%s v%s\n\n" "Usage: %s -N new-set settype [options]\n" " %s -[XFLSH] [set] [options]\n" @@ -1940,7 +1935,11 @@ static void set_help(const struct settype *settype) " --resolve -r Try to resolve addresses in a -L\n" " --quiet -q Suppress any output to stdout and stderr.\n" " --binding -b Specifies the binding for -B\n"); - printf(debughelp); +#ifdef IPSET_DEBUG + printf(" --debug -z Enable debugging\n\n"); +#else + printf("\n"); +#endif if (settype != NULL) { printf("Type '%s' specific:\n", settype->typename); @@ -1948,18 +1947,18 @@ static void set_help(const struct settype *settype) } } -static int find_cmd(const char option) +static int find_cmd(int option) { int i; for (i = 1; i <= NUMBER_OF_CMD; i++) - if (cmdflags[i] == option) + if (cmdflags[i] == (char) option) return i; return CMD_NONE; } -static int parse_adt_cmdline(unsigned command, +static int parse_adt_cmdline(int command, const char *name, char *adt, struct set **set, @@ -2009,7 +2008,7 @@ static int parse_adt_cmdline(unsigned command, int parse_commandline(int argc, char *argv[]) { int res = 0; - unsigned command = CMD_NONE; + int command = CMD_NONE; unsigned options = 0; int c; @@ -2201,7 +2200,7 @@ int parse_commandline(int argc, char *argv[]) case 1: /* non option */ printf("Bad argument `%s'\n", optarg); - exit_tryhelp(2); + exit_tryhelp(PARAMETER_PROBLEM); break; /*always good */ default:{ diff --git a/ipset.h b/ipset.h index 1c8b0c1..35a2055 100644 --- a/ipset.h +++ b/ipset.h @@ -68,11 +68,10 @@ enum set_commands { CMD_ADT_GET, }; -enum exittype { - OTHER_PROBLEM = 1, - PARAMETER_PROBLEM, - VERSION_PROBLEM -}; +/* Exit codes */ +#define OTHER_PROBLEM 1 +#define PARAMETER_PROBLEM 2 +#define VERSION_PROBLEM 3 /* The view of an ipset in userspace */ struct set { @@ -118,7 +117,7 @@ struct settype { size_t adt_size; /* Function which parses command options */ - ip_set_ip_t (*adt_parser) (unsigned cmd, const char *optarg, void *data); + ip_set_ip_t (*adt_parser) (int cmd, const char *optarg, void *data); /* * Printing @@ -157,7 +156,7 @@ struct settype { /* Internal data */ void *header; void *data; - unsigned int option_offset; + int option_offset; unsigned int flags; }; @@ -165,7 +164,7 @@ extern void settype_register(struct settype *settype); /* extern void unregister_settype(set_type_t *set_type); */ -extern void exit_error(enum exittype status, const char *msg, ...); +extern void exit_error(int status, const char *msg, ...); extern char *binding_ip_tostring(struct set *set, ip_set_ip_t ip, unsigned options); @@ -194,4 +193,9 @@ extern unsigned warn_once; #define ID2MASK(id) (1 << ((id)%BITSPERBYTE)) #define test_bit(id, heap) ((((char *)(heap))[ID2BYTE(id)] & ID2MASK(id)) != 0) +#define UNUSED __attribute__ ((unused)) +#define CONSTRUCTOR(module) \ +void __attribute__ ((constructor)) module##_init(void); \ +void module##_init(void) + #endif /* __IPSET_H */ diff --git a/ipset_iphash.c b/ipset_iphash.c index 8110203..a11695b 100644 --- a/ipset_iphash.c +++ b/ipset_iphash.c @@ -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[], void *data, unsigned *flags) +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,14 +117,8 @@ create_parse(int c, char *argv[], void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data, unsigned int flags) +create_final(void *data UNUSED, unsigned int flags UNUSED) { -#ifdef IPSET_DEBUG - struct ip_set_req_iphash_create *mydata = data; - - DP("hashsize %u probes %u resize %u", - mydata->hashsize, mydata->probes, mydata->resize); -#endif } /* Create commandline options */ @@ -133,19 +127,19 @@ static const struct option create_opts[] = { {.name = "probes", .has_arg = required_argument, .val = '2'}, {.name = "resize", .has_arg = required_argument, .val = '3'}, {.name = "netmask", .has_arg = required_argument, .val = '4'}, - {NULL}, + {0, 0, 0, 0}, }; /* Add, del, test parser */ static ip_set_ip_t -adt_parser(unsigned cmd, const char *optarg, void *data) +adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_iphash *mydata = data; - parse_ip(optarg, &mydata->ip); + parse_ip(arg, &mydata->ip); if (!mydata->ip) exit_error(PARAMETER_PROBLEM, - "Zero valued IP address `%s' specified", optarg); + "Zero valued IP address `%s' specified", arg); return mydata->ip; }; @@ -177,14 +171,14 @@ mask_to_bits(ip_set_ip_t mask) return bits; maskaddr = 0xFFFFFFFE; - while (--bits >= 0 && maskaddr != mask) + while (--bits > 0 && maskaddr != mask) maskaddr <<= 1; return bits; } static void -printheader(struct set *set, unsigned options) +printheader(struct set *set, unsigned options UNUSED) { struct ip_set_iphash *mysetdata = set->settype->header; @@ -198,7 +192,7 @@ printheader(struct set *set, unsigned options) } static void -printips(struct set *set, void *data, size_t len, unsigned options) +printips(struct set *set UNUSED, void *data, size_t len, unsigned options) { size_t offset = 0; ip_set_ip_t *ip; @@ -212,7 +206,7 @@ printips(struct set *set, void *data, size_t len, unsigned options) } static void -saveheader(struct set *set, unsigned options) +saveheader(struct set *set, unsigned options UNUSED) { struct ip_set_iphash *mysetdata = set->settype->header; @@ -227,7 +221,7 @@ saveheader(struct set *set, unsigned options) /* Print save for an IP */ static void -saveips(struct set *set, void *data, size_t len, unsigned options) +saveips(struct set *set UNUSED, void *data, size_t len, unsigned options) { size_t offset = 0; ip_set_ip_t *ip; @@ -282,7 +276,7 @@ static struct settype settype_iphash = { .usage = &usage, }; -void _init(void) +CONSTRUCTOR(iphash) { settype_register(&settype_iphash); diff --git a/ipset_ipmap.c b/ipset_ipmap.c index f068537..a0158bd 100644 --- a/ipset_ipmap.c +++ b/ipset_ipmap.c @@ -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[], void *data, unsigned *flags) +create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_ipmap_create *mydata = data; unsigned int bits; @@ -183,18 +183,18 @@ static const struct option create_opts[] = { {.name = "to", .has_arg = required_argument, .val = '2'}, {.name = "network", .has_arg = required_argument, .val = '3'}, {.name = "netmask", .has_arg = required_argument, .val = '4'}, - {NULL}, + {0, 0, 0, 0}, }; /* Add, del, test parser */ static ip_set_ip_t -adt_parser(unsigned cmd, const char *optarg, void *data) +adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_ipmap *mydata = data; - DP("ipmap: %p %p", optarg, data); + DP("ipmap: %p %p", arg, data); - parse_ip(optarg, &mydata->ip); + parse_ip(arg, &mydata->ip); DP("%s", ip_tostring_numeric(mydata->ip)); return 1; @@ -247,7 +247,8 @@ printheader(struct set *set, unsigned options) } static void -printips_sorted(struct set *set, void *data, size_t len, unsigned options) +printips_sorted(struct set *set, void *data, + size_t len UNUSED, unsigned options) { struct ip_set_ipmap *mysetdata = set->settype->header; ip_set_ip_t id; @@ -278,7 +279,7 @@ saveheader(struct set *set, unsigned options) } static void -saveips(struct set *set, void *data, size_t len, unsigned options) +saveips(struct set *set, void *data, size_t len UNUSED, unsigned options) { struct ip_set_ipmap *mysetdata = set->settype->header; ip_set_ip_t id; @@ -334,7 +335,7 @@ static struct settype settype_ipmap = { .usage = &usage, }; -void _init(void) +CONSTRUCTOR(ipmap) { settype_register(&settype_ipmap); diff --git a/ipset_ipporthash.c b/ipset_ipporthash.c index be8cd85..1e5f562 100644 --- a/ipset_ipporthash.c +++ b/ipset_ipporthash.c @@ -46,7 +46,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[], void *data, unsigned *flags) +create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_ipporthash_create *mydata = data; ip_set_ip_t value; @@ -184,18 +184,18 @@ static const struct option create_opts[] = { {.name = "from", .has_arg = required_argument, .val = '4'}, {.name = "to", .has_arg = required_argument, .val = '5'}, {.name = "network", .has_arg = required_argument, .val = '6'}, - {NULL}, + {0, 0, 0, 0}, }; /* Add, del, test parser */ static ip_set_ip_t -adt_parser(unsigned cmd, const char *optarg, void *data) +adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_ipporthash *mydata = data; - char *saved = ipset_strdup(optarg); + char *saved = ipset_strdup(arg); char *ptr, *tmp = saved; - DP("ipporthash: %p %p", optarg, data); + DP("ipporthash: %p %p", arg, data); if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1) fprintf(stderr, "Warning: please use ',' separator token between ip,port.\n" @@ -209,6 +209,10 @@ adt_parser(unsigned cmd, const char *optarg, void *data) else exit_error(PARAMETER_PROBLEM, "IP address and port must be specified: ip,port"); + + if (!(mydata->ip || mydata->port)) + exit_error(PARAMETER_PROBLEM, + "Zero valued IP address and port `%s' specified", arg); ipset_free(saved); return 1; }; @@ -359,7 +363,7 @@ static struct settype settype_ipporthash = { .usage = &usage, }; -void _init(void) +CONSTRUCTOR(ipporthash) { settype_register(&settype_ipporthash); diff --git a/ipset_ipportiphash.c b/ipset_ipportiphash.c index 84d085f..0942d30 100644 --- a/ipset_ipportiphash.c +++ b/ipset_ipportiphash.c @@ -46,7 +46,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[], void *data, unsigned *flags) +create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_ipportiphash_create *mydata = data; ip_set_ip_t value; @@ -184,18 +184,18 @@ static const struct option create_opts[] = { {.name = "from", .has_arg = required_argument, .val = '4'}, {.name = "to", .has_arg = required_argument, .val = '5'}, {.name = "network", .has_arg = required_argument, .val = '6'}, - {NULL}, + {0, 0, 0, 0}, }; /* Add, del, test parser */ static ip_set_ip_t -adt_parser(unsigned cmd, const char *optarg, void *data) +adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_ipportiphash *mydata = data; - char *saved = ipset_strdup(optarg); + char *saved = ipset_strdup(arg); char *ptr, *tmp = saved; - DP("ipportiphash: %p %p", optarg, data); + DP("ipportiphash: %p %p", arg, data); if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1) fprintf(stderr, "Warning: please use ',' separator token between ip,port,ip.\n" @@ -215,6 +215,9 @@ adt_parser(unsigned cmd, const char *optarg, void *data) else exit_error(PARAMETER_PROBLEM, "IP address, port and IP address must be specified: ip,port,ip"); + if (!(mydata->ip || mydata->port || mydata->ip1)) + exit_error(PARAMETER_PROBLEM, + "Zero valued IP address, port and IP address `%s' specified", arg); ipset_free(saved); return 1; }; @@ -351,7 +354,7 @@ static struct settype settype_ipportiphash = { .usage = &usage, }; -void _init(void) +CONSTRUCTOR(ipportiphash) { settype_register(&settype_ipportiphash); diff --git a/ipset_ipportnethash.c b/ipset_ipportnethash.c index 83a83fe..eabe41e 100644 --- a/ipset_ipportnethash.c +++ b/ipset_ipportnethash.c @@ -46,7 +46,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[], void *data, unsigned *flags) +create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_ipportnethash_create *mydata = data; ip_set_ip_t value; @@ -184,19 +184,19 @@ static const struct option create_opts[] = { {.name = "from", .has_arg = required_argument, .val = '4'}, {.name = "to", .has_arg = required_argument, .val = '5'}, {.name = "network", .has_arg = required_argument, .val = '6'}, - {NULL}, + {0, 0, 0, 0}, }; /* Add, del, test parser */ static ip_set_ip_t -adt_parser(unsigned cmd, const char *optarg, void *data) +adt_parser(int cmd, const char *arg, void *data) { struct ip_set_req_ipportnethash *mydata = data; - char *saved = ipset_strdup(optarg); + char *saved = ipset_strdup(arg); char *ptr, *tmp = saved; ip_set_ip_t cidr; - DP("ipportnethash: %p %p", optarg, data); + DP("ipportnethash: %p %p", arg, data); if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1) fprintf(stderr, "Warning: please use ',' separator token between ip,port,net.\n" @@ -220,11 +220,11 @@ adt_parser(unsigned cmd, const char *optarg, void *data) cidr = 32; else exit_error(PARAMETER_PROBLEM, - "Missing /cidr from `%s'", optarg); + "Missing /cidr from `%s'", arg); else if (string_to_number(tmp, 1, 31, &cidr)) exit_error(PARAMETER_PROBLEM, - "Out of range cidr `%s' specified", optarg); + "Out of range cidr `%s' specified", arg); mydata->cidr = cidr; @@ -266,7 +266,7 @@ printheader(struct set *set, unsigned options) static char buf[20]; static char * -unpack_ip_tostring(ip_set_ip_t ip, unsigned options) +unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED) { int i, j = 3; unsigned char a, b; @@ -313,7 +313,7 @@ unpack_ip_tostring(ip_set_ip_t ip, unsigned options) ((unsigned char *)&ip)[3], b); - DP("%s %s", ip_tostring(ntohl(ip), options), buf); + DP("%s %s", ip_tostring(ntohl(ip), 0), buf); return buf; } @@ -419,7 +419,7 @@ static struct settype settype_ipportnethash = { .usage = &usage, }; -void _init(void) +CONSTRUCTOR(ipportnethash) { settype_register(&settype_ipportnethash); diff --git a/ipset_iptree.c b/ipset_iptree.c index b127c9f..f8cd488 100644 --- a/ipset_iptree.c +++ b/ipset_iptree.c @@ -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[], void *data, unsigned *flags) +create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_iptree_create *mydata = data; @@ -63,25 +63,25 @@ create_parse(int c, char *argv[], void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data, unsigned int flags) +create_final(void *data UNUSED, unsigned int flags UNUSED) { } /* Create commandline options */ static const struct option create_opts[] = { {.name = "timeout", .has_arg = required_argument, .val = '1'}, - {NULL}, + {0, 0, 0, 0}, }; /* Add, del, test parser */ static ip_set_ip_t -adt_parser(unsigned cmd, const char *optarg, void *data) +adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_iptree *mydata = data; - char *saved = ipset_strdup(optarg); + char *saved = ipset_strdup(arg); char *ptr, *tmp = saved; - DP("iptree: %p %p", optarg, data); + DP("iptree: %p %p", arg, data); if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1) fprintf(stderr, "Warning: please use ',' separator token between ip,timeout.\n" @@ -113,7 +113,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options) +printheader(struct set *set, unsigned options UNUSED) { struct ip_set_iptree *mysetdata = set->settype->header; @@ -141,7 +141,7 @@ printips_sorted(struct set *set, void *data, size_t len, unsigned options) } static void -saveheader(struct set *set, unsigned options) +saveheader(struct set *set, unsigned options UNUSED) { struct ip_set_iptree *mysetdata = set->settype->header; @@ -218,7 +218,7 @@ static struct settype settype_iptree = { .usage = &usage, }; -void _init(void) +CONSTRUCTOR(iptree) { settype_register(&settype_iptree); diff --git a/ipset_iptreemap.c b/ipset_iptreemap.c index d1d31bb..bcdf133 100644 --- a/ipset_iptreemap.c +++ b/ipset_iptreemap.c @@ -34,7 +34,7 @@ create_init(void *data) } static int -create_parse(int c, char *argv[], void *data, unsigned int *flags) +create_parse(int c, char *argv[] UNUSED, void *data, unsigned int *flags) { struct ip_set_req_iptreemap_create *mydata = data; @@ -53,22 +53,22 @@ create_parse(int c, char *argv[], void *data, unsigned int *flags) } static void -create_final(void *data, unsigned int flags) +create_final(void *data UNUSED, unsigned int flags UNUSED) { } static const struct option create_opts[] = { {.name = "gc", .has_arg = required_argument, .val = 'g'}, - {NULL}, + {0, 0, 0, 0}, }; static ip_set_ip_t -adt_parser(unsigned int cmd, const char *optarg, void *data) +adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_iptreemap *mydata = data; ip_set_ip_t mask; - char *saved = ipset_strdup(optarg); + char *saved = ipset_strdup(arg); char *ptr, *tmp = saved; if (strchr(tmp, '/')) { @@ -103,7 +103,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned int options) +printheader(struct set *set, unsigned int options UNUSED) { struct ip_set_iptreemap *mysetdata = set->settype->header; @@ -114,7 +114,8 @@ printheader(struct set *set, unsigned int options) } static void -printips_sorted(struct set *set, void *data, size_t len, unsigned int options) +printips_sorted(struct set *set UNUSED, void *data, + size_t len, unsigned int options) { struct ip_set_req_iptreemap *req; size_t offset = 0; @@ -132,7 +133,7 @@ printips_sorted(struct set *set, void *data, size_t len, unsigned int options) } static void -saveheader(struct set *set, unsigned int options) +saveheader(struct set *set, unsigned int options UNUSED) { struct ip_set_iptreemap *mysetdata = set->settype->header; @@ -145,7 +146,8 @@ saveheader(struct set *set, unsigned int options) } static void -saveips(struct set *set, void *data, size_t len, unsigned int options) +saveips(struct set *set UNUSED, void *data, + size_t len, unsigned int options) { struct ip_set_req_iptreemap *req; size_t offset = 0; @@ -202,8 +204,7 @@ static struct settype settype_iptreemap = { .usage = &usage, }; -void -_init(void) +CONSTRUCTOR(iptreemap) { settype_register(&settype_iptreemap); } diff --git a/ipset_macipmap.c b/ipset_macipmap.c index d4b8a06..839a6e0 100644 --- a/ipset_macipmap.c +++ b/ipset_macipmap.c @@ -39,7 +39,7 @@ /* Initialize the create. */ static void -create_init(void *data) +create_init(void *data UNUSED) { DP("create INIT"); /* Nothing */ @@ -47,7 +47,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[], void *data, unsigned *flags) +create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_macipmap_create *mydata = data; @@ -149,7 +149,7 @@ static const struct option create_opts[] = { {.name = "to", .has_arg = required_argument, .val = '2'}, {.name = "network", .has_arg = required_argument, .val = '3'}, {.name = "matchunset", .has_arg = no_argument, .val = '4'}, - {NULL}, + {0, 0, 0, 0}, }; static void @@ -176,13 +176,13 @@ parse_mac(const char *mac, unsigned char *ethernet) /* Add, del, test parser */ static ip_set_ip_t -adt_parser(unsigned cmd, const char *optarg, void *data) +adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_macipmap *mydata = data; - char *saved = ipset_strdup(optarg); + char *saved = ipset_strdup(arg); char *ptr, *tmp = saved; - DP("macipmap: %p %p", optarg, data); + DP("macipmap: %p %p", arg, data); ptr = strsep(&tmp, ","); if (!tmp) { @@ -200,6 +200,7 @@ adt_parser(unsigned cmd, const char *optarg, void *data) memset(mydata->ethernet, 0, ETH_ALEN); free(saved); + return 1; } @@ -243,7 +244,8 @@ print_mac(unsigned char macaddress[ETH_ALEN]) } static void -printips_sorted(struct set *set, void *data, size_t len, unsigned options) +printips_sorted(struct set *set, void *data, + size_t len UNUSED, unsigned options) { struct ip_set_macipmap *mysetdata = set->settype->header; struct ip_set_macip *table = data; @@ -277,7 +279,8 @@ saveheader(struct set *set, unsigned options) } static void -saveips(struct set *set, void *data, size_t len, unsigned options) +saveips(struct set *set, void *data, + size_t len UNUSED, unsigned options) { struct ip_set_macipmap *mysetdata = set->settype->header; struct ip_set_macip *table = data; @@ -337,7 +340,7 @@ static struct settype settype_macipmap = { .usage = &usage, }; -void _init(void) +CONSTRUCTOR(macipmap) { settype_register(&settype_macipmap); diff --git a/ipset_nethash.c b/ipset_nethash.c index ff6576f..7c1f609 100644 --- a/ipset_nethash.c +++ b/ipset_nethash.c @@ -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[], void *data, unsigned *flags) +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,14 +97,8 @@ create_parse(int c, char *argv[], void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data, unsigned int flags) +create_final(void *data UNUSED, unsigned int flags UNUSED) { -#ifdef IPSET_DEBUG - struct ip_set_req_nethash_create *mydata = data; - - DP("hashsize %u probes %u resize %u", - mydata->hashsize, mydata->probes, mydata->resize); -#endif } /* Create commandline options */ @@ -112,15 +106,15 @@ static const struct option create_opts[] = { {.name = "hashsize", .has_arg = required_argument, .val = '1'}, {.name = "probes", .has_arg = required_argument, .val = '2'}, {.name = "resize", .has_arg = required_argument, .val = '3'}, - {NULL}, + {0, 0, 0, 0}, }; /* Add, del, test parser */ static ip_set_ip_t -adt_parser(unsigned cmd, const char *optarg, void *data) +adt_parser(int cmd, const char *arg, void *data) { struct ip_set_req_nethash *mydata = data; - char *saved = ipset_strdup(optarg); + char *saved = ipset_strdup(arg); char *ptr, *tmp = saved; ip_set_ip_t cidr; @@ -131,20 +125,22 @@ adt_parser(unsigned cmd, const char *optarg, void *data) cidr = 32; else exit_error(PARAMETER_PROBLEM, - "Missing cidr from `%s'", optarg); + "Missing cidr from `%s'", arg); } else if (string_to_number(tmp, 1, 31, &cidr)) exit_error(PARAMETER_PROBLEM, - "Out of range cidr `%s' specified", optarg); + "Out of range cidr `%s' specified", arg); mydata->cidr = cidr; parse_ip(ptr, &mydata->ip); +#if 0 if (!mydata->ip) exit_error(PARAMETER_PROBLEM, "Zero valued IP address `%s' specified", ptr); +#endif ipset_free(saved); - return mydata->ip; + return 1; }; /* @@ -164,7 +160,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options) +printheader(struct set *set, unsigned options UNUSED) { struct ip_set_nethash *mysetdata = set->settype->header; @@ -176,7 +172,7 @@ printheader(struct set *set, unsigned options) static char buf[20]; static char * -unpack_ip_tostring(ip_set_ip_t ip, unsigned options) +unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED) { int i, j = 3; unsigned char a, b; @@ -223,12 +219,12 @@ unpack_ip_tostring(ip_set_ip_t ip, unsigned options) ((unsigned char *)&ip)[3], b); - DP("%s %s", ip_tostring(ntohl(ip), options), buf); + DP("%s %s", ip_tostring(ntohl(ip), 0), buf); return buf; } static void -printips(struct set *set, void *data, size_t len, unsigned options) +printips(struct set *set UNUSED, void *data, size_t len, unsigned options) { size_t offset = 0; ip_set_ip_t *ip; @@ -242,7 +238,7 @@ printips(struct set *set, void *data, size_t len, unsigned options) } static void -saveheader(struct set *set, unsigned options) +saveheader(struct set *set, unsigned options UNUSED) { struct ip_set_nethash *mysetdata = set->settype->header; @@ -253,7 +249,7 @@ saveheader(struct set *set, unsigned options) /* Print save for an IP */ static void -saveips(struct set *set, void *data, size_t len, unsigned options) +saveips(struct set *set UNUSED, void *data, size_t len, unsigned options) { size_t offset = 0; ip_set_ip_t *ip; @@ -268,7 +264,7 @@ saveips(struct set *set, void *data, size_t len, unsigned options) } static char * -net_tostring(struct set *set, ip_set_ip_t ip, unsigned options) +net_tostring(struct set *set UNUSED, ip_set_ip_t ip, unsigned options) { return unpack_ip_tostring(ip, options); } @@ -337,7 +333,7 @@ static struct settype settype_nethash = { .usage = &usage, }; -void _init(void) +CONSTRUCTOR(nethash) { settype_register(&settype_nethash); diff --git a/ipset_portmap.c b/ipset_portmap.c index 6d35b4c..b9f4ef8 100644 --- a/ipset_portmap.c +++ b/ipset_portmap.c @@ -32,7 +32,7 @@ /* Initialize the create. */ static void -create_init(void *data) +create_init(void *data UNUSED) { DP("create INIT"); /* Nothing */ @@ -40,7 +40,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[], void *data, unsigned *flags) +create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags) { struct ip_set_req_portmap_create *mydata = data; @@ -108,16 +108,16 @@ create_final(void *data, unsigned int flags) static const struct option create_opts[] = { {.name = "from", .has_arg = required_argument, .val = '1'}, {.name = "to", .has_arg = required_argument, .val = '2'}, - {NULL}, + {0, 0, 0, 0}, }; /* Add, del, test parser */ static ip_set_ip_t -adt_parser(unsigned cmd, const char *optarg, void *data) +adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_portmap *mydata = data; - parse_port(optarg, &mydata->ip); + parse_port(arg, &mydata->ip); DP("%s", port_tostring(mydata->ip, 0)); return 1; @@ -148,7 +148,8 @@ printheader(struct set *set, unsigned options) } static void -printports_sorted(struct set *set, void *data, size_t len, unsigned options) +printports_sorted(struct set *set, void *data, + size_t len UNUSED, unsigned options) { struct ip_set_portmap *mysetdata = set->settype->header; u_int32_t addr = mysetdata->first_ip; @@ -162,7 +163,8 @@ printports_sorted(struct set *set, void *data, size_t len, unsigned options) } static char * -binding_port_tostring(struct set *set, ip_set_ip_t ip, unsigned options) +binding_port_tostring(struct set *set UNUSED, + ip_set_ip_t ip, unsigned options) { return port_tostring(ip, options); } @@ -181,7 +183,8 @@ saveheader(struct set *set, unsigned options) } static void -saveports(struct set *set, void *data, size_t len, unsigned options) +saveports(struct set *set, void *data, + size_t len UNUSED, unsigned options) { struct ip_set_portmap *mysetdata = set->settype->header; u_int32_t addr = mysetdata->first_ip; @@ -235,7 +238,7 @@ static struct settype settype_portmap = { .usage = &usage, }; -void _init(void) +CONSTRUCTOR(portmap) { settype_register(&settype_portmap); diff --git a/ipset_setlist.c b/ipset_setlist.c index b82cd6c..8e0bd94 100644 --- a/ipset_setlist.c +++ b/ipset_setlist.c @@ -36,7 +36,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[], void *data, unsigned *flags) +create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags UNUSED) { struct ip_set_req_setlist_create *mydata = data; unsigned int size; @@ -57,14 +57,14 @@ create_parse(int c, char *argv[], void *data, unsigned *flags) /* Final check; exit if not ok. */ static void -create_final(void *data, unsigned int flags) +create_final(void *data UNUSED, unsigned int flags UNUSED) { } /* Create commandline options */ static const struct option create_opts[] = { {.name = "size", .has_arg = required_argument, .val = '1'}, - {NULL}, + {0, 0, 0, 0}, }; static void check_setname(const char *name) @@ -77,13 +77,13 @@ static void check_setname(const char *name) /* Add, del, test parser */ static ip_set_ip_t -adt_parser(unsigned cmd, const char *optarg, void *data) +adt_parser(int cmd UNUSED, const char *arg, void *data) { struct ip_set_req_setlist *mydata = data; - char *saved = ipset_strdup(optarg); + char *saved = ipset_strdup(arg); char *ptr, *tmp = saved; - DP("setlist: %p %p", optarg, data); + DP("setlist: %p %p", arg, data); ptr = strsep(&tmp, ","); check_setname(ptr); @@ -125,7 +125,7 @@ initheader(struct set *set, const void *data) } static void -printheader(struct set *set, unsigned options) +printheader(struct set *set, unsigned options UNUSED) { struct ip_set_setlist *mysetdata = set->settype->header; @@ -133,7 +133,8 @@ printheader(struct set *set, unsigned options) } static void -printips_sorted(struct set *set, void *data, size_t len, unsigned options) +printips_sorted(struct set *set, void *data, + size_t len UNUSED, unsigned options UNUSED) { struct ip_set_setlist *mysetdata = set->settype->header; int i; @@ -150,7 +151,7 @@ printips_sorted(struct set *set, void *data, size_t len, unsigned options) } static void -saveheader(struct set *set, unsigned options) +saveheader(struct set *set, unsigned options UNUSED) { struct ip_set_setlist *mysetdata = set->settype->header; @@ -160,7 +161,8 @@ saveheader(struct set *set, unsigned options) } static void -saveips(struct set *set, void *data, size_t len, unsigned options) +saveips(struct set *set, void *data, + size_t len UNUSED, unsigned options UNUSED) { struct ip_set_setlist *mysetdata = set->settype->header; int i; @@ -212,7 +214,7 @@ static struct settype settype_setlist = { .usage = &usage, }; -void _init(void) +CONSTRUCTOR(setlist) { settype_register(&settype_setlist); diff --git a/kernel/ChangeLog b/kernel/ChangeLog index 25006be..292e19f 100644 --- a/kernel/ChangeLog +++ b/kernel/ChangeLog @@ -1,3 +1,7 @@ +2.4.4 + - Premature checking prevents to add valid elements to hash + types, fixed (bug reported by JC Janos). + 2.4.2 - When flushing a nethash/ipportnethash type of set, it can lead to a kernel crash due to a wrong type declaration, diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h b/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h index 3d800ef..d1381b5 100644 --- a/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h +++ b/kernel/include/linux/netfilter_ipv4/ip_set_ipmap.h @@ -36,7 +36,7 @@ mask_to_bits(ip_set_ip_t mask) return bits; maskaddr = 0xFFFFFFFE; - while (--bits >= 0 && maskaddr != mask) + while (--bits > 0 && maskaddr != mask) maskaddr <<= 1; return bits; @@ -48,7 +48,7 @@ range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits) ip_set_ip_t mask = 0xFFFFFFFE; *bits = 32; - while (--(*bits) >= 0 && mask && (to & mask) != from) + while (--(*bits) > 0 && mask && (to & mask) != from) mask <<= 1; return mask; diff --git a/kernel/ip_set_ipportnethash.c b/kernel/ip_set_ipportnethash.c index 3c7f859..87385a3 100644 --- a/kernel/ip_set_ipportnethash.c +++ b/kernel/ip_set_ipportnethash.c @@ -44,6 +44,8 @@ ipportnethash_id_cidr(struct ip_set *set, ip_set_ip_t *hash_ip, DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u", set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip)); ip1 = pack_ip_cidr(ip1, cidr); + if (!(*hash_ip || ip1)) + return UINT_MAX; for (i = 0; i < map->probes; i++) { id = jhash_ip2(map, i, *hash_ip, ip1) % map->hashsize; @@ -104,13 +106,10 @@ static int ipportnethash_utest(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip) { - const struct ip_set_ipportnethash *map = set->data; const struct ip_set_req_ipportnethash *req = data; if (req->cidr <= 0 || req->cidr > 32) return -EINVAL; - if (!(pack_ip_port(map, req->ip, req->port))) - return -ERANGE; return (req->cidr == 32 ? ipportnethash_test(set, hash_ip, req->ip, req->port, req->ip1) @@ -120,7 +119,6 @@ ipportnethash_utest(struct ip_set *set, const void *data, size_t size, #define KADT_CONDITION \ ip_set_ip_t port, ip1; \ - struct ip_set_ipportnethash *map = set->data; \ \ if (flags[index+2] == 0) \ return 0; \ @@ -129,8 +127,6 @@ ipportnethash_utest(struct ip_set *set, const void *data, size_t size, ip1 = ipaddr(skb, flags[index+2]); \ \ if (port == INVALID_PORT) \ - return 0; \ - if (!(pack_ip_port(map, ip, port))) \ return 0; KADT(ipportnethash, test, ipaddr, port, ip1) @@ -185,10 +181,11 @@ ipportnethash_add(struct ip_set *set, ip_set_ip_t *hash_ip, return -ERANGE; *hash_ip = pack_ip_port(map, ip, port); + ip1 = pack_ip_cidr(ip1, cidr); if (!(*hash_ip || ip1)) return -ERANGE; - ret =__ipportnet_add(map, *hash_ip, pack_ip_cidr(ip1, cidr)); + ret =__ipportnet_add(map, *hash_ip, ip1); if (ret == 0) { if (!map->nets[cidr-1]++) add_cidr_size(map->cidr, cidr); diff --git a/kernel/ip_set_nethash.c b/kernel/ip_set_nethash.c index 9b3d826..d5b7a76 100644 --- a/kernel/ip_set_nethash.c +++ b/kernel/ip_set_nethash.c @@ -35,6 +35,8 @@ nethash_id_cidr(const struct ip_set_nethash *map, ip_set_ip_t *elem; *hash_ip = pack_ip_cidr(ip, cidr); + if (!*hash_ip) + return MAX_RANGE; for (i = 0; i < map->probes; i++) { id = jhash_ip(map, i, *hash_ip) % map->hashsize; @@ -67,13 +69,13 @@ nethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip, { const struct ip_set_nethash *map = set->data; - return (ip && nethash_id_cidr(map, hash_ip, ip, cidr) != UINT_MAX); + return (nethash_id_cidr(map, hash_ip, ip, cidr) != UINT_MAX); } static inline int nethash_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) { - return (ip && nethash_id(set, hash_ip, ip) != UINT_MAX); + return (nethash_id(set, hash_ip, ip) != UINT_MAX); } static int @@ -120,15 +122,15 @@ nethash_add(struct ip_set *set, ip_set_ip_t *hash_ip, struct ip_set_nethash *map = set->data; int ret; - if (!ip || map->elements >= limit) - return -ERANGE; + if (map->elements >= limit || map->nets[cidr-1] == UINT16_MAX) + return -ERANGE; if (cidr <= 0 || cidr >= 32) return -EINVAL; - if (map->nets[cidr-1] == UINT16_MAX) - return -ERANGE; - + *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) + return -ERANGE; ret = __nethash_add(map, hash_ip); if (ret == 0) { @@ -164,8 +166,6 @@ nethash_del(struct ip_set *set, ip_set_ip_t *hash_ip, struct ip_set_nethash *map = set->data; ip_set_ip_t id, *elem; - if (!ip) - return -ERANGE; if (cidr <= 0 || cidr >= 32) return -EINVAL; diff --git a/tests/iphash.t b/tests/iphash.t index 46ce58b..4c33ce3 100644 --- a/tests/iphash.t +++ b/tests/iphash.t @@ -28,6 +28,12 @@ 0 ipset -X test # Network: Create a set 0 ipset -N test iphash --hashsize 128 --netmask 24 +# Range: Add zero valued element +2 ipset -A test 0.0.0.0 +# Range: Test zero valued element +2 ipset -T test 0.0.0.0 +# Range: 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 # Network: Add second random network diff --git a/tests/ipporthash.t b/tests/ipporthash.t index 4db4bf3..74fed1a 100644 --- a/tests/ipporthash.t +++ b/tests/ipporthash.t @@ -6,6 +6,8 @@ 1 ipset -A test 2.0.0.1,0 # Range: Test zero valued element 1 ipset -T test 2.0.0.1,0 +# Range: Delete zero valued element +1 ipset -D test 2.0.0.1,0 # Range: Add lower boundary 0 ipset -A test 2.0.0.1,5 # Range: Add upper boundary diff --git a/tests/ipportiphash.t b/tests/ipportiphash.t index 2b38667..c7c25e5 100644 --- a/tests/ipportiphash.t +++ b/tests/ipportiphash.t @@ -6,6 +6,14 @@ 1 ipset -A test 2.0.0.1,0,0.0.0.0 # Range: Test zero valued element 1 ipset -T test 2.0.0.1,0,0.0.0.0 +# Range: Delete zero valued element +1 ipset -D test 2.0.0.1,0,0.0.0.0 +# Range: Add almost zero valued element +0 ipset -A test 2.0.0.1,0,0.0.0.1 +# Range: Test almost zero valued element +0 ipset -T test 2.0.0.1,0,0.0.0.1 +# Range: Delete almost zero valued element +0 ipset -D test 2.0.0.1,0,0.0.0.1 # Range: Add lower boundary 0 ipset -A test 2.0.0.1,5,1.1.1.1 # Range: Add upper boundary diff --git a/tests/ipportnethash.t b/tests/ipportnethash.t index 35cb9fc..0b87dad 100644 --- a/tests/ipportnethash.t +++ b/tests/ipportnethash.t @@ -3,9 +3,17 @@ # Range: Create a set from a valid range 0 ipset -N test ipportnethash --from 2.0.0.1 --to 2.1.0.0 # Range: Add zero valued element -1 ipset -A test 2.0.0.1,0,0.0.0.0/1 +2 ipset -A test 2.0.0.1,0,0.0.0.0/0 # Range: Test zero valued element -1 ipset -T test 2.0.0.1,0,0.0.0.0/1 +2 ipset -T test 2.0.0.1,0,0.0.0.0/0 +# Range: Delete zero valued element +2 ipset -D test 2.0.0.1,0,0.0.0.0/0 +# Range: Add almost zero valued element +0 ipset -A test 2.0.0.1,0,0.0.0.0/24 +# Range: Test almost zero valued element +0 ipset -T test 2.0.0.1,0,0.0.0.0/24 +# Range: Delete almost zero valued element +0 ipset -D test 2.0.0.1,0,0.0.0.0/24 # Range: Add lower boundary 0 ipset -A test 2.0.0.1,5,1.1.1.1/24 # Range: Add upper boundary diff --git a/tests/nethash.t b/tests/nethash.t index 0011216..b2f234e 100644 --- a/tests/nethash.t +++ b/tests/nethash.t @@ -4,6 +4,18 @@ 2 ipset -A test 0.0.0.0/0 # Range: Test zero valued element 2 ipset -T test 0.0.0.0/0 +# Range: Delete zero valued element +2 ipset -D test 0.0.0.0/0 +# Range: Try to add /0 +2 ipset -A test 1.1.1.1/0 +# Range: Try to add /32 +2 ipset -A test 1.1.1.1/32 +# Range: Add almost zero valued element +0 ipset -A test 0.0.0.0/1 +# Range: Test almost zero valued element +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 0 ipset -A test 2.0.0.1/24 # Add second random network -- cgit v1.2.3