summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/libip6t_ipv6header.c6
-rw-r--r--extensions/libip6t_rt.c4
-rw-r--r--extensions/libxt_IDLETIMER.c70
-rw-r--r--extensions/libxt_NFLOG.c98
-rw-r--r--extensions/libxt_TCPOPTSTRIP.c2
-rw-r--r--extensions/libxt_dccp.c6
-rw-r--r--extensions/libxt_multiport.c10
-rw-r--r--extensions/libxt_owner.c20
-rw-r--r--extensions/libxt_policy.c4
-rw-r--r--extensions/libxt_rateest.c2
-rw-r--r--extensions/libxt_sctp.c6
-rw-r--r--extensions/libxt_statistic.c160
-rw-r--r--extensions/libxt_statistic.man11
-rw-r--r--extensions/libxt_tcp.c6
-rw-r--r--extensions/libxt_tos.c4
-rw-r--r--extensions/libxt_u32.c1
-rw-r--r--extensions/libxt_udp.c6
-rw-r--r--include/xtables.h.in5
-rw-r--r--xtables.c4
-rw-r--r--xtoptions.c27
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" {
diff --git a/xtables.c b/xtables.c
index fab1d79d..9038f892 100644
--- a/xtables.c
+++ b/xtables.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),