diff options
author | Patrick McHardy <kaber@trash.net> | 2011-05-09 20:23:21 +0200 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-05-09 20:23:21 +0200 |
commit | c29f7ef7cb5a31620060ef721d3c65b343eb537a (patch) | |
tree | 09d7a610fbdda5c259d85458f4b6cf9ae9b07f03 | |
parent | edc2b1adf32d2b11e126174f525293b3bca6e7bc (diff) | |
parent | 6cfb28bb9032dcf2749ff80f88ad37b9fe5e7c2a (diff) |
Merge branch 'opts' of git://dev.medozas.de/iptables
-rw-r--r-- | extensions/libip6t_ipv6header.c | 6 | ||||
-rw-r--r-- | extensions/libip6t_rt.c | 4 | ||||
-rw-r--r-- | extensions/libxt_IDLETIMER.c | 70 | ||||
-rw-r--r-- | extensions/libxt_NFLOG.c | 98 | ||||
-rw-r--r-- | extensions/libxt_TCPOPTSTRIP.c | 2 | ||||
-rw-r--r-- | extensions/libxt_dccp.c | 6 | ||||
-rw-r--r-- | extensions/libxt_multiport.c | 10 | ||||
-rw-r--r-- | extensions/libxt_owner.c | 20 | ||||
-rw-r--r-- | extensions/libxt_policy.c | 4 | ||||
-rw-r--r-- | extensions/libxt_rateest.c | 2 | ||||
-rw-r--r-- | extensions/libxt_sctp.c | 6 | ||||
-rw-r--r-- | extensions/libxt_statistic.c | 160 | ||||
-rw-r--r-- | extensions/libxt_statistic.man | 11 | ||||
-rw-r--r-- | extensions/libxt_tcp.c | 6 | ||||
-rw-r--r-- | extensions/libxt_tos.c | 4 | ||||
-rw-r--r-- | extensions/libxt_u32.c | 1 | ||||
-rw-r--r-- | extensions/libxt_udp.c | 6 | ||||
-rw-r--r-- | include/xtables.h.in | 5 | ||||
-rw-r--r-- | xtables.c | 4 | ||||
-rw-r--r-- | xtoptions.c | 27 |
20 files changed, 167 insertions, 285 deletions
diff --git a/extensions/libip6t_ipv6header.c b/extensions/libip6t_ipv6header.c index fca6f323..00d5d5b4 100644 --- a/extensions/libip6t_ipv6header.c +++ b/extensions/libip6t_ipv6header.c @@ -61,13 +61,13 @@ static const struct numflag chain_flags[] = { { IPPROTO_RAW, MASK_PROTO }, }; -static char * +static const char * proto_to_name(uint8_t proto, int nolookup) { unsigned int i; if (proto && !nolookup) { - struct protoent *pent = getprotobynumber(proto); + const struct protoent *pent = getprotobynumber(proto); if (pent) return pent->p_name; } @@ -83,7 +83,7 @@ static uint16_t name_to_proto(const char *s) { unsigned int proto=0; - struct protoent *pent; + const struct protoent *pent; if ((pent = getprotobyname(s))) proto = pent->p_proto; diff --git a/extensions/libip6t_rt.c b/extensions/libip6t_rt.c index 333350db..1c57dbd6 100644 --- a/extensions/libip6t_rt.c +++ b/extensions/libip6t_rt.c @@ -81,11 +81,11 @@ parse_rt_segsleft(const char *idstring, uint32_t *ids) free(buffer); } -static char * +static const char * addr_to_numeric(const struct in6_addr *addrp) { static char buf[50+1]; - return (char *)inet_ntop(AF_INET6, addrp, buf, sizeof(buf)); + return inet_ntop(AF_INET6, addrp, buf, sizeof(buf)); } static struct in6_addr * diff --git a/extensions/libxt_IDLETIMER.c b/extensions/libxt_IDLETIMER.c index 847ab180..21004a4b 100644 --- a/extensions/libxt_IDLETIMER.c +++ b/extensions/libxt_IDLETIMER.c @@ -20,26 +20,24 @@ * 02110-1301 USA * */ -#include <stdbool.h> #include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <getopt.h> -#include <stddef.h> - #include <xtables.h> #include <linux/netfilter/xt_IDLETIMER.h> enum { - IDLETIMER_TG_OPT_TIMEOUT = 1 << 0, - IDLETIMER_TG_OPT_LABEL = 1 << 1, + O_TIMEOUT = 0, + O_LABEL, }; -static const struct option idletimer_tg_opts[] = { - {.name = "timeout", .has_arg = true, .val = 't'}, - {.name = "label", .has_arg = true, .val = 'l'}, - XT_GETOPT_TABLEEND, +#define s struct idletimer_tg_info +static const struct xt_option_entry idletimer_tg_opts[] = { + {.name = "timeout", .id = O_TIMEOUT, .type = XTTYPE_UINT32, + .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, timeout)}, + {.name = "label", .id = O_LABEL, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, label)}, + XTOPT_TABLEEND, }; +#undef s static void idletimer_tg_help(void) { @@ -50,49 +48,6 @@ static void idletimer_tg_help(void) "\n"); } -static int idletimer_tg_parse(int c, char **argv, int invert, - unsigned int *flags, - const void *entry, - struct xt_entry_target **target) -{ - struct idletimer_tg_info *info = - (struct idletimer_tg_info *)(*target)->data; - - switch (c) { - case 't': - xtables_param_act(XTF_ONLY_ONCE, "IDLETIMER", "--timeout", - *flags & IDLETIMER_TG_OPT_TIMEOUT); - - info->timeout = atoi(optarg); - *flags |= IDLETIMER_TG_OPT_TIMEOUT; - break; - - case 'l': - xtables_param_act(XTF_ONLY_ONCE, "IDLETIMER", "--label", - *flags & IDLETIMER_TG_OPT_TIMEOUT); - - if (strlen(optarg) > MAX_IDLETIMER_LABEL_SIZE - 1) - xtables_param_act(XTF_BAD_VALUE, "IDLETIMER", "--label", - optarg); - - strcpy(info->label, optarg); - *flags |= IDLETIMER_TG_OPT_LABEL; - break; - } - - return true; -} - -static void idletimer_tg_final_check(unsigned int flags) -{ - if (!(flags & IDLETIMER_TG_OPT_TIMEOUT)) - xtables_error(PARAMETER_PROBLEM, "IDLETIMER target: " - "--timeout parameter required"); - if (!(flags & IDLETIMER_TG_OPT_LABEL)) - xtables_error(PARAMETER_PROBLEM, "IDLETIMER target: " - "--label parameter required"); -} - static void idletimer_tg_print(const void *ip, const struct xt_entry_target *target, int numeric) @@ -122,11 +77,10 @@ static struct xtables_target idletimer_tg_reg = { .size = XT_ALIGN(sizeof(struct idletimer_tg_info)), .userspacesize = offsetof(struct idletimer_tg_info, timer), .help = idletimer_tg_help, - .parse = idletimer_tg_parse, - .final_check = idletimer_tg_final_check, + .x6_parse = xtables_option_parse, .print = idletimer_tg_print, .save = idletimer_tg_save, - .extra_opts = idletimer_tg_opts, + .x6_options = idletimer_tg_opts, }; void _init(void) diff --git a/extensions/libxt_NFLOG.c b/extensions/libxt_NFLOG.c index 61c97412..448576af 100644 --- a/extensions/libxt_NFLOG.c +++ b/extensions/libxt_NFLOG.c @@ -9,19 +9,25 @@ #include <linux/netfilter/xt_NFLOG.h> enum { - NFLOG_GROUP = 0x1, - NFLOG_PREFIX = 0x2, - NFLOG_RANGE = 0x4, - NFLOG_THRESHOLD = 0x8, + O_GROUP = 0, + O_PREFIX, + O_RANGE, + O_THRESHOLD, }; -static const struct option NFLOG_opts[] = { - {.name = "nflog-group", .has_arg = true, .val = NFLOG_GROUP}, - {.name = "nflog-prefix", .has_arg = true, .val = NFLOG_PREFIX}, - {.name = "nflog-range", .has_arg = true, .val = NFLOG_RANGE}, - {.name = "nflog-threshold", .has_arg = true, .val = NFLOG_THRESHOLD}, - XT_GETOPT_TABLEEND, +#define s struct xt_nflog_info +static const struct xt_option_entry NFLOG_opts[] = { + {.name = "nflog-group", .id = O_GROUP, .type = XTTYPE_UINT16, + .flags = XTOPT_PUT, XTOPT_POINTER(s, group)}, + {.name = "nflog-prefix", .id = O_PREFIX, .type = XTTYPE_STRING, + .min = 1, .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix)}, + {.name = "nflog-range", .id = O_RANGE, .type = XTTYPE_UINT32, + .flags = XTOPT_PUT, XTOPT_POINTER(s, len)}, + {.name = "nflog-threshold", .id = O_THRESHOLD, .type = XTTYPE_UINT16, + .flags = XTOPT_PUT, XTOPT_POINTER(s, threshold)}, + XTOPT_TABLEEND, }; +#undef s static void NFLOG_help(void) { @@ -39,72 +45,16 @@ static void NFLOG_init(struct xt_entry_target *t) info->threshold = XT_NFLOG_DEFAULT_THRESHOLD; } -static int NFLOG_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) +static void NFLOG_parse(struct xt_option_call *cb) { - struct xt_nflog_info *info = (struct xt_nflog_info *)(*target)->data; - int n; - size_t length; - - switch (c) { - case NFLOG_GROUP: - if (*flags & NFLOG_GROUP) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --nflog-group twice"); - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --nflog-group"); - - n = atoi(optarg); - if (n < 0) - xtables_error(PARAMETER_PROBLEM, - "--nflog-group can not be negative"); - info->group = n; - break; - case NFLOG_PREFIX: - if (*flags & NFLOG_PREFIX) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --nflog-prefix twice"); - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --nflog-prefix"); - - length = strlen(optarg); - if (length == 0) - xtables_error(PARAMETER_PROBLEM, - "No prefix specified for --nflog-prefix"); - if (length >= sizeof(info->prefix)) - xtables_error(PARAMETER_PROBLEM, - "--nflog-prefix too long, max %Zu characters", - sizeof(info->prefix) - 1); - if (length != strlen(strtok(optarg, "\n"))) - xtables_error(PARAMETER_PROBLEM, - "Newlines are not allowed in --nflog-prefix"); - strcpy(info->prefix, optarg); - break; - case NFLOG_RANGE: - if (*flags & NFLOG_RANGE) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --nflog-range twice"); - n = atoi(optarg); - if (n < 0) - xtables_error(PARAMETER_PROBLEM, - "Invalid --nflog-range, must be >= 0"); - info->len = n; - break; - case NFLOG_THRESHOLD: - if (*flags & NFLOG_THRESHOLD) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --nflog-threshold twice"); - n = atoi(optarg); - if (n < 1) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_PREFIX: + if (strchr(cb->arg, '\n') != NULL) xtables_error(PARAMETER_PROBLEM, - "Invalid --nflog-threshold, must be >= 1"); - info->threshold = n; + "Newlines not allowed in --log-prefix"); break; } - *flags |= c; - return 1; } static void nflog_print(const struct xt_nflog_info *info, char *prefix) @@ -144,10 +94,10 @@ static struct xtables_target nflog_target = { .userspacesize = XT_ALIGN(sizeof(struct xt_nflog_info)), .help = NFLOG_help, .init = NFLOG_init, - .parse = NFLOG_parse, + .x6_parse = NFLOG_parse, .print = NFLOG_print, .save = NFLOG_save, - .extra_opts = NFLOG_opts, + .x6_options = NFLOG_opts, }; void _init(void) diff --git a/extensions/libxt_TCPOPTSTRIP.c b/extensions/libxt_TCPOPTSTRIP.c index 43320d1b..68978573 100644 --- a/extensions/libxt_TCPOPTSTRIP.c +++ b/extensions/libxt_TCPOPTSTRIP.c @@ -34,7 +34,7 @@ static const struct tcp_optionmap tcp_optionmap[] = { {"sack", "Selective ACK", TCPOPT_SACK}, {"timestamp", "Timestamp", TCPOPT_TIMESTAMP}, {"md5", "MD5 signature", TCPOPT_MD5SIG}, - XT_GETOPT_TABLEEND, + {NULL}, }; static void tcpoptstrip_tg_help(void) diff --git a/extensions/libxt_dccp.c b/extensions/libxt_dccp.c index 5aff262a..28c59b9d 100644 --- a/extensions/libxt_dccp.c +++ b/extensions/libxt_dccp.c @@ -126,10 +126,10 @@ static void dccp_parse(struct xt_option_call *cb) } } -static char * +static const char * port_to_service(int port) { - struct servent *service; + const struct servent *service; if ((service = getservbyport(htons(port), "dccp"))) return service->s_name; @@ -140,7 +140,7 @@ port_to_service(int port) static void print_port(uint16_t port, int numeric) { - char *service; + const char *service; if (numeric || (service = port_to_service(port)) == NULL) printf("%u", port); diff --git a/extensions/libxt_multiport.c b/extensions/libxt_multiport.c index 163c7dc5..7fa537e0 100644 --- a/extensions/libxt_multiport.c +++ b/extensions/libxt_multiport.c @@ -53,7 +53,7 @@ static const struct option multiport_opts[] = { XT_GETOPT_TABLEEND, }; -static char * +static const char * proto_to_name(uint8_t proto) { switch (proto) { @@ -135,7 +135,7 @@ parse_multi_ports_v1(const char *portstring, static const char * check_proto(uint16_t pnum, uint8_t invflags) { - char *proto; + const char *proto; if (invflags & XT_INV_PROTO) xtables_error(PARAMETER_PROBLEM, @@ -285,10 +285,10 @@ static void multiport_check(unsigned int flags) xtables_error(PARAMETER_PROBLEM, "multiport expection an option"); } -static char * +static const char * port_to_service(int port, uint8_t proto) { - struct servent *service; + const struct servent *service; if ((service = getservbyport(htons(port), proto_to_name(proto)))) return service->s_name; @@ -299,7 +299,7 @@ port_to_service(int port, uint8_t proto) static void print_port(uint16_t port, uint8_t protocol, int numeric) { - char *service; + const char *service; if (numeric || (service = port_to_service(port, protocol)) == NULL) printf("%u", port); diff --git a/extensions/libxt_owner.c b/extensions/libxt_owner.c index 5cc7b7a6..f930cf45 100644 --- a/extensions/libxt_owner.c +++ b/extensions/libxt_owner.c @@ -65,7 +65,6 @@ enum { static void owner_mt_help_v0(void) { -#ifdef IPT_OWNER_COMM printf( "owner match options:\n" "[!] --uid-owner userid Match local UID\n" @@ -74,15 +73,6 @@ static void owner_mt_help_v0(void) "[!] --sid-owner sessionid Match local SID\n" "[!] --cmd-owner name Match local command name\n" "NOTE: PID, SID and command matching are broken on SMP\n"); -#else - printf( -"owner match options:\n" -"[!] --uid-owner userid Match local UID\n" -"[!] --gid-owner groupid Match local GID\n" -"[!] --pid-owner processid Match local PID\n" -"[!] --sid-owner sessionid Match local SID\n" -"NOTE: PID and SID matching are broken on SMP\n"); -#endif /* IPT_OWNER_COMM */ } static void owner_mt6_help_v0(void) @@ -110,9 +100,7 @@ static const struct option owner_mt_opts_v0[] = { {.name = "gid-owner", .has_arg = true, .val = 'g'}, {.name = "pid-owner", .has_arg = true, .val = 'p'}, {.name = "sid-owner", .has_arg = true, .val = 's'}, -#ifdef IPT_OWNER_COMM {.name = "cmd-owner", .has_arg = true, .val = 'c'}, -#endif XT_GETOPT_TABLEEND, }; @@ -189,7 +177,6 @@ owner_mt_parse_v0(int c, char **argv, int invert, unsigned int *flags, *flags |= FLAG_SID_OWNER; return true; -#ifdef IPT_OWNER_COMM case 'c': xtables_param_act(XTF_ONLY_ONCE, "owner", "--cmd-owner", *flags & FLAG_COMM); if (strlen(optarg) > sizeof(info->comm)) @@ -205,7 +192,6 @@ owner_mt_parse_v0(int c, char **argv, int invert, unsigned int *flags, info->match |= IPT_OWNER_COMM; *flags |= FLAG_COMM; return true; -#endif } return false; } @@ -394,11 +380,9 @@ owner_mt_print_item_v0(const struct ipt_owner_info *info, const char *label, printf(" %u", (unsigned int)info->sid); break; -#ifdef IPT_OWNER_COMM case IPT_OWNER_COMM: printf(" %.*s", (int)sizeof(info->comm), info->comm); break; -#endif } } @@ -502,9 +486,7 @@ owner_mt_print_v0(const void *ip, const struct xt_entry_match *match, owner_mt_print_item_v0(info, "owner GID match", IPT_OWNER_GID, numeric); owner_mt_print_item_v0(info, "owner PID match", IPT_OWNER_PID, numeric); owner_mt_print_item_v0(info, "owner SID match", IPT_OWNER_SID, numeric); -#ifdef IPT_OWNER_COMM owner_mt_print_item_v0(info, "owner CMD match", IPT_OWNER_COMM, numeric); -#endif } static void @@ -538,9 +520,7 @@ owner_mt_save_v0(const void *ip, const struct xt_entry_match *match) owner_mt_print_item_v0(info, "--gid-owner", IPT_OWNER_GID, true); owner_mt_print_item_v0(info, "--pid-owner", IPT_OWNER_PID, true); owner_mt_print_item_v0(info, "--sid-owner", IPT_OWNER_SID, true); -#ifdef IPT_OWNER_COMM owner_mt_print_item_v0(info, "--cmd-owner", IPT_OWNER_COMM, true); -#endif } static void diff --git a/extensions/libxt_policy.c b/extensions/libxt_policy.c index 646d3330..16e8c535 100644 --- a/extensions/libxt_policy.c +++ b/extensions/libxt_policy.c @@ -347,7 +347,7 @@ static void print_mode(const char *prefix, uint8_t mode, int numeric) static void print_proto(const char *prefix, uint8_t proto, int numeric) { - struct protoent *p = NULL; + const struct protoent *p = NULL; printf(" %sproto ", prefix); if (!numeric) @@ -407,7 +407,7 @@ static void print_entry(const char *prefix, const struct xt_policy_elem *e, } } -static void print_flags(char *prefix, const struct xt_policy_info *info) +static void print_flags(const char *prefix, const struct xt_policy_info *info) { if (info->flags & XT_POLICY_MATCH_IN) printf(" %sdir in", prefix); diff --git a/extensions/libxt_rateest.c b/extensions/libxt_rateest.c index 6998c016..e70edc67 100644 --- a/extensions/libxt_rateest.c +++ b/extensions/libxt_rateest.c @@ -80,7 +80,7 @@ static const struct rate_suffix { { "GBps", 8000000000. }, { "TiBps", 8.*1024.*1024.*1024.*1024. }, { "TBps", 8000000000000. }, - XT_GETOPT_TABLEEND, + {NULL}, }; static int diff --git a/extensions/libxt_sctp.c b/extensions/libxt_sctp.c index d3379d30..5dbc36f5 100644 --- a/extensions/libxt_sctp.c +++ b/extensions/libxt_sctp.c @@ -298,10 +298,10 @@ sctp_parse(int c, char **argv, int invert, unsigned int *flags, return 1; } -static char * +static const char * port_to_service(int port) { - struct servent *service; + const struct servent *service; if ((service = getservbyport(htons(port), "sctp"))) return service->s_name; @@ -312,7 +312,7 @@ port_to_service(int port) static void print_port(uint16_t port, int numeric) { - char *service; + const char *service; if (numeric || (service = port_to_service(port)) == NULL) printf("%u", port); diff --git a/extensions/libxt_statistic.c b/extensions/libxt_statistic.c index b4171b11..12a83dd8 100644 --- a/extensions/libxt_statistic.c +++ b/extensions/libxt_statistic.c @@ -1,140 +1,111 @@ -#include <stdbool.h> +#include <math.h> #include <stdio.h> -#include <netdb.h> #include <string.h> -#include <stdlib.h> -#include <stddef.h> -#include <getopt.h> - #include <xtables.h> #include <linux/netfilter/xt_statistic.h> +enum { + O_MODE = 0, + O_PROBABILITY, + O_EVERY, + O_PACKET, + F_PROBABILITY = 1 << O_PROBABILITY, + F_EVERY = 1 << O_EVERY, + F_PACKET = 1 << O_PACKET, +}; + static void statistic_help(void) { printf( "statistic match options:\n" " --mode mode Match mode (random, nth)\n" " random mode:\n" -" --probability p Probability\n" +"[!] --probability p Probability\n" " nth mode:\n" -" --every n Match every nth packet\n" +"[!] --every n Match every nth packet\n" " --packet p Initial counter value (0 <= p <= n-1, default 0)\n"); } -static const struct option statistic_opts[] = { - {.name = "mode", .has_arg = true, .val = '1'}, - {.name = "probability", .has_arg = true, .val = '2'}, - {.name = "every", .has_arg = true, .val = '3'}, - {.name = "packet", .has_arg = true, .val = '4'}, - XT_GETOPT_TABLEEND, +#define s struct xt_statistic_info +static const struct xt_option_entry statistic_opts[] = { + {.name = "mode", .id = O_MODE, .type = XTTYPE_STRING, + .flags = XTOPT_MAND}, + {.name = "probability", .id = O_PROBABILITY, .type = XTTYPE_DOUBLE, + .flags = XTOPT_INVERT, .min = 0, .max = 1, + .excl = F_EVERY | F_PACKET}, + {.name = "every", .id = O_EVERY, .type = XTTYPE_UINT32, .min = 1, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, u.nth.every), + .excl = F_PROBABILITY, .also = F_PACKET}, + {.name = "packet", .id = O_PACKET, .type = XTTYPE_UINT32, + .flags = XTOPT_PUT, XTOPT_POINTER(s, u.nth.packet), + .excl = F_PROBABILITY, .also = F_EVERY}, + XTOPT_TABLEEND, }; +#undef s -static struct xt_statistic_info *global_info; - -static void statistic_mt_init(struct xt_entry_match *match) +static void statistic_parse(struct xt_option_call *cb) { - global_info = (void *)match->data; -} - -static int -statistic_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - struct xt_statistic_info *info = (void *)(*match)->data; - unsigned int val; - double prob; + struct xt_statistic_info *info = cb->data; - if (invert) + if (cb->invert) info->flags |= XT_STATISTIC_INVERT; - switch (c) { - case '1': - if (*flags & 0x1) - xtables_error(PARAMETER_PROBLEM, "double --mode"); - if (!strcmp(optarg, "random")) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_MODE: + if (strcmp(cb->arg, "random") == 0) info->mode = XT_STATISTIC_MODE_RANDOM; - else if (!strcmp(optarg, "nth")) + else if (strcmp(cb->arg, "nth") == 0) info->mode = XT_STATISTIC_MODE_NTH; else - xtables_error(PARAMETER_PROBLEM, "Bad mode \"%s\"", optarg); - *flags |= 0x1; - break; - case '2': - if (*flags & 0x2) - xtables_error(PARAMETER_PROBLEM, "double --probability"); - prob = atof(optarg); - if (prob < 0 || prob > 1) - xtables_error(PARAMETER_PROBLEM, - "--probability must be between 0 and 1"); - info->u.random.probability = 0x80000000 * prob; - *flags |= 0x2; + xtables_error(PARAMETER_PROBLEM, "Bad mode \"%s\"", + cb->arg); break; - case '3': - if (*flags & 0x4) - xtables_error(PARAMETER_PROBLEM, "double --every"); - if (!xtables_strtoui(optarg, NULL, &val, 0, UINT32_MAX)) - xtables_error(PARAMETER_PROBLEM, - "cannot parse --every `%s'", optarg); - info->u.nth.every = val; - if (info->u.nth.every == 0) - xtables_error(PARAMETER_PROBLEM, "--every cannot be 0"); - info->u.nth.every--; - *flags |= 0x4; + case O_PROBABILITY: + info->u.random.probability = lround(0x80000000 * cb->val.dbl); break; - case '4': - if (*flags & 0x8) - xtables_error(PARAMETER_PROBLEM, "double --packet"); - if (!xtables_strtoui(optarg, NULL, &val, 0, UINT32_MAX)) - xtables_error(PARAMETER_PROBLEM, - "cannot parse --packet `%s'", optarg); - info->u.nth.packet = val; - *flags |= 0x8; + case O_EVERY: + --info->u.nth.every; break; } - return 1; } -static void statistic_check(unsigned int flags) +static void statistic_check(struct xt_fcheck_call *cb) { - if (!(flags & 0x1)) - xtables_error(PARAMETER_PROBLEM, "no mode specified"); - if ((flags & 0x2) && (flags & (0x4 | 0x8))) - xtables_error(PARAMETER_PROBLEM, - "both nth and random parameters given"); - if (flags & 0x2 && global_info->mode != XT_STATISTIC_MODE_RANDOM) - xtables_error(PARAMETER_PROBLEM, - "--probability can only be used in random mode"); - if (flags & 0x4 && global_info->mode != XT_STATISTIC_MODE_NTH) - xtables_error(PARAMETER_PROBLEM, - "--every can only be used in nth mode"); - if (flags & 0x8 && global_info->mode != XT_STATISTIC_MODE_NTH) + struct xt_statistic_info *info = cb->data; + + if (info->mode == XT_STATISTIC_MODE_RANDOM && + !(cb->xflags & F_PROBABILITY)) xtables_error(PARAMETER_PROBLEM, - "--packet can only be used in nth mode"); - if ((flags & 0x8) && !(flags & 0x4)) + "--probability must be specified when using " + "random mode"); + if (info->mode == XT_STATISTIC_MODE_NTH && + !(cb->xflags & (F_EVERY | F_PACKET))) xtables_error(PARAMETER_PROBLEM, - "--packet can only be used with --every"); + "--every and --packet must be specified when " + "using nth mode"); + /* at this point, info->u.nth.every have been decreased. */ - if (global_info->u.nth.packet > global_info->u.nth.every) + if (info->u.nth.packet > info->u.nth.every) xtables_error(PARAMETER_PROBLEM, "the --packet p must be 0 <= p <= n-1"); - - global_info->u.nth.count = global_info->u.nth.every - - global_info->u.nth.packet; + info->u.nth.count = info->u.nth.every - info->u.nth.packet; } static void print_match(const struct xt_statistic_info *info, char *prefix) { - if (info->flags & XT_STATISTIC_INVERT) - printf(" !"); - switch (info->mode) { case XT_STATISTIC_MODE_RANDOM: - printf( "%smode random %sprobability %f", prefix, prefix, + printf(" %smode random%s %sprobability %.11f", prefix, + (info->flags & XT_STATISTIC_INVERT) ? " !" : "", + prefix, 1.0 * info->u.random.probability / 0x80000000); break; case XT_STATISTIC_MODE_NTH: - printf(" %smode nth %severy %u", prefix, prefix, + printf(" %smode nth%s %severy %u", prefix, + (info->flags & XT_STATISTIC_INVERT) ? " !" : "", + prefix, info->u.nth.every + 1); if (info->u.nth.packet) printf(" %spacket %u", prefix, info->u.nth.packet); @@ -164,13 +135,12 @@ static struct xtables_match statistic_match = { .version = XTABLES_VERSION, .size = XT_ALIGN(sizeof(struct xt_statistic_info)), .userspacesize = offsetof(struct xt_statistic_info, u.nth.count), - .init = statistic_mt_init, .help = statistic_help, - .parse = statistic_parse, - .final_check = statistic_check, + .x6_parse = statistic_parse, + .x6_fcheck = statistic_check, .print = statistic_print, .save = statistic_save, - .extra_opts = statistic_opts, + .x6_options = statistic_opts, }; void _init(void) diff --git a/extensions/libxt_statistic.man b/extensions/libxt_statistic.man index 8fc3b293..47182bfb 100644 --- a/extensions/libxt_statistic.man +++ b/extensions/libxt_statistic.man @@ -11,13 +11,12 @@ Set the matching mode of the matching rule, supported modes are and .B nth. .TP -\fB\-\-probability\fP \fIp\fP -Set the probability from 0 to 1 for a packet to be randomly -matched. It works only with the -.B random -mode. +[\fB!\fP] \fB\-\-probability\fP \fIp\fP +Set the probability for a packet to be randomly matched. It only works with the +\fBrandom\fP mode. \fIp\fP must be within 0.0 and 1.0. The supported +granularity is in 1/2147483648th increments. .TP -\fB\-\-every\fP \fIn\fP +[\fB!\fP] \fB\-\-every\fP \fIn\fP Match one packet every nth packet. It works only with the .B nth mode (see also the diff --git a/extensions/libxt_tcp.c b/extensions/libxt_tcp.c index d9bcbd0e..4d914e39 100644 --- a/extensions/libxt_tcp.c +++ b/extensions/libxt_tcp.c @@ -208,10 +208,10 @@ tcp_parse(int c, char **argv, int invert, unsigned int *flags, return 1; } -static char * +static const char * port_to_service(int port) { - struct servent *service; + const struct servent *service; if ((service = getservbyport(htons(port), "tcp"))) return service->s_name; @@ -222,7 +222,7 @@ port_to_service(int port) static void print_port(uint16_t port, int numeric) { - char *service; + const char *service; if (numeric || (service = port_to_service(port)) == NULL) printf("%u", port); diff --git a/extensions/libxt_tos.c b/extensions/libxt_tos.c index 7646a4f3..81c096f9 100644 --- a/extensions/libxt_tos.c +++ b/extensions/libxt_tos.c @@ -26,13 +26,13 @@ enum { static const struct xt_option_entry tos_mt_opts_v0[] = { {.name = "tos", .id = O_TOS, .type = XTTYPE_TOSMASK, - .flags = XTOPT_MAND, .max = 0xFF}, + .flags = XTOPT_INVERT | XTOPT_MAND, .max = 0xFF}, XTOPT_TABLEEND, }; static const struct xt_option_entry tos_mt_opts[] = { {.name = "tos", .id = O_TOS, .type = XTTYPE_TOSMASK, - .flags = XTOPT_MAND, .max = 0x3F}, + .flags = XTOPT_INVERT | XTOPT_MAND, .max = 0x3F}, XTOPT_TABLEEND, }; diff --git a/extensions/libxt_u32.c b/extensions/libxt_u32.c index 0df28a84..9198edca 100644 --- a/extensions/libxt_u32.c +++ b/extensions/libxt_u32.c @@ -111,6 +111,7 @@ static void u32_parse(struct xt_option_call *cb) const char *start = cb->arg; int state = 0; + xtables_option_parse(cb); data->invert = cb->invert; /* diff --git a/extensions/libxt_udp.c b/extensions/libxt_udp.c index d4930725..b9f39ee4 100644 --- a/extensions/libxt_udp.c +++ b/extensions/libxt_udp.c @@ -60,10 +60,10 @@ static void udp_parse(struct xt_option_call *cb) } } -static char * +static const char * port_to_service(int port) { - struct servent *service; + const struct servent *service; if ((service = getservbyport(htons(port), "udp"))) return service->s_name; @@ -74,7 +74,7 @@ port_to_service(int port) static void print_port(uint16_t port, int numeric) { - char *service; + const char *service; if (numeric || (service = port_to_service(port)) == NULL) printf("%u", port); diff --git a/include/xtables.h.in b/include/xtables.h.in index 5563ecb9..eb088b6b 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -49,6 +49,7 @@ struct in_addr; * %XTTYPE_NONE: option takes no argument * %XTTYPE_UINT*: standard integer * %XTTYPE_UINT*RC: colon-separated range of standard integers + * %XTTYPE_DOUBLE: double-precision floating point number * %XTTYPE_STRING: arbitrary string * %XTTYPE_TOSMASK: 8-bit TOS value with optional mask * %XTTYPE_MARKMASK32: 32-bit mark with optional mask @@ -69,6 +70,7 @@ enum xt_option_type { XTTYPE_UINT16RC, XTTYPE_UINT32RC, XTTYPE_UINT64RC, + XTTYPE_DOUBLE, XTTYPE_STRING, XTTYPE_TOSMASK, XTTYPE_MARKMASK32, @@ -136,6 +138,7 @@ struct xt_option_call { uint16_t u16, u16_range[2], port, port_range[2]; uint32_t u32, u32_range[2]; uint64_t u64, u64_range[2]; + double dbl; union nf_inet_addr inetaddr; struct { uint8_t tos_value, tos_mask; @@ -346,7 +349,7 @@ struct xtables_globals void (*exit_err)(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); }; -#define XT_GETOPT_TABLEEND {NULL} +#define XT_GETOPT_TABLEEND {.name = NULL, .has_arg = false} #ifdef __cplusplus extern "C" { @@ -742,10 +742,10 @@ static int compatible_revision(const char *name, uint8_t revision, int opt) if (errno == EPERM) { /* revision 0 is always supported. */ if (revision != 0) - fprintf(stderr, "Could not determine whether " + fprintf(stderr, "%s: Could not determine whether " "revision %u is supported, " "assuming it is.\n", - revision); + name, revision); return 1; } fprintf(stderr, "Could not open socket to kernel: %s\n", diff --git a/xtoptions.c b/xtoptions.c index 5b1df889..86498a97 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -144,6 +144,29 @@ static void xtopt_parse_int(struct xt_option_call *cb) } /** + * Require a simple floating point number. + */ +static void xtopt_parse_float(struct xt_option_call *cb) +{ + const struct xt_option_entry *entry = cb->entry; + double value; + char *end; + + value = strtod(cb->arg, &end); + if (end == cb->arg || *end != '\0' || + (entry->min != entry->max && + (value < entry->min || value > entry->max))) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: bad value for option \"--%s\", " + "or out of range (%u-%u).\n", + cb->ext_name, entry->name, entry->min, entry->max); + + cb->val.dbl = value; + if (entry->flags & XTOPT_PUT) + *(double *)XTOPT_MKPTR(cb) = cb->val.dbl; +} + +/** * Multiple integer parse routine. * * This function is capable of parsing any number of fields. Only the first @@ -190,7 +213,6 @@ static void xtopt_parse_mint(struct xt_option_call *cb) xt_params->exit_err(PARAMETER_PROBLEM, "%s: Argument to \"--%s\" has unexpected " "characters.\n", cb->ext_name, entry->name); - ++cb->nvals; if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) { if (entry->type == XTTYPE_UINT8RC) cb->val.u8_range[cb->nvals] = value; @@ -201,6 +223,7 @@ static void xtopt_parse_mint(struct xt_option_call *cb) else if (entry->type == XTTYPE_UINT64RC) cb->val.u64_range[cb->nvals] = value; } + ++cb->nvals; if (entry->flags & XTOPT_PUT) { if (entry->type == XTTYPE_UINT8RC) *(uint8_t *)put = value; @@ -547,6 +570,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT16RC] = xtopt_parse_mint, [XTTYPE_UINT32RC] = xtopt_parse_mint, [XTTYPE_UINT64RC] = xtopt_parse_mint, + [XTTYPE_DOUBLE] = xtopt_parse_float, [XTTYPE_STRING] = xtopt_parse_string, [XTTYPE_TOSMASK] = xtopt_parse_tosmask, [XTTYPE_MARKMASK32] = xtopt_parse_markmask, @@ -567,6 +591,7 @@ static const size_t xtopt_psize[] = { [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), + [XTTYPE_DOUBLE] = sizeof(double), [XTTYPE_STRING] = -1, [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), [XTTYPE_ONEHOST] = sizeof(union nf_inet_addr), |