summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/libip6t_LOG.c174
-rw-r--r--extensions/libipt_LOG.c174
-rw-r--r--extensions/libipt_ULOG.c137
-rw-r--r--extensions/libipt_realm.c202
-rw-r--r--extensions/libxt_CONNMARK.c271
-rw-r--r--extensions/libxt_CT.c74
-rw-r--r--extensions/libxt_MARK.c202
-rw-r--r--extensions/libxt_NFQUEUE.c139
-rw-r--r--extensions/libxt_TCPMSS.c96
-rw-r--r--extensions/libxt_TPROXY.c216
-rw-r--r--extensions/libxt_connbytes.c107
-rw-r--r--extensions/libxt_connmark.c98
-rw-r--r--extensions/libxt_devgroup.c201
-rw-r--r--extensions/libxt_length.c92
-rw-r--r--extensions/libxt_mark.c95
-rw-r--r--extensions/libxt_quota.c67
-rw-r--r--extensions/libxt_string.c138
-rw-r--r--extensions/libxt_tcpmss.c92
-rw-r--r--include/xtables.h.in42
-rw-r--r--xtoptions.c352
20 files changed, 1127 insertions, 1842 deletions
diff --git a/extensions/libip6t_LOG.c b/extensions/libip6t_LOG.c
index e9c738f1..a419ec91 100644
--- a/extensions/libip6t_LOG.c
+++ b/extensions/libip6t_LOG.c
@@ -1,11 +1,6 @@
-/* Shared library add-on to ip6tables to add LOG support. */
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
-#include <stdlib.h>
#include <syslog.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_ipv6/ip6t_LOG.h>
@@ -17,6 +12,16 @@
#define LOG_DEFAULT_LEVEL LOG_WARNING
+enum {
+ O_LOG_LEVEL = 0,
+ O_LOG_PREFIX,
+ O_LOG_TCPSEQ,
+ O_LOG_TCPOPTS,
+ O_LOG_IPOPTS,
+ O_LOG_UID,
+ O_LOG_MAC,
+};
+
static void LOG_help(void)
{
printf(
@@ -30,16 +35,20 @@ static void LOG_help(void)
" --log-macdecode Decode MAC addresses and protocol.\n");
}
-static const struct option LOG_opts[] = {
- {.name = "log-level", .has_arg = true, .val = '!'},
- {.name = "log-prefix", .has_arg = true, .val = '#'},
- {.name = "log-tcp-sequence", .has_arg = false, .val = '1'},
- {.name = "log-tcp-options", .has_arg = false, .val = '2'},
- {.name = "log-ip-options", .has_arg = false, .val = '3'},
- {.name = "log-uid", .has_arg = false, .val = '4'},
- {.name = "log-macdecode", .has_arg = false, .val = '5'},
- XT_GETOPT_TABLEEND,
+#define s struct ip6t_log_info
+static const struct xt_option_entry LOG_opts[] = {
+ {.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
+ {.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1},
+ {.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE},
+ {.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE},
+ {.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE},
+ {.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE},
+ {.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
+#undef s
static void LOG_init(struct xt_entry_target *t)
{
@@ -66,134 +75,33 @@ static const struct ip6t_log_names ip6t_log_names[]
{ .name = "warning", .level = LOG_WARNING }
};
-static uint8_t
-parse_level(const char *level)
+static void LOG_parse(struct xt_option_call *cb)
{
- unsigned int lev = -1;
- unsigned int set = 0;
-
- if (!xtables_strtoui(level, NULL, &lev, 0, 7)) {
- unsigned int i = 0;
-
- for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i)
- if (strncasecmp(level, ip6t_log_names[i].name,
- strlen(level)) == 0) {
- if (set++)
- xtables_error(PARAMETER_PROBLEM,
- "log-level `%s' ambiguous",
- level);
- lev = ip6t_log_names[i].level;
- }
+ struct ip6t_log_info *info = cb->data;
- if (!set)
- xtables_error(PARAMETER_PROBLEM,
- "log-level `%s' unknown", level);
- }
-
- return lev;
-}
-
-#define IP6T_LOG_OPT_LEVEL 0x01
-#define IP6T_LOG_OPT_PREFIX 0x02
-#define IP6T_LOG_OPT_TCPSEQ 0x04
-#define IP6T_LOG_OPT_TCPOPT 0x08
-#define IP6T_LOG_OPT_IPOPT 0x10
-#define IP6T_LOG_OPT_UID 0x20
-#define IP6T_LOG_OPT_MACDECODE 0x40
-
-static int LOG_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct ip6t_log_info *loginfo = (struct ip6t_log_info *)(*target)->data;
-
- switch (c) {
- case '!':
- if (*flags & IP6T_LOG_OPT_LEVEL)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-level twice");
-
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --log-level");
-
- loginfo->level = parse_level(optarg);
- *flags |= IP6T_LOG_OPT_LEVEL;
- break;
-
- case '#':
- if (*flags & IP6T_LOG_OPT_PREFIX)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-prefix twice");
-
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --log-prefix");
-
- if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
- xtables_error(PARAMETER_PROBLEM,
- "Maximum prefix length %u for --log-prefix",
- (unsigned int)sizeof(loginfo->prefix) - 1);
-
- if (strlen(optarg) == 0)
- xtables_error(PARAMETER_PROBLEM,
- "No prefix specified for --log-prefix");
-
- if (strlen(optarg) != strlen(strtok(optarg, "\n")))
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_LOG_PREFIX:
+ if (strchr(cb->arg, '\n') != NULL)
xtables_error(PARAMETER_PROBLEM,
"Newlines not allowed in --log-prefix");
-
- strcpy(loginfo->prefix, optarg);
- *flags |= IP6T_LOG_OPT_PREFIX;
break;
-
- case '1':
- if (*flags & IP6T_LOG_OPT_TCPSEQ)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-tcp-sequence "
- "twice");
-
- loginfo->logflags |= IP6T_LOG_TCPSEQ;
- *flags |= IP6T_LOG_OPT_TCPSEQ;
+ case O_LOG_TCPSEQ:
+ info->logflags = IP6T_LOG_TCPSEQ;
break;
-
- case '2':
- if (*flags & IP6T_LOG_OPT_TCPOPT)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-tcp-options twice");
-
- loginfo->logflags |= IP6T_LOG_TCPOPT;
- *flags |= IP6T_LOG_OPT_TCPOPT;
+ case O_LOG_TCPOPTS:
+ info->logflags = IP6T_LOG_TCPOPT;
break;
-
- case '3':
- if (*flags & IP6T_LOG_OPT_IPOPT)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-ip-options twice");
-
- loginfo->logflags |= IP6T_LOG_IPOPT;
- *flags |= IP6T_LOG_OPT_IPOPT;
+ case O_LOG_IPOPTS:
+ info->logflags = IP6T_LOG_IPOPT;
break;
-
- case '4':
- if (*flags & IP6T_LOG_OPT_UID)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-uid twice");
-
- loginfo->logflags |= IP6T_LOG_UID;
- *flags |= IP6T_LOG_OPT_UID;
+ case O_LOG_UID:
+ info->logflags = IP6T_LOG_UID;
break;
-
- case '5':
- if (*flags & IP6T_LOG_OPT_MACDECODE)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-macdecode twice");
-
- loginfo->logflags |= IP6T_LOG_MACDECODE;
- *flags |= IP6T_LOG_OPT_MACDECODE;
+ case O_LOG_MAC:
+ info->logflags = IP6T_LOG_MACDECODE;
break;
}
-
- return 1;
}
static void LOG_print(const void *ip, const struct xt_entry_target *target,
@@ -264,10 +172,10 @@ static struct xtables_target log_tg6_reg = {
.userspacesize = XT_ALIGN(sizeof(struct ip6t_log_info)),
.help = LOG_help,
.init = LOG_init,
- .parse = LOG_parse,
.print = LOG_print,
.save = LOG_save,
- .extra_opts = LOG_opts,
+ .x6_parse = LOG_parse,
+ .x6_options = LOG_opts,
};
void _init(void)
diff --git a/extensions/libipt_LOG.c b/extensions/libipt_LOG.c
index ba6af044..b270bcf6 100644
--- a/extensions/libipt_LOG.c
+++ b/extensions/libipt_LOG.c
@@ -1,11 +1,6 @@
-/* Shared library add-on to iptables to add LOG support. */
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
-#include <stdlib.h>
#include <syslog.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_ipv4/ipt_LOG.h>
@@ -17,6 +12,16 @@
#define IPT_LOG_MASK 0x0f
#endif
+enum {
+ O_LOG_LEVEL = 0,
+ O_LOG_PREFIX,
+ O_LOG_TCPSEQ,
+ O_LOG_TCPOPTS,
+ O_LOG_IPOPTS,
+ O_LOG_UID,
+ O_LOG_MAC,
+};
+
static void LOG_help(void)
{
printf(
@@ -30,16 +35,20 @@ static void LOG_help(void)
" --log-macdecode Decode MAC addresses and protocol.\n\n");
}
-static const struct option LOG_opts[] = {
- {.name = "log-level", .has_arg = true, .val = '!'},
- {.name = "log-prefix", .has_arg = true, .val = '#'},
- {.name = "log-tcp-sequence", .has_arg = false, .val = '1'},
- {.name = "log-tcp-options", .has_arg = false, .val = '2'},
- {.name = "log-ip-options", .has_arg = false, .val = '3'},
- {.name = "log-uid", .has_arg = false, .val = '4'},
- {.name = "log-macdecode", .has_arg = false, .val = '5'},
- XT_GETOPT_TABLEEND,
+#define s struct ipt_log_info
+static const struct xt_option_entry LOG_opts[] = {
+ {.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
+ {.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1},
+ {.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE},
+ {.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE},
+ {.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE},
+ {.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE},
+ {.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
+#undef s
static void LOG_init(struct xt_entry_target *t)
{
@@ -66,134 +75,33 @@ static const struct ipt_log_names ipt_log_names[]
{ .name = "warning", .level = LOG_WARNING }
};
-static uint8_t
-parse_level(const char *level)
+static void LOG_parse(struct xt_option_call *cb)
{
- unsigned int lev = -1;
- unsigned int set = 0;
-
- if (!xtables_strtoui(level, NULL, &lev, 0, 7)) {
- unsigned int i = 0;
-
- for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i)
- if (strncasecmp(level, ipt_log_names[i].name,
- strlen(level)) == 0) {
- if (set++)
- xtables_error(PARAMETER_PROBLEM,
- "log-level `%s' ambiguous",
- level);
- lev = ipt_log_names[i].level;
- }
+ struct ipt_log_info *info = cb->data;
- if (!set)
- xtables_error(PARAMETER_PROBLEM,
- "log-level `%s' unknown", level);
- }
-
- return lev;
-}
-
-#define IPT_LOG_OPT_LEVEL 0x01
-#define IPT_LOG_OPT_PREFIX 0x02
-#define IPT_LOG_OPT_TCPSEQ 0x04
-#define IPT_LOG_OPT_TCPOPT 0x08
-#define IPT_LOG_OPT_IPOPT 0x10
-#define IPT_LOG_OPT_UID 0x20
-#define IPT_LOG_OPT_MACDECODE 0x40
-
-static int LOG_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct ipt_log_info *loginfo = (struct ipt_log_info *)(*target)->data;
-
- switch (c) {
- case '!':
- if (*flags & IPT_LOG_OPT_LEVEL)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-level twice");
-
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --log-level");
-
- loginfo->level = parse_level(optarg);
- *flags |= IPT_LOG_OPT_LEVEL;
- break;
-
- case '#':
- if (*flags & IPT_LOG_OPT_PREFIX)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-prefix twice");
-
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --log-prefix");
-
- if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
- xtables_error(PARAMETER_PROBLEM,
- "Maximum prefix length %u for --log-prefix",
- (unsigned int)sizeof(loginfo->prefix) - 1);
-
- if (strlen(optarg) == 0)
- xtables_error(PARAMETER_PROBLEM,
- "No prefix specified for --log-prefix");
-
- if (strlen(optarg) != strlen(strtok(optarg, "\n")))
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_LOG_PREFIX:
+ if (strchr(cb->arg, '\n') != NULL)
xtables_error(PARAMETER_PROBLEM,
"Newlines not allowed in --log-prefix");
-
- strcpy(loginfo->prefix, optarg);
- *flags |= IPT_LOG_OPT_PREFIX;
break;
-
- case '1':
- if (*flags & IPT_LOG_OPT_TCPSEQ)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-tcp-sequence "
- "twice");
-
- loginfo->logflags |= IPT_LOG_TCPSEQ;
- *flags |= IPT_LOG_OPT_TCPSEQ;
+ case O_LOG_TCPSEQ:
+ info->logflags = IPT_LOG_TCPSEQ;
break;
-
- case '2':
- if (*flags & IPT_LOG_OPT_TCPOPT)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-tcp-options twice");
-
- loginfo->logflags |= IPT_LOG_TCPOPT;
- *flags |= IPT_LOG_OPT_TCPOPT;
+ case O_LOG_TCPOPTS:
+ info->logflags = IPT_LOG_TCPOPT;
break;
-
- case '3':
- if (*flags & IPT_LOG_OPT_IPOPT)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-ip-options twice");
-
- loginfo->logflags |= IPT_LOG_IPOPT;
- *flags |= IPT_LOG_OPT_IPOPT;
+ case O_LOG_IPOPTS:
+ info->logflags = IPT_LOG_IPOPT;
break;
-
- case '4':
- if (*flags & IPT_LOG_OPT_UID)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --log-uid twice");
-
- loginfo->logflags |= IPT_LOG_UID;
- *flags |= IPT_LOG_OPT_UID;
+ case O_LOG_UID:
+ info->logflags = IPT_LOG_UID;
break;
-
- case '5':
- if (*flags & IPT_LOG_OPT_MACDECODE)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specifiy --log-macdecode twice");
-
- loginfo->logflags |= IPT_LOG_MACDECODE;
- *flags |= IPT_LOG_OPT_MACDECODE;
+ case O_LOG_MAC:
+ info->logflags = IPT_LOG_MACDECODE;
break;
}
-
- return 1;
}
static void LOG_print(const void *ip, const struct xt_entry_target *target,
@@ -266,10 +174,10 @@ static struct xtables_target log_tg_reg = {
.userspacesize = XT_ALIGN(sizeof(struct ipt_log_info)),
.help = LOG_help,
.init = LOG_init,
- .parse = LOG_parse,
.print = LOG_print,
.save = LOG_save,
- .extra_opts = LOG_opts,
+ .x6_parse = LOG_parse,
+ .x6_options = LOG_opts,
};
void _init(void)
diff --git a/extensions/libipt_ULOG.c b/extensions/libipt_ULOG.c
index 8eeccf00..e08ae056 100644
--- a/extensions/libipt_ULOG.c
+++ b/extensions/libipt_ULOG.c
@@ -9,29 +9,18 @@
*
* libipt_ULOG.c,v 1.7 2001/01/30 11:55:02 laforge Exp
*/
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
#include <xtables.h>
/* For 64bit kernel / 32bit userspace */
#include <linux/netfilter_ipv4/ipt_ULOG.h>
-
-static void print_groups(unsigned int gmask)
-{
- int b;
- unsigned int test;
-
- for (b = 31; b >= 0; b--) {
- test = (1 << b);
- if (gmask & test)
- printf(" %d", b + 1);
- }
-}
+enum {
+ O_ULOG_NLGROUP = 0,
+ O_ULOG_PREFIX,
+ O_ULOG_CPRANGE,
+ O_ULOG_QTHR,
+};
static void ULOG_help(void)
{
@@ -42,12 +31,16 @@ static void ULOG_help(void)
" --ulog-prefix prefix Prefix log messages with this prefix.\n");
}
-static const struct option ULOG_opts[] = {
- {.name = "ulog-nlgroup", .has_arg = true, .val = '!'},
- {.name = "ulog-prefix", .has_arg = true, .val = '#'},
- {.name = "ulog-cprange", .has_arg = true, .val = 'A'},
- {.name = "ulog-qthreshold", .has_arg = true, .val = 'B'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry ULOG_opts[] = {
+ {.name = "ulog-nlgroup", .id = O_ULOG_NLGROUP, .type = XTTYPE_UINT8,
+ .min = 1, .max = 32},
+ {.name = "ulog-prefix", .id = O_ULOG_PREFIX, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ipt_ulog_info, prefix),
+ .min = 1},
+ {.name = "ulog-cprange", .id = O_ULOG_CPRANGE, .type = XTTYPE_UINT64,
+ .min = 1, .max = ULOG_MAX_QLEN},
+ {.name = "ulog-qthreshold", .id = O_ULOG_QTHR, .type = XTTYPE_UINT64},
+ XTOPT_TABLEEND,
};
static void ULOG_init(struct xt_entry_target *t)
@@ -59,87 +52,27 @@ static void ULOG_init(struct xt_entry_target *t)
}
-#define IPT_LOG_OPT_NLGROUP 0x01
-#define IPT_LOG_OPT_PREFIX 0x02
-#define IPT_LOG_OPT_CPRANGE 0x04
-#define IPT_LOG_OPT_QTHRESHOLD 0x08
-
-static int ULOG_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void ULOG_parse(struct xt_option_call *cb)
{
- struct ipt_ulog_info *loginfo =
- (struct ipt_ulog_info *) (*target)->data;
- int group_d;
+ struct ipt_ulog_info *loginfo = cb->data;
- switch (c) {
- case '!':
- if (*flags & IPT_LOG_OPT_NLGROUP)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --ulog-nlgroup twice");
-
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --ulog-nlgroup");
- group_d = atoi(optarg);
- if (group_d > 32 || group_d < 1)
- xtables_error(PARAMETER_PROBLEM,
- "--ulog-nlgroup has to be between 1 and 32");
-
- loginfo->nl_group = (1 << (group_d - 1));
-
- *flags |= IPT_LOG_OPT_NLGROUP;
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_ULOG_NLGROUP:
+ loginfo->nl_group = 1 << (cb->val.u8 - 1);
break;
-
- case '#':
- if (*flags & IPT_LOG_OPT_PREFIX)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --ulog-prefix twice");
-
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --ulog-prefix");
-
- if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
- xtables_error(PARAMETER_PROBLEM,
- "Maximum prefix length %u for --ulog-prefix",
- (unsigned int)sizeof(loginfo->prefix) - 1);
-
- if (strlen(optarg) == 0)
- xtables_error(PARAMETER_PROBLEM,
- "No prefix specified for --ulog-prefix");
-
- if (strlen(optarg) != strlen(strtok(optarg, "\n")))
+ case O_ULOG_PREFIX:
+ if (strchr(cb->arg, '\n') != NULL)
xtables_error(PARAMETER_PROBLEM,
"Newlines not allowed in --ulog-prefix");
-
- strcpy(loginfo->prefix, optarg);
- *flags |= IPT_LOG_OPT_PREFIX;
break;
- case 'A':
- if (*flags & IPT_LOG_OPT_CPRANGE)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --ulog-cprange twice");
- if (atoi(optarg) < 0)
- xtables_error(PARAMETER_PROBLEM,
- "Negative copy range?");
- loginfo->copy_range = atoi(optarg);
- *flags |= IPT_LOG_OPT_CPRANGE;
+ case O_ULOG_CPRANGE:
+ loginfo->copy_range = cb->val.u64;
break;
- case 'B':
- if (*flags & IPT_LOG_OPT_QTHRESHOLD)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --ulog-qthreshold twice");
- if (atoi(optarg) < 1)
- xtables_error(PARAMETER_PROBLEM,
- "Negative or zero queue threshold ?");
- if (atoi(optarg) > ULOG_MAX_QLEN)
- xtables_error(PARAMETER_PROBLEM,
- "Maximum queue length exceeded");
- loginfo->qthreshold = atoi(optarg);
- *flags |= IPT_LOG_OPT_QTHRESHOLD;
+ case O_ULOG_QTHR:
+ loginfo->qthreshold = cb->val.u64;
break;
}
- return 1;
}
static void ULOG_save(const void *ip, const struct xt_entry_target *target)
@@ -152,10 +85,8 @@ static void ULOG_save(const void *ip, const struct xt_entry_target *target)
xtables_save_string(loginfo->prefix);
}
- if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) {
- printf(" --ulog-nlgroup");
- print_groups(loginfo->nl_group);
- }
+ if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP)
+ printf(" --ulog-nlgroup %d", ffs(loginfo->nl_group));
if (loginfo->copy_range)
printf(" --ulog-cprange %u", (unsigned int)loginfo->copy_range);
@@ -170,8 +101,8 @@ static void ULOG_print(const void *ip, const struct xt_entry_target *target,
= (const struct ipt_ulog_info *) target->data;
printf(" ULOG ");
- printf("copy_range %u nlgroup", (unsigned int)loginfo->copy_range);
- print_groups(loginfo->nl_group);
+ printf("copy_range %u nlgroup %d", (unsigned int)loginfo->copy_range,
+ ffs(loginfo->nl_group));
if (strcmp(loginfo->prefix, "") != 0)
printf(" prefix \"%s\"", loginfo->prefix);
printf(" queue_threshold %u", (unsigned int)loginfo->qthreshold);
@@ -185,10 +116,10 @@ static struct xtables_target ulog_tg_reg = {
.userspacesize = XT_ALIGN(sizeof(struct ipt_ulog_info)),
.help = ULOG_help,
.init = ULOG_init,
- .parse = ULOG_parse,
.print = ULOG_print,
.save = ULOG_save,
- .extra_opts = ULOG_opts,
+ .x6_parse = ULOG_parse,
+ .x6_options = ULOG_opts,
};
void _init(void)
diff --git a/extensions/libipt_realm.c b/extensions/libipt_realm.c
index 17b1754e..b60c57ee 100644
--- a/extensions/libipt_realm.c
+++ b/extensions/libipt_realm.c
@@ -1,12 +1,7 @@
-/* Shared library add-on to iptables to add realm matching support. */
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
-#include <ctype.h>
-#include <getopt.h>
#if defined(__GLIBC__) && __GLIBC__ == 2
#include <net/ethernet.h>
#else
@@ -15,6 +10,10 @@
#include <xtables.h>
#include <linux/netfilter_ipv4/ipt_realm.h>
+enum {
+ O_REALM = 0,
+};
+
static void realm_help(void)
{
printf(
@@ -23,165 +22,49 @@ static void realm_help(void)
" Match realm\n");
}
-static const struct option realm_opts[] = {
- {.name = "realm", .has_arg = true, .val = '1'},
- XT_GETOPT_TABLEEND,
-};
-
-struct realmname {
- int id;
- char* name;
- int len;
- struct realmname* next;
+static const struct xt_option_entry realm_opts[] = {
+ {.name = "realm", .id = O_REALM, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND | XTOPT_INVERT},
+ XTOPT_TABLEEND,
};
/* array of realms from /etc/iproute2/rt_realms */
-static struct realmname *realms;
-/* 1 if loading failed */
-static int rdberr;
+static struct xtables_lmap *realms;
-static void load_realms(void)
+static void realm_init(struct xt_entry_match *m)
{
- const char* rfnm = "/etc/iproute2/rt_realms";
- char buf[512];
- FILE *fil;
- char *cur, *nxt;
- int id;
- struct realmname *oldnm = NULL, *newnm = NULL;
-
- fil = fopen(rfnm, "re");
- if (!fil) {
- rdberr = 1;
- return;
- }
-
- while (fgets(buf, sizeof(buf), fil)) {
- cur = buf;
- while ((*cur == ' ') || (*cur == '\t'))
- cur++;
- if ((*cur == '#') || (*cur == '\n') || (*cur == 0))
- continue;
-
- /* iproute2 allows hex and dec format */
- errno = 0;
- id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) ? 10 : 16);
- if ((nxt == cur) || errno)
- continue;
-
- /* same boundaries as in iproute2 */
- if (id < 0 || id > 255)
- continue;
- cur = nxt;
-
- if (!isspace(*cur))
- continue;
- while ((*cur == ' ') || (*cur == '\t'))
- cur++;
- if ((*cur == '#') || (*cur == '\n') || (*cur == 0))
- continue;
- nxt = cur;
- while ((*nxt != 0) && !isspace(*nxt))
- nxt++;
- if (nxt == cur)
- continue;
-
- /* found valid data */
- newnm = malloc(sizeof(struct realmname));
- if (newnm == NULL) {
- perror("libipt_realm: malloc failed");
- exit(1);
- }
- newnm->id = id;
- newnm->len = nxt - cur;
- newnm->name = malloc(newnm->len + 1);
- if (newnm->name == NULL) {
- perror("libipt_realm: malloc failed");
- exit(1);
- }
- strncpy(newnm->name, cur, newnm->len);
- newnm->name[newnm->len] = 0;
- newnm->next = NULL;
-
- if (oldnm)
- oldnm->next = newnm;
- else
- realms = newnm;
- oldnm = newnm;
- }
-
- fclose(fil);
+ const char file[] = "/etc/iproute2/rt_realms";
+ realms = xtables_lmap_init(file);
+ if (realms == NULL && errno != ENOENT)
+ fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno));
}
-/* get realm id for name, -1 if error/not found */
-static int realm_name2id(const char* name)
+static void realm_parse(struct xt_option_call *cb)
{
- struct realmname* cur;
-
- if ((realms == NULL) && (rdberr == 0))
- load_realms();
- cur = realms;
- if (cur == NULL)
- return -1;
- while (cur) {
- if (!strncmp(name, cur->name, cur->len + 1))
- return cur->id;
- cur = cur->next;
- }
- return -1;
-}
-
-/* get realm name for id, NULL if error/not found */
-static const char *realm_id2name(int id)
-{
- struct realmname* cur;
-
- if ((realms == NULL) && (rdberr == 0))
- load_realms();
- cur = realms;
- if (cur == NULL)
- return NULL;
- while (cur) {
- if (id == cur->id)
- return cur->name;
- cur = cur->next;
- }
- return NULL;
-}
-
-static int realm_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- struct ipt_realm_info *realminfo = (struct ipt_realm_info *)(*match)->data;
+ struct ipt_realm_info *realminfo = cb->data;
int id;
+ char *end;
- switch (c) {
- char *end;
- case '1':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- end = optarg = optarg;
- realminfo->id = strtoul(optarg, &end, 0);
- if (end != optarg && (*end == '/' || *end == '\0')) {
- if (*end == '/')
- realminfo->mask = strtoul(end+1, &end, 0);
- else
- realminfo->mask = 0xffffffff;
- if (*end != '\0' || end == optarg)
- xtables_error(PARAMETER_PROBLEM,
- "Bad realm value `%s'", optarg);
- } else {
- id = realm_name2id(optarg);
- if (id == -1)
- xtables_error(PARAMETER_PROBLEM,
- "Realm `%s' not found", optarg);
- realminfo->id = id;
+ xtables_option_parse(cb);
+ realminfo->id = strtoul(cb->arg, &end, 0);
+ if (end != cb->arg && (*end == '/' || *end == '\0')) {
+ if (*end == '/')
+ realminfo->mask = strtoul(end+1, &end, 0);
+ else
realminfo->mask = 0xffffffff;
- }
- if (invert)
- realminfo->invert = 1;
- *flags = 1;
- break;
+ if (*end != '\0' || end == cb->arg)
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad realm value \"%s\"", cb->arg);
+ } else {
+ id = xtables_lmap_name2id(realms, cb->arg);
+ if (id == -1)
+ xtables_error(PARAMETER_PROBLEM,
+ "Realm \"%s\" not found", cb->arg);
+ realminfo->id = id;
+ realminfo->mask = 0xffffffff;
}
- return 1;
+ if (cb->invert)
+ realminfo->invert = 1;
}
static void
@@ -193,7 +76,7 @@ print_realm(unsigned long id, unsigned long mask, int numeric)
printf(" 0x%lx/0x%lx", id, mask);
else {
if (numeric == 0)
- name = realm_id2name(id);
+ name = xtables_lmap_id2name(realms, id);
if (name)
printf(" %s", name);
else
@@ -224,13 +107,6 @@ static void realm_save(const void *ip, const struct xt_entry_match *match)
print_realm(ri->id, ri->mask, 0);
}
-static void realm_check(unsigned int flags)
-{
- if (!flags)
- xtables_error(PARAMETER_PROBLEM,
- "realm match: You must specify `--realm'");
-}
-
static struct xtables_match realm_mt_reg = {
.name = "realm",
.version = XTABLES_VERSION,
@@ -238,11 +114,11 @@ static struct xtables_match realm_mt_reg = {
.size = XT_ALIGN(sizeof(struct ipt_realm_info)),
.userspacesize = XT_ALIGN(sizeof(struct ipt_realm_info)),
.help = realm_help,
- .parse = realm_parse,
- .final_check = realm_check,
+ .init = realm_init,
.print = realm_print,
.save = realm_save,
- .extra_opts = realm_opts,
+ .x6_parse = realm_parse,
+ .x6_options = realm_opts,
};
void _init(void)
diff --git a/extensions/libxt_CONNMARK.c b/extensions/libxt_CONNMARK.c
index dbb9dc50..5d5351e3 100644
--- a/extensions/libxt_CONNMARK.c
+++ b/extensions/libxt_CONNMARK.c
@@ -20,13 +20,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
#include <xtables.h>
-#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_CONNMARK.h>
struct xt_connmark_target_info {
@@ -36,8 +32,28 @@ struct xt_connmark_target_info {
};
enum {
- F_MARK = 1 << 0,
- F_SR_MARK = 1 << 1,
+ O_SET_MARK = 0,
+ O_SAVE_MARK,
+ O_RESTORE_MARK,
+ O_AND_MARK,
+ O_OR_MARK,
+ O_XOR_MARK,
+ O_SET_XMARK,
+ O_CTMASK,
+ O_NFMASK,
+ O_MASK,
+ F_SET_MARK = 1 << O_SET_MARK,
+ F_SAVE_MARK = 1 << O_SAVE_MARK,
+ F_RESTORE_MARK = 1 << O_RESTORE_MARK,
+ F_AND_MARK = 1 << O_AND_MARK,
+ F_OR_MARK = 1 << O_OR_MARK,
+ F_XOR_MARK = 1 << O_XOR_MARK,
+ F_SET_XMARK = 1 << O_SET_XMARK,
+ F_CTMASK = 1 << O_CTMASK,
+ F_NFMASK = 1 << O_NFMASK,
+ F_MASK = 1 << O_MASK,
+ F_OP_ANY = F_SET_MARK | F_SAVE_MARK | F_RESTORE_MARK |
+ F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK,
};
static void CONNMARK_help(void)
@@ -49,27 +65,44 @@ static void CONNMARK_help(void)
" --restore-mark [--mask mask] Restore saved nfmark value\n");
}
-static const struct option CONNMARK_opts[] = {
- {.name = "set-mark", .has_arg = true, .val = '1'},
- {.name = "save-mark", .has_arg = false, .val = '2'},
- {.name = "restore-mark", .has_arg = false, .val = '3'},
- {.name = "mask", .has_arg = true, .val = '4'},
- XT_GETOPT_TABLEEND,
+#define s struct xt_connmark_target_info
+static const struct xt_option_entry CONNMARK_opts[] = {
+ {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
+ .excl = F_OP_ANY},
+ {.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
+ .excl = F_OP_ANY},
+ {.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
+ .excl = F_OP_ANY},
+ {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32},
+ XTOPT_TABLEEND,
};
-
-static const struct option connmark_tg_opts[] = {
- {.name = "set-xmark", .has_arg = true, .val = '='},
- {.name = "set-mark", .has_arg = true, .val = '-'},
- {.name = "and-mark", .has_arg = true, .val = '&'},
- {.name = "or-mark", .has_arg = true, .val = '|'},
- {.name = "xor-mark", .has_arg = true, .val = '^'},
- {.name = "save-mark", .has_arg = false, .val = 'S'},
- {.name = "restore-mark", .has_arg = false, .val = 'R'},
- {.name = "ctmask", .has_arg = true, .val = 'c'},
- {.name = "nfmask", .has_arg = true, .val = 'n'},
- {.name = "mask", .has_arg = true, .val = 'm'},
- XT_GETOPT_TABLEEND,
+#undef s
+
+#define s struct xt_connmark_tginfo1
+static const struct xt_option_entry connmark_tg_opts[] = {
+ {.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
+ .excl = F_OP_ANY},
+ {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
+ .excl = F_OP_ANY},
+ {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
+ .excl = F_OP_ANY},
+ {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
+ .excl = F_OP_ANY},
+ {.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
+ .excl = F_OP_ANY},
+ {.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
+ .excl = F_OP_ANY},
+ {.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
+ .excl = F_OP_ANY},
+ {.name = "ctmask", .id = O_CTMASK, .type = XTTYPE_UINT32,
+ .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, ctmask)},
+ {.name = "nfmask", .id = O_NFMASK, .type = XTTYPE_UINT32,
+ .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)},
+ {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32,
+ .excl = F_CTMASK | F_NFMASK},
+ XTOPT_TABLEEND,
};
+#undef s
static void connmark_tg_help(void)
{
@@ -101,163 +134,75 @@ static void connmark_tg_init(struct xt_entry_target *target)
info->nfmask = UINT32_MAX;
}
-static int
-CONNMARK_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void CONNMARK_parse(struct xt_option_call *cb)
{
- struct xt_connmark_target_info *markinfo
- = (struct xt_connmark_target_info *)(*target)->data;
+ struct xt_connmark_target_info *markinfo = cb->data;
- switch (c) {
- char *end;
- case '1':
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SET_MARK:
markinfo->mode = XT_CONNMARK_SET;
-
- markinfo->mark = strtoul(optarg, &end, 0);
- if (*end == '/' && end[1] != '\0')
- markinfo->mask = strtoul(end+1, &end, 0);
-
- if (*end != '\0' || end == optarg)
- xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --set-mark twice");
- *flags = 1;
+ markinfo->mark = cb->val.mark;
+ markinfo->mask = cb->val.mask;
break;
- case '2':
+ case O_SAVE_MARK:
markinfo->mode = XT_CONNMARK_SAVE;
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --save-mark twice");
- *flags = 1;
break;
- case '3':
+ case O_RESTORE_MARK:
markinfo->mode = XT_CONNMARK_RESTORE;
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --restore-mark twice");
- *flags = 1;
break;
- case '4':
- if (!*flags)
- xtables_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --mask without a operation");
- markinfo->mask = strtoul(optarg, &end, 0);
-
- if (*end != '\0' || end == optarg)
- xtables_error(PARAMETER_PROBLEM, "Bad MASK value \"%s\"", optarg);
+ case O_MASK:
+ markinfo->mask = cb->val.u32;
break;
}
-
- return 1;
}
-static int connmark_tg_parse(int c, char **argv, int invert,
- unsigned int *flags, const void *entry,
- struct xt_entry_target **target)
+static void connmark_tg_parse(struct xt_option_call *cb)
{
- struct xt_connmark_tginfo1 *info = (void *)(*target)->data;
- unsigned int value, mask = UINT32_MAX;
- char *end;
+ struct xt_connmark_tginfo1 *info = cb->data;
- switch (c) {
- case '=': /* --set-xmark */
- case '-': /* --set-mark */
- xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
- if (!xtables_strtoui(optarg, &end, &value, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
- if (*end == '/')
- if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
- if (*end != '\0')
- xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SET_XMARK:
info->mode = XT_CONNMARK_SET;
- info->ctmark = value;
- info->ctmask = mask;
- if (c == '-')
- info->ctmask |= value;
- *flags |= F_MARK;
- return true;
-
- case '&': /* --and-mark */
- xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
- if (!xtables_strtoui(optarg, NULL, &mask, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--and-mark", optarg);
+ info->ctmark = cb->val.mark;
+ info->ctmask = cb->val.mask;
+ break;
+ case O_SET_MARK:
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = cb->val.mark;
+ info->ctmask = cb->val.mark | cb->val.mask;
+ break;
+ case O_AND_MARK:
info->mode = XT_CONNMARK_SET;
info->ctmark = 0;
- info->ctmask = ~mask;
- *flags |= F_MARK;
- return true;
-
- case '|': /* --or-mark */
- xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
- if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--or-mark", optarg);
+ info->ctmask = ~cb->val.u32;
+ break;
+ case O_OR_MARK:
info->mode = XT_CONNMARK_SET;
- info->ctmark = value;
- info->ctmask = value;
- *flags |= F_MARK;
- return true;
-
- case '^': /* --xor-mark */
- xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
- if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--xor-mark", optarg);
+ info->ctmark = cb->val.u32;
+ info->ctmask = cb->val.u32;
+ break;
+ case O_XOR_MARK:
info->mode = XT_CONNMARK_SET;
- info->ctmark = value;
+ info->ctmark = cb->val.u32;
info->ctmask = 0;
- *flags |= F_MARK;
- return true;
-
- case 'S': /* --save-mark */
- xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ break;
+ case O_SAVE_MARK:
info->mode = XT_CONNMARK_SAVE;
- *flags |= F_MARK | F_SR_MARK;
- return true;
-
- case 'R': /* --restore-mark */
- xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ break;
+ case O_RESTORE_MARK:
info->mode = XT_CONNMARK_RESTORE;
- *flags |= F_MARK | F_SR_MARK;
- return true;
-
- case 'n': /* --nfmask */
- if (!(*flags & F_SR_MARK))
- xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
- "or --restore-mark is required for "
- "--nfmask");
- if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--nfmask", optarg);
- info->nfmask = value;
- return true;
-
- case 'c': /* --ctmask */
- if (!(*flags & F_SR_MARK))
- xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
- "or --restore-mark is required for "
- "--ctmask");
- if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--ctmask", optarg);
- info->ctmask = value;
- return true;
-
- case 'm': /* --mask */
- if (!(*flags & F_SR_MARK))
- xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
- "or --restore-mark is required for "
- "--mask");
- if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--mask", optarg);
- info->nfmask = info->ctmask = value;
- return true;
+ break;
+ case O_MASK:
+ info->nfmask = info->ctmask = cb->val.u32;
+ break;
}
-
- return false;
}
-static void connmark_tg_check(unsigned int flags)
+static void connmark_tg_check(struct xt_fcheck_call *cb)
{
- if (!flags)
+ if (!(cb->xflags & F_OP_ANY))
xtables_error(PARAMETER_PROBLEM,
"CONNMARK target: No operation specified");
}
@@ -412,11 +357,11 @@ static struct xtables_target connmark_tg_reg[] = {
.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
.help = CONNMARK_help,
.init = CONNMARK_init,
- .parse = CONNMARK_parse,
- .final_check = connmark_tg_check,
.print = CONNMARK_print,
.save = CONNMARK_save,
- .extra_opts = CONNMARK_opts,
+ .x6_parse = CONNMARK_parse,
+ .x6_fcheck = connmark_tg_check,
+ .x6_options = CONNMARK_opts,
},
{
.version = XTABLES_VERSION,
@@ -427,11 +372,11 @@ static struct xtables_target connmark_tg_reg[] = {
.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
.help = connmark_tg_help,
.init = connmark_tg_init,
- .parse = connmark_tg_parse,
- .final_check = connmark_tg_check,
.print = connmark_tg_print,
.save = connmark_tg_save,
- .extra_opts = connmark_tg_opts,
+ .x6_parse = connmark_tg_parse,
+ .x6_fcheck = connmark_tg_check,
+ .x6_options = connmark_tg_opts,
},
};
diff --git a/extensions/libxt_CT.c b/extensions/libxt_CT.c
index 38ee17b1..7b93bfaf 100644
--- a/extensions/libxt_CT.c
+++ b/extensions/libxt_CT.c
@@ -1,9 +1,5 @@
-#include <stdbool.h>
#include <stdio.h>
#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/xt_CT.h>
@@ -20,22 +16,26 @@ static void ct_help(void)
);
}
-enum ct_options {
- CT_OPT_NOTRACK = 0x1,
- CT_OPT_HELPER = 0x2,
- CT_OPT_CTEVENTS = 0x4,
- CT_OPT_EXPEVENTS = 0x8,
- CT_OPT_ZONE = 0x10,
+enum {
+ O_NOTRACK = 0,
+ O_HELPER,
+ O_CTEVENTS,
+ O_EXPEVENTS,
+ O_ZONE,
};
-static const struct option ct_opts[] = {
- {.name = "notrack", .has_arg = false, .val = CT_OPT_NOTRACK},
- {.name = "helper", .has_arg = true, .val = CT_OPT_HELPER},
- {.name = "ctevents", .has_arg = true, .val = CT_OPT_CTEVENTS},
- {.name = "expevents", .has_arg = true, .val = CT_OPT_EXPEVENTS},
- {.name = "zone", .has_arg = true, .val = CT_OPT_ZONE},
- XT_GETOPT_TABLEEND,
+#define s struct xt_ct_target_info
+static const struct xt_option_entry ct_opts[] = {
+ {.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE},
+ {.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, helper)},
+ {.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING},
+ {.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING},
+ {.name = "zone", .id = O_ZONE, .type = XTTYPE_UINT16,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, zone)},
+ XTOPT_TABLEEND,
};
+#undef s
struct event_tbl {
const char *name;
@@ -96,40 +96,22 @@ static void ct_print_events(const char *pfx, const struct event_tbl *tbl,
}
}
-static int ct_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void ct_parse(struct xt_option_call *cb)
{
- struct xt_ct_target_info *info = (struct xt_ct_target_info *)(*target)->data;
- unsigned int zone;
+ struct xt_ct_target_info *info = cb->data;
- switch (c) {
- case CT_OPT_NOTRACK:
- xtables_param_act(XTF_ONLY_ONCE, "CT", "--notrack", *flags & CT_OPT_NOTRACK);
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_NOTRACK:
info->flags |= XT_CT_NOTRACK;
break;
- case CT_OPT_HELPER:
- xtables_param_act(XTF_ONLY_ONCE, "CT", "--helper", *flags & CT_OPT_HELPER);
- strncpy(info->helper, optarg, sizeof(info->helper));
- info->helper[sizeof(info->helper) - 1] = '\0';
+ case O_CTEVENTS:
+ info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), cb->arg);
break;
- case CT_OPT_CTEVENTS:
- xtables_param_act(XTF_ONLY_ONCE, "CT", "--ctevents", *flags & CT_OPT_CTEVENTS);
- info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), optarg);
- break;
- case CT_OPT_EXPEVENTS:
- xtables_param_act(XTF_ONLY_ONCE, "CT", "--expevents", *flags & CT_OPT_EXPEVENTS);
- info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), optarg);
- break;
- case CT_OPT_ZONE:
- xtables_param_act(XTF_ONLY_ONCE, "CT", "--zone", *flags & CT_OPT_ZONE);
- if (!xtables_strtoui(optarg, NULL, &zone, 0, UINT16_MAX))
- xtables_error(PARAMETER_PROBLEM, "Bad zone value \"%s\"", optarg);
- info->zone = zone;
+ case O_EXPEVENTS:
+ info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), cb->arg);
break;
}
-
- *flags |= c;
- return 1;
}
static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric)
@@ -178,10 +160,10 @@ static struct xtables_target ct_target = {
.size = XT_ALIGN(sizeof(struct xt_ct_target_info)),
.userspacesize = offsetof(struct xt_ct_target_info, ct),
.help = ct_help,
- .parse = ct_parse,
.print = ct_print,
.save = ct_save,
- .extra_opts = ct_opts,
+ .x6_parse = ct_parse,
+ .x6_options = ct_opts,
};
void _init(void)
diff --git a/extensions/libxt_MARK.c b/extensions/libxt_MARK.c
index 885cf2f2..556dbde5 100644
--- a/extensions/libxt_MARK.c
+++ b/extensions/libxt_MARK.c
@@ -1,12 +1,6 @@
-/* Shared library add-on to iptables to add MARK target support. */
#include <stdbool.h>
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
#include <xtables.h>
-#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_MARK.h>
/* Version 0 */
@@ -27,7 +21,18 @@ struct xt_mark_target_info_v1 {
};
enum {
- F_MARK = 1 << 0,
+ O_SET_MARK = 0,
+ O_AND_MARK,
+ O_OR_MARK,
+ O_XOR_MARK,
+ O_SET_XMARK,
+ F_SET_MARK = 1 << O_SET_MARK,
+ F_AND_MARK = 1 << O_AND_MARK,
+ F_OR_MARK = 1 << O_OR_MARK,
+ F_XOR_MARK = 1 << O_XOR_MARK,
+ F_SET_XMARK = 1 << O_SET_XMARK,
+ F_ANY = F_SET_MARK | F_AND_MARK | F_OR_MARK |
+ F_XOR_MARK | F_SET_XMARK,
};
static void MARK_help(void)
@@ -39,20 +44,28 @@ static void MARK_help(void)
" --or-mark value Binary OR the nfmark with value\n");
}
-static const struct option MARK_opts[] = {
- {.name = "set-mark", .has_arg = true, .val = '1'},
- {.name = "and-mark", .has_arg = true, .val = '2'},
- {.name = "or-mark", .has_arg = true, .val = '3'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry MARK_opts[] = {
+ {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY},
+ {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY},
+ {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY},
+ XTOPT_TABLEEND,
};
-static const struct option mark_tg_opts[] = {
- {.name = "set-xmark", .has_arg = true, .val = 'X'},
- {.name = "set-mark", .has_arg = true, .val = '='},
- {.name = "and-mark", .has_arg = true, .val = '&'},
- {.name = "or-mark", .has_arg = true, .val = '|'},
- {.name = "xor-mark", .has_arg = true, .val = '^'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry mark_tg_opts[] = {
+ {.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
+ .excl = F_ANY},
+ {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
+ .excl = F_ANY},
+ {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY},
+ {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY},
+ {.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY},
+ XTOPT_TABLEEND,
};
static void mark_tg_help(void)
@@ -67,137 +80,80 @@ static void mark_tg_help(void)
"\n");
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-MARK_parse_v0(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void MARK_parse_v0(struct xt_option_call *cb)
{
- struct xt_mark_target_info *markinfo
- = (struct xt_mark_target_info *)(*target)->data;
- unsigned int mark = 0;
+ struct xt_mark_target_info *markinfo = cb->data;
- switch (c) {
- case '1':
- if (!xtables_strtoui(optarg, NULL, &mark, 0, UINT32_MAX))
- xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
- markinfo->mark = mark;
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "MARK target: Can't specify --set-mark twice");
- *flags = 1;
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SET_MARK:
+ markinfo->mark = cb->val.mark;
break;
- case '2':
- xtables_error(PARAMETER_PROBLEM,
- "MARK target: kernel too old for --and-mark");
- case '3':
+ default:
xtables_error(PARAMETER_PROBLEM,
- "MARK target: kernel too old for --or-mark");
+ "MARK target: kernel too old for --%s",
+ cb->entry->name);
}
-
- return 1;
}
-static void MARK_check(unsigned int flags)
+static void MARK_check(struct xt_fcheck_call *cb)
{
- if (!flags)
+ if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM,
"MARK target: Parameter --set/and/or-mark"
" is required");
}
-static int
-MARK_parse_v1(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void MARK_parse_v1(struct xt_option_call *cb)
{
- struct xt_mark_target_info_v1 *markinfo
- = (struct xt_mark_target_info_v1 *)(*target)->data;
- unsigned int mark = 0;
+ struct xt_mark_target_info_v1 *markinfo = cb->data;
- switch (c) {
- case '1':
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SET_MARK:
markinfo->mode = XT_MARK_SET;
break;
- case '2':
+ case O_AND_MARK:
markinfo->mode = XT_MARK_AND;
break;
- case '3':
+ case O_OR_MARK:
markinfo->mode = XT_MARK_OR;
break;
}
-
- if (!xtables_strtoui(optarg, NULL, &mark, 0, UINT32_MAX))
- xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
- markinfo->mark = mark;
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "MARK target: Can't specify --set-mark twice");
-
- *flags = 1;
- return 1;
+ markinfo->mark = cb->val.u32;
}
-static int mark_tg_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void mark_tg_parse(struct xt_option_call *cb)
{
- struct xt_mark_tginfo2 *info = (void *)(*target)->data;
- unsigned int value, mask = UINT32_MAX;
- char *end;
+ struct xt_mark_tginfo2 *info = cb->data;
- switch (c) {
- case 'X': /* --set-xmark */
- case '=': /* --set-mark */
- xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
- xtables_param_act(XTF_NO_INVERT, "MARK", "--set-xmark/--set-mark", invert);
- if (!xtables_strtoui(optarg, &end, &value, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
- if (*end == '/')
- if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
- if (*end != '\0')
- xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
- info->mark = value;
- info->mask = mask;
-
- if (c == '=')
- info->mask = value | mask;
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SET_XMARK:
+ info->mark = cb->val.mark;
+ info->mask = cb->val.mask;
break;
-
- case '&': /* --and-mark */
- xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
- xtables_param_act(XTF_NO_INVERT, "MARK", "--and-mark", invert);
- if (!xtables_strtoui(optarg, NULL, &mask, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "MARK", "--and-mark", optarg);
+ case O_SET_MARK:
+ info->mark = cb->val.mark;
+ info->mask = cb->val.mark | cb->val.mask;
+ break;
+ case O_AND_MARK:
info->mark = 0;
- info->mask = ~mask;
+ info->mask = ~cb->val.u32;
break;
-
- case '|': /* --or-mark */
- xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
- xtables_param_act(XTF_NO_INVERT, "MARK", "--or-mark", invert);
- if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "MARK", "--or-mark", optarg);
- info->mark = value;
- info->mask = value;
+ case O_OR_MARK:
+ info->mark = info->mask = cb->val.u32;
break;
-
- case '^': /* --xor-mark */
- xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
- xtables_param_act(XTF_NO_INVERT, "MARK", "--xor-mark", invert);
- if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "MARK", "--xor-mark", optarg);
- info->mark = value;
+ case O_XOR_MARK:
+ info->mark = cb->val.u32;
info->mask = 0;
break;
}
-
- *flags |= F_MARK;
- return true;
}
-static void mark_tg_check(unsigned int flags)
+static void mark_tg_check(struct xt_fcheck_call *cb)
{
- if (flags == 0)
+ if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, "
"--{and,or,xor,set}-mark options is required");
}
@@ -298,11 +254,11 @@ static struct xtables_target mark_tg_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_mark_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)),
.help = MARK_help,
- .parse = MARK_parse_v0,
- .final_check = MARK_check,
.print = MARK_print_v0,
.save = MARK_save_v0,
- .extra_opts = MARK_opts,
+ .x6_parse = MARK_parse_v0,
+ .x6_fcheck = MARK_check,
+ .x6_options = MARK_opts,
},
{
.family = NFPROTO_IPV4,
@@ -312,11 +268,11 @@ static struct xtables_target mark_tg_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
.help = MARK_help,
- .parse = MARK_parse_v1,
- .final_check = MARK_check,
.print = MARK_print_v1,
.save = MARK_save_v1,
- .extra_opts = MARK_opts,
+ .x6_parse = MARK_parse_v1,
+ .x6_fcheck = MARK_check,
+ .x6_options = MARK_opts,
},
{
.version = XTABLES_VERSION,
@@ -326,11 +282,11 @@ static struct xtables_target mark_tg_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
.userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
.help = mark_tg_help,
- .parse = mark_tg_parse,
- .final_check = mark_tg_check,
.print = mark_tg_print,
.save = mark_tg_save,
- .extra_opts = mark_tg_opts,
+ .x6_parse = mark_tg_parse,
+ .x6_fcheck = mark_tg_check,
+ .x6_options = mark_tg_opts,
},
};
diff --git a/extensions/libxt_NFQUEUE.c b/extensions/libxt_NFQUEUE.c
index 7f2aab16..a86c88a3 100644
--- a/extensions/libxt_NFQUEUE.c
+++ b/extensions/libxt_NFQUEUE.c
@@ -5,16 +5,16 @@
* This program is distributed under the terms of GNU GPL v2, 1991
*
*/
-#include <stdbool.h>
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
#include <xtables.h>
-#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_NFQUEUE.h>
+enum {
+ O_QUEUE_NUM = 0,
+ O_QUEUE_BALANCE,
+ O_QUEUE_BYPASS,
+};
+
static void NFQUEUE_help(void)
{
printf(
@@ -38,103 +38,58 @@ static void NFQUEUE_help_v2(void)
" --queue-bypass Bypass Queueing if no queue instance exists.\n");
}
-static const struct option NFQUEUE_opts[] = {
- {.name = "queue-num", .has_arg = true, .val = 'F'},
- {.name = "queue-balance", .has_arg = true, .val = 'B'},
- {.name = "queue-bypass", .has_arg = false,.val = 'P'},
- XT_GETOPT_TABLEEND,
+#define s struct xt_NFQ_info
+static const struct xt_option_entry NFQUEUE_opts[] = {
+ {.name = "queue-num", .id = O_QUEUE_NUM, .type = XTTYPE_UINT16,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum)},
+ {.name = "queue-balance", .id = O_QUEUE_BALANCE,
+ .type = XTTYPE_UINT16RC},
+ {.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
+#undef s
-static void exit_badqueue(const char *s)
-{
- xtables_error(PARAMETER_PROBLEM, "Invalid queue number `%s'\n", s);
-}
-
-static void
-parse_num(const char *s, struct xt_NFQ_info *tinfo)
+static void NFQUEUE_parse(struct xt_option_call *cb)
{
- unsigned int num;
-
- if (!xtables_strtoui(s, NULL, &num, 0, UINT16_MAX))
- exit_badqueue(s);
-
- tinfo->queuenum = num;
-}
-
-static int
-NFQUEUE_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct xt_NFQ_info *tinfo
- = (struct xt_NFQ_info *)(*target)->data;
-
- switch (c) {
- case 'F':
- if (*flags)
- xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
- "Only use --queue-num ONCE!");
- parse_num(optarg, tinfo);
- break;
- case 'B':
+ xtables_option_parse(cb);
+ if (cb->entry->id == O_QUEUE_BALANCE)
xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
"--queue-balance not supported (kernel too old?)");
- }
-
- return 1;
}
-static int
-NFQUEUE_parse_v1(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void NFQUEUE_parse_v1(struct xt_option_call *cb)
{
- struct xt_NFQ_info_v1 *info = (void *)(*target)->data;
- char *colon;
- unsigned int firstqueue, lastqueue;
-
- switch (c) {
- case 'F': /* fallthrough */
- case 'B':
- if (*flags)
- xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
- "Only use --queue-num ONCE!");
-
- if (!xtables_strtoui(optarg, &colon, &firstqueue, 0, UINT16_MAX))
- exit_badqueue(optarg);
-
- info->queuenum = firstqueue;
-
- if (c == 'F') {
- if (*colon)
- exit_badqueue(optarg);
- break;
- }
+ struct xt_NFQ_info_v1 *info = cb->data;
+ const uint16_t *r = cb->val.u16_range;
- if (*colon != ':')
- xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", optarg);
-
- if (!xtables_strtoui(colon + 1, NULL, &lastqueue, 1, UINT16_MAX))
- exit_badqueue(optarg);
-
- if (firstqueue >= lastqueue)
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_QUEUE_BALANCE:
+ if (cb->nvals != 2)
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad range \"%s\"", cb->arg);
+ if (r[0] >= r[1])
xtables_error(PARAMETER_PROBLEM, "%u should be less than %u",
- firstqueue, lastqueue);
- info->queues_total = lastqueue - firstqueue + 1;
+ r[0], r[1]);
+ info->queuenum = r[0];
+ info->queues_total = r[1] - r[0] + 1;
break;
}
-
- return 1;
}
-static int
-NFQUEUE_parse_v2(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void NFQUEUE_parse_v2(struct xt_option_call *cb)
{
- if (c == 'P') {
- struct xt_NFQ_info_v2 *info = (void *)(*target)->data;
+ struct xt_NFQ_info_v2 *info = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_QUEUE_BYPASS:
info->bypass = 1;
- return 1;
+ break;
+ default:
+ NFQUEUE_parse_v1(cb);
+ break;
}
- return NFQUEUE_parse_v1(c, argv, invert, flags, entry, target);
}
static void NFQUEUE_print(const void *ip,
@@ -214,10 +169,10 @@ static struct xtables_target nfqueue_targets[] = {
.size = XT_ALIGN(sizeof(struct xt_NFQ_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info)),
.help = NFQUEUE_help,
- .parse = NFQUEUE_parse,
.print = NFQUEUE_print,
.save = NFQUEUE_save,
- .extra_opts = NFQUEUE_opts
+ .x6_parse = NFQUEUE_parse,
+ .x6_options = NFQUEUE_opts
},{
.family = NFPROTO_UNSPEC,
.revision = 1,
@@ -227,10 +182,10 @@ static struct xtables_target nfqueue_targets[] = {
.userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
.help = NFQUEUE_help_v1,
.init = NFQUEUE_init_v1,
- .parse = NFQUEUE_parse_v1,
.print = NFQUEUE_print_v1,
.save = NFQUEUE_save_v1,
- .extra_opts = NFQUEUE_opts,
+ .x6_parse = NFQUEUE_parse_v1,
+ .x6_options = NFQUEUE_opts,
},{
.family = NFPROTO_UNSPEC,
.revision = 2,
@@ -240,10 +195,10 @@ static struct xtables_target nfqueue_targets[] = {
.userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)),
.help = NFQUEUE_help_v2,
.init = NFQUEUE_init_v1,
- .parse = NFQUEUE_parse_v2,
.print = NFQUEUE_print_v2,
.save = NFQUEUE_save_v2,
- .extra_opts = NFQUEUE_opts,
+ .x6_parse = NFQUEUE_parse_v2,
+ .x6_options = NFQUEUE_opts,
}
};
diff --git a/extensions/libxt_TCPMSS.c b/extensions/libxt_TCPMSS.c
index e15e87a8..2266326d 100644
--- a/extensions/libxt_TCPMSS.c
+++ b/extensions/libxt_TCPMSS.c
@@ -2,16 +2,17 @@
*
* Copyright (c) 2000 Marc Boucher
*/
-#include <stdbool.h>
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
#include <xtables.h>
-#include <linux/netfilter/x_tables.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <linux/netfilter/xt_TCPMSS.h>
+enum {
+ O_SET_MSS = 0,
+ O_CLAMP_MSS,
+};
+
struct mssinfo {
struct xt_entry_target t;
struct xt_tcpmss_info mss;
@@ -28,69 +29,42 @@ hdrsize);
static void TCPMSS_help(void)
{
- __TCPMSS_help(40);
+ __TCPMSS_help(sizeof(struct iphdr));
}
static void TCPMSS_help6(void)
{
- __TCPMSS_help(60);
+ __TCPMSS_help(sizeof(struct ip6_hdr));
}
-static const struct option TCPMSS_opts[] = {
- {.name = "set-mss", .has_arg = true, .val = '1'},
- {.name = "clamp-mss-to-pmtu", .has_arg = false, .val = '2'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry TCPMSS4_opts[] = {
+ {.name = "set-mss", .id = O_SET_MSS, .type = XTTYPE_UINT16,
+ .min = 0, .max = UINT16_MAX - sizeof(struct iphdr),
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_tcpmss_info, mss)},
+ {.name = "clamp-mss-to-pmtu", .id = O_CLAMP_MSS, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
-static int __TCPMSS_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target,
- int hdrsize)
-{
- struct xt_tcpmss_info *mssinfo
- = (struct xt_tcpmss_info *)(*target)->data;
-
- switch (c) {
- unsigned int mssval;
-
- case '1':
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "TCPMSS target: Only one option may be specified");
- if (!xtables_strtoui(optarg, NULL, &mssval,
- 0, UINT16_MAX - hdrsize))
- xtables_error(PARAMETER_PROBLEM, "Bad TCPMSS value \"%s\"", optarg);
-
- mssinfo->mss = mssval;
- *flags = 1;
- break;
-
- case '2':
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "TCPMSS target: Only one option may be specified");
- mssinfo->mss = XT_TCPMSS_CLAMP_PMTU;
- *flags = 1;
- break;
- }
-
- return 1;
-}
+static const struct xt_option_entry TCPMSS6_opts[] = {
+ {.name = "set-mss", .id = O_SET_MSS, .type = XTTYPE_UINT16,
+ .min = 0, .max = UINT16_MAX - sizeof(struct ip6_hdr),
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_tcpmss_info, mss)},
+ {.name = "clamp-mss-to-pmtu", .id = O_CLAMP_MSS, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
-static int TCPMSS_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void TCPMSS_parse(struct xt_option_call *cb)
{
- return __TCPMSS_parse(c, argv, invert, flags, entry, target, 40);
-}
+ struct xt_tcpmss_info *mssinfo = cb->data;
-static int TCPMSS_parse6(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- return __TCPMSS_parse(c, argv, invert, flags, entry, target, 60);
+ xtables_option_parse(cb);
+ if (cb->entry->id == O_CLAMP_MSS)
+ mssinfo->mss = XT_TCPMSS_CLAMP_PMTU;
}
-static void TCPMSS_check(unsigned int flags)
+static void TCPMSS_check(struct xt_fcheck_call *cb)
{
- if (!flags)
+ if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM,
"TCPMSS target: At least one parameter is required");
}
@@ -124,11 +98,11 @@ static struct xtables_target tcpmss_target = {
.size = XT_ALIGN(sizeof(struct xt_tcpmss_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)),
.help = TCPMSS_help,
- .parse = TCPMSS_parse,
- .final_check = TCPMSS_check,
.print = TCPMSS_print,
.save = TCPMSS_save,
- .extra_opts = TCPMSS_opts,
+ .x6_parse = TCPMSS_parse,
+ .x6_fcheck = TCPMSS_check,
+ .x6_options = TCPMSS4_opts,
};
static struct xtables_target tcpmss_target6 = {
@@ -138,11 +112,11 @@ static struct xtables_target tcpmss_target6 = {
.size = XT_ALIGN(sizeof(struct xt_tcpmss_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)),
.help = TCPMSS_help6,
- .parse = TCPMSS_parse6,
- .final_check = TCPMSS_check,
.print = TCPMSS_print,
.save = TCPMSS_save,
- .extra_opts = TCPMSS_opts,
+ .x6_parse = TCPMSS_parse,
+ .x6_fcheck = TCPMSS_check,
+ .x6_options = TCPMSS6_opts,
};
void _init(void)
diff --git a/extensions/libxt_TPROXY.c b/extensions/libxt_TPROXY.c
index 890dd866..5264ea7d 100644
--- a/extensions/libxt_TPROXY.c
+++ b/extensions/libxt_TPROXY.c
@@ -1,32 +1,42 @@
/*
- * Shared library add-on to iptables to add TPROXY target support.
+ * shared library add-on to iptables to add TPROXY target support.
*
* Copyright (C) 2002-2008 BalaBit IT Ltd.
*/
-#include <getopt.h>
-#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
#include <limits.h>
-
#include <xtables.h>
-#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_TPROXY.h>
+#include <arpa/inet.h>
-static const struct option tproxy_tg_opts[] = {
- {.name = "on-port", .has_arg = true, .val = '1'},
- {.name = "on-ip", .has_arg = true, .val = '2'},
- {.name = "tproxy-mark", .has_arg = true, .val = '3'},
- XT_GETOPT_TABLEEND,
+enum {
+ P_PORT = 0,
+ P_ADDR,
+ P_MARK,
+ F_PORT = 1 << P_PORT,
+ F_ADDR = 1 << P_ADDR,
+ F_MARK = 1 << P_MARK,
};
-enum {
- PARAM_ONPORT = 1 << 0,
- PARAM_ONIP = 1 << 1,
- PARAM_MARK = 1 << 2,
+#define s struct xt_tproxy_target_info
+static const struct xt_option_entry tproxy_tg0_opts[] = {
+ {.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT_NE,
+ .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, lport)},
+ {.name = "on-ip", .id = P_ADDR, .type = XTTYPE_ONEHOST},
+ {.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
+ XTOPT_TABLEEND,
};
+#undef s
+#define s struct xt_tproxy_target_info_v1
+static const struct xt_option_entry tproxy_tg1_opts[] = {
+ {.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT_NE,
+ .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, lport)},
+ {.name = "on-ip", .id = P_ADDR, .type = XTTYPE_ONEHOST,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, laddr)},
+ {.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
+ XTOPT_TABLEEND,
+};
+#undef s
static void tproxy_tg_help(void)
{
@@ -37,134 +47,6 @@ static void tproxy_tg_help(void)
" --tproxy-mark value[/mask] Mark packets with the given value/mask\n\n");
}
-static void parse_tproxy_lport(const char *s, uint16_t *portp)
-{
- unsigned int lport;
-
- if (xtables_strtoui(s, NULL, &lport, 0, UINT16_MAX))
- *portp = htons(lport);
- else
- xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--on-port", s);
-}
-
-static void parse_tproxy_laddr(const char *s, union nf_inet_addr *addrp,
- unsigned int nfproto)
-{
- struct in6_addr *laddr6 = NULL;
- struct in_addr *laddr4 = NULL;
-
- if (nfproto == NFPROTO_IPV6) {
- laddr6 = xtables_numeric_to_ip6addr(s);
- if (laddr6 == NULL)
- goto out;
- addrp->in6 = *laddr6;
- } else if (nfproto == NFPROTO_IPV4) {
- laddr4 = xtables_numeric_to_ipaddr(s);
- if (laddr4 == NULL)
- goto out;
- addrp->in = *laddr4;
- }
- return;
- out:
- xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--on-ip", s);
-}
-
-static void parse_tproxy_mark(char *s, uint32_t *markp, uint32_t *maskp)
-{
- unsigned int value, mask = UINT32_MAX;
- char *end;
-
- if (!xtables_strtoui(s, &end, &value, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
- if (*end == '/')
- if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
- if (*end != '\0')
- xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
-
- *markp = value;
- *maskp = mask;
-}
-
-static int tproxy_tg_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct xt_tproxy_target_info *info = (void *)(*target)->data;
-
- switch (c) {
- case '1':
- xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-port", *flags & PARAM_ONPORT);
- xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-port", invert);
- parse_tproxy_lport(optarg, &info->lport);
- *flags |= PARAM_ONPORT;
- return 1;
- case '2':
- xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-ip", *flags & PARAM_ONIP);
- xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-ip", invert);
- parse_tproxy_laddr(optarg, (void *)&info->laddr, NFPROTO_IPV4);
- *flags |= PARAM_ONIP;
- return 1;
- case '3':
- xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--tproxy-mark", *flags & PARAM_MARK);
- xtables_param_act(XTF_NO_INVERT, "TPROXY", "--tproxy-mark", invert);
- parse_tproxy_mark(optarg, &info->mark_value, &info->mark_mask);
- *flags |= PARAM_MARK;
- return 1;
- }
-
- return 0;
-}
-
-static int
-tproxy_tg_parse1(int c, char **argv, int invert, unsigned int *flags,
- struct xt_tproxy_target_info_v1 *info, unsigned int nfproto)
-{
- switch (c) {
- case '1':
- xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-port", *flags & PARAM_ONPORT);
- xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-port", invert);
- parse_tproxy_lport(optarg, &info->lport);
- *flags |= PARAM_ONPORT;
- return true;
- case '2':
- xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-ip", *flags & PARAM_ONIP);
- xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-ip", invert);
- parse_tproxy_laddr(optarg, (void *)&info->laddr, nfproto);
- *flags |= PARAM_ONIP;
- return true;
- case '3':
- xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--tproxy-mark", *flags & PARAM_MARK);
- xtables_param_act(XTF_NO_INVERT, "TPROXY", "--tproxy-mark", invert);
- parse_tproxy_mark(optarg, &info->mark_value, &info->mark_mask);
- *flags |= PARAM_MARK;
- return true;
- }
- return false;
-}
-
-static int
-tproxy_tg_parse4(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct xt_tproxy_target_info_v1 *info = (void *)(*target)->data;
- return tproxy_tg_parse1(c, argv, invert, flags, info, NFPROTO_IPV4);
-}
-
-static int
-tproxy_tg_parse6(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct xt_tproxy_target_info_v1 *info = (void *)(*target)->data;
- return tproxy_tg_parse1(c, argv, invert, flags, info, NFPROTO_IPV6);
-}
-
-static void tproxy_tg_check(unsigned int flags)
-{
- if (!(flags & PARAM_ONPORT))
- xtables_error(PARAMETER_PROBLEM,
- "TPROXY target: Parameter --on-port is required");
-}
-
static void tproxy_tg_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
@@ -236,6 +118,35 @@ tproxy_tg_save6(const void *ip, const struct xt_entry_target *target)
(unsigned int)info->mark_value, (unsigned int)info->mark_mask);
}
+static void tproxy_tg0_parse(struct xt_option_call *cb)
+{
+ struct xt_tproxy_target_info *info = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case P_MARK:
+ info->mark_value = cb->val.mark;
+ info->mark_mask = cb->val.mask;
+ break;
+ case P_ADDR:
+ info->laddr = cb->val.inetaddr.ip;
+ break;
+ }
+}
+
+static void tproxy_tg1_parse(struct xt_option_call *cb)
+{
+ struct xt_tproxy_target_info_v1 *info = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case P_MARK:
+ info->mark_value = cb->val.mark;
+ info->mark_mask = cb->val.mask;
+ break;
+ }
+}
+
static struct xtables_target tproxy_tg_reg[] = {
{
.name = "TPROXY",
@@ -245,11 +156,10 @@ static struct xtables_target tproxy_tg_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
.help = tproxy_tg_help,
- .parse = tproxy_tg_parse,
- .final_check = tproxy_tg_check,
.print = tproxy_tg_print,
.save = tproxy_tg_save,
- .extra_opts = tproxy_tg_opts,
+ .x6_options = tproxy_tg0_opts,
+ .x6_parse = tproxy_tg0_parse,
},
{
.name = "TPROXY",
@@ -259,11 +169,10 @@ static struct xtables_target tproxy_tg_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
.help = tproxy_tg_help,
- .parse = tproxy_tg_parse4,
- .final_check = tproxy_tg_check,
.print = tproxy_tg_print4,
.save = tproxy_tg_save4,
- .extra_opts = tproxy_tg_opts,
+ .x6_options = tproxy_tg1_opts,
+ .x6_parse = tproxy_tg1_parse,
},
{
.name = "TPROXY",
@@ -273,11 +182,10 @@ static struct xtables_target tproxy_tg_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
.help = tproxy_tg_help,
- .parse = tproxy_tg_parse6,
- .final_check = tproxy_tg_check,
.print = tproxy_tg_print6,
.save = tproxy_tg_save6,
- .extra_opts = tproxy_tg_opts,
+ .x6_options = tproxy_tg1_opts,
+ .x6_parse = tproxy_tg1_parse,
},
};
diff --git a/extensions/libxt_connbytes.c b/extensions/libxt_connbytes.c
index 1d3391ae..46a7e4b9 100644
--- a/extensions/libxt_connbytes.c
+++ b/extensions/libxt_connbytes.c
@@ -1,14 +1,14 @@
-/* Shared library add-on to iptables to add byte tracking support. */
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
-#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/xt_connbytes.h>
+enum {
+ O_CONNBYTES = 0,
+ O_CONNBYTES_DIR,
+ O_CONNBYTES_MODE,
+};
+
static void connbytes_help(void)
{
printf(
@@ -18,87 +18,57 @@ static void connbytes_help(void)
" --connbytes-mode [packets, bytes, avgpkt]\n");
}
-static const struct option connbytes_opts[] = {
- {.name = "connbytes", .has_arg = true, .val = '1'},
- {.name = "connbytes-dir", .has_arg = true, .val = '2'},
- {.name = "connbytes-mode", .has_arg = true, .val = '3'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry connbytes_opts[] = {
+ {.name = "connbytes", .id = O_CONNBYTES, .type = XTTYPE_UINT64RC,
+ .flags = XTOPT_MAND | XTOPT_INVERT},
+ {.name = "connbytes-dir", .id = O_CONNBYTES_DIR, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND},
+ {.name = "connbytes-mode", .id = O_CONNBYTES_MODE,
+ .type = XTTYPE_STRING, .flags = XTOPT_MAND},
+ XTOPT_TABLEEND,
};
-static void
-parse_range(const char *arg, struct xt_connbytes_info *si)
-{
- char *colon,*p;
-
- si->count.from = strtoul(arg,&colon,10);
- if (*colon != ':')
- xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", arg);
- si->count.to = strtoul(colon+1,&p,10);
- if (p == colon+1) {
- /* second number omited */
- si->count.to = 0xffffffff;
- }
- if (si->count.from > si->count.to)
- xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu",
- (unsigned long long)si->count.from,
- (unsigned long long)si->count.to);
-}
-
-static int
-connbytes_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void connbytes_parse(struct xt_option_call *cb)
{
- struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)(*match)->data;
- unsigned long i;
-
- switch (c) {
- case '1':
- if (xtables_check_inverse(optarg, &invert, &optind, 0, argv))
- optind++;
-
- parse_range(optarg, sinfo);
- if (invert) {
+ struct xt_connbytes_info *sinfo = cb->data;
+ unsigned long long i;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_CONNBYTES:
+ sinfo->count.from = cb->val.u64_range[0];
+ sinfo->count.to = cb->val.u64_range[0];
+ if (cb->nvals == 2)
+ sinfo->count.to = cb->val.u64_range[1];
+ if (cb->invert) {
i = sinfo->count.from;
sinfo->count.from = sinfo->count.to;
sinfo->count.to = i;
}
- *flags |= 1;
break;
- case '2':
- if (!strcmp(optarg, "original"))
+ case O_CONNBYTES_DIR:
+ if (strcmp(cb->arg, "original") == 0)
sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL;
- else if (!strcmp(optarg, "reply"))
+ else if (strcmp(cb->arg, "reply") == 0)
sinfo->direction = XT_CONNBYTES_DIR_REPLY;
- else if (!strcmp(optarg, "both"))
+ else if (strcmp(cb->arg, "both") == 0)
sinfo->direction = XT_CONNBYTES_DIR_BOTH;
else
xtables_error(PARAMETER_PROBLEM,
- "Unknown --connbytes-dir `%s'", optarg);
-
- *flags |= 2;
+ "Unknown --connbytes-dir `%s'", cb->arg);
break;
- case '3':
- if (!strcmp(optarg, "packets"))
+ case O_CONNBYTES_MODE:
+ if (strcmp(cb->arg, "packets") == 0)
sinfo->what = XT_CONNBYTES_PKTS;
- else if (!strcmp(optarg, "bytes"))
+ else if (strcmp(cb->arg, "bytes") == 0)
sinfo->what = XT_CONNBYTES_BYTES;
- else if (!strcmp(optarg, "avgpkt"))
+ else if (strcmp(cb->arg, "avgpkt") == 0)
sinfo->what = XT_CONNBYTES_AVGPKT;
else
xtables_error(PARAMETER_PROBLEM,
- "Unknown --connbytes-mode `%s'", optarg);
- *flags |= 4;
+ "Unknown --connbytes-mode `%s'", cb->arg);
break;
}
-
- return 1;
-}
-
-static void connbytes_check(unsigned int flags)
-{
- if (flags != 7)
- xtables_error(PARAMETER_PROBLEM, "You must specify `--connbytes'"
- "`--connbytes-dir' and `--connbytes-mode'");
}
static void print_mode(const struct xt_connbytes_info *sinfo)
@@ -185,11 +155,10 @@ static struct xtables_match connbytes_match = {
.size = XT_ALIGN(sizeof(struct xt_connbytes_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)),
.help = connbytes_help,
- .parse = connbytes_parse,
- .final_check = connbytes_check,
.print = connbytes_print,
.save = connbytes_save,
- .extra_opts = connbytes_opts,
+ .x6_parse = connbytes_parse,
+ .x6_options = connbytes_opts,
};
void _init(void)
diff --git a/extensions/libxt_connmark.c b/extensions/libxt_connmark.c
index a0e89fe7..6f1d5323 100644
--- a/extensions/libxt_connmark.c
+++ b/extensions/libxt_connmark.c
@@ -20,12 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
#include <xtables.h>
#include <linux/netfilter/xt_connmark.h>
@@ -35,7 +31,7 @@ struct xt_connmark_info {
};
enum {
- F_MARK = 1 << 0,
+ O_MARK = 0,
};
static void connmark_mt_help(void)
@@ -45,65 +41,32 @@ static void connmark_mt_help(void)
"[!] --mark value[/mask] Match ctmark value with optional mask\n");
}
-static const struct option connmark_mt_opts[] = {
- {.name = "mark", .has_arg = true, .val = '1'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry connmark_mt_opts[] = {
+ {.name = "mark", .id = O_MARK, .type = XTTYPE_MARKMASK32,
+ .flags = XTOPT_MAND | XTOPT_INVERT},
+ XTOPT_TABLEEND,
};
-static int
-connmark_mt_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void connmark_mt_parse(struct xt_option_call *cb)
{
- struct xt_connmark_mtinfo1 *info = (void *)(*match)->data;
- unsigned int mark, mask = UINT32_MAX;
- char *end;
-
- switch (c) {
- case '1': /* --mark */
- xtables_param_act(XTF_ONLY_ONCE, "connmark", "--mark", *flags & F_MARK);
- if (!xtables_strtoui(optarg, &end, &mark, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
- if (*end == '/')
- if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
- if (*end != '\0')
- xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
-
- if (invert)
- info->invert = true;
- info->mark = mark;
- info->mask = mask;
- *flags |= F_MARK;
- return true;
- }
- return false;
+ struct xt_connmark_mtinfo1 *info = cb->data;
+
+ xtables_option_parse(cb);
+ if (cb->invert)
+ info->invert = true;
+ info->mark = cb->val.mark;
+ info->mask = cb->val.mask;
}
-static int
-connmark_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void connmark_parse(struct xt_option_call *cb)
{
- struct xt_connmark_info *markinfo = (struct xt_connmark_info *)(*match)->data;
-
- switch (c) {
- char *end;
- case '1':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
- markinfo->mark = strtoul(optarg, &end, 0);
- markinfo->mask = 0xffffffffUL;
-
- if (*end == '/')
- markinfo->mask = strtoul(end+1, &end, 0);
-
- if (*end != '\0' || end == optarg)
- xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
- if (invert)
- markinfo->invert = 1;
- *flags = 1;
- break;
- }
- return 1;
+ struct xt_connmark_info *markinfo = cb->data;
+
+ xtables_option_parse(cb);
+ markinfo->mark = cb->val.mark;
+ markinfo->mask = cb->val.mask;
+ if (cb->invert)
+ markinfo->invert = 1;
}
static void print_mark(unsigned int mark, unsigned int mask)
@@ -114,13 +77,6 @@ static void print_mark(unsigned int mark, unsigned int mask)
printf(" 0x%x", mark);
}
-static void connmark_mt_check(unsigned int flags)
-{
- if (flags == 0)
- xtables_error(PARAMETER_PROBLEM,
- "connmark: The --mark option is required");
-}
-
static void
connmark_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
@@ -175,11 +131,10 @@ static struct xtables_match connmark_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_connmark_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_info)),
.help = connmark_mt_help,
- .parse = connmark_parse,
- .final_check = connmark_mt_check,
.print = connmark_print,
.save = connmark_save,
- .extra_opts = connmark_mt_opts,
+ .x6_parse = connmark_parse,
+ .x6_options = connmark_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -189,11 +144,10 @@ static struct xtables_match connmark_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
.help = connmark_mt_help,
- .parse = connmark_mt_parse,
- .final_check = connmark_mt_check,
.print = connmark_mt_print,
.save = connmark_mt_save,
- .extra_opts = connmark_mt_opts,
+ .x6_parse = connmark_mt_parse,
+ .x6_options = connmark_mt_opts,
},
};
diff --git a/extensions/libxt_devgroup.c b/extensions/libxt_devgroup.c
index 26248687..a925dd08 100644
--- a/extensions/libxt_devgroup.c
+++ b/extensions/libxt_devgroup.c
@@ -2,14 +2,10 @@
*
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
*/
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
-#include <ctype.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter/xt_devgroup.h>
@@ -23,200 +19,84 @@ static void devgroup_help(void)
}
enum {
- XT_DEVGROUP_OPT_SRCGROUP = 1,
- XT_DEVGROUP_OPT_DSTGROUP,
+ O_SRC_GROUP = 0,
+ O_DST_GROUP,
};
-static const struct option devgroup_opts[] = {
- { .name = "src-group", .has_arg = true, .val = XT_DEVGROUP_OPT_SRCGROUP },
- { .name = "dst-group", .has_arg = true, .val = XT_DEVGROUP_OPT_DSTGROUP },
- XT_GETOPT_TABLEEND,
-};
-
-struct devgroupname {
- unsigned int id;
- char *name;
- int len;
- struct devgroupname *next;
+static const struct xt_option_entry devgroup_opts[] = {
+ {.name = "src-group", .id = O_SRC_GROUP, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "dst-group", .id = O_DST_GROUP, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ XTOPT_TABLEEND,
};
/* array of devgroups from /etc/iproute2/group_map */
-static struct devgroupname *devgroups;
-/* 1 if loading failed */
-static int rdberr;
+static struct xtables_lmap *devgroups;
-static void load_devgroups(void)
+static void devgroup_init(struct xt_entry_match *match)
{
- const char* rfnm = "/etc/iproute2/group_map";
- char buf[512];
- FILE *fil;
- char *cur, *nxt;
- int id;
- struct devgroupname *oldnm = NULL, *newnm = NULL;
-
- fil = fopen(rfnm, "r");
- if (!fil) {
- rdberr = 1;
- return;
- }
-
- while (fgets(buf, sizeof(buf), fil)) {
- cur = buf;
- while ((*cur == ' ') || (*cur == '\t'))
- cur++;
- if ((*cur == '#') || (*cur == '\n') || (*cur == 0))
- continue;
-
- /* iproute2 allows hex and dec format */
- errno = 0;
- id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) ? 10 : 16);
- if ((nxt == cur) || errno)
- continue;
-
- /* same boundaries as in iproute2 */
- if (id < 0 || id > 255)
- continue;
- cur = nxt;
-
- if (!isspace(*cur))
- continue;
- while ((*cur == ' ') || (*cur == '\t'))
- cur++;
- if ((*cur == '#') || (*cur == '\n') || (*cur == 0))
- continue;
- nxt = cur;
- while ((*nxt != 0) && !isspace(*nxt))
- nxt++;
- if (nxt == cur)
- continue;
-
- /* found valid data */
- newnm = malloc(sizeof(struct devgroupname));
- if (newnm == NULL) {
- perror("libxt_devgroup: malloc failed");
- exit(1);
- }
- newnm->id = id;
- newnm->len = nxt - cur;
- newnm->name = malloc(newnm->len + 1);
- if (newnm->name == NULL) {
- perror("libxt_devgroup: malloc failed");
- exit(1);
- }
- strncpy(newnm->name, cur, newnm->len);
- newnm->name[newnm->len] = 0;
- newnm->next = NULL;
-
- if (oldnm)
- oldnm->next = newnm;
- else
- devgroups = newnm;
- oldnm = newnm;
- }
-
- fclose(fil);
-}
-
-/* get devgroup id for name, -1 if error/not found */
-static int devgroup_name2id(const char* name)
-{
- struct devgroupname* cur;
-
- if ((devgroups == NULL) && (rdberr == 0))
- load_devgroups();
- cur = devgroups;
- if (cur == NULL)
- return -1;
- while (cur) {
- if (!strncmp(name, cur->name, cur->len + 1))
- return cur->id;
- cur = cur->next;
- }
- return -1;
-}
-
-/* get devgroup name for id, NULL if error/not found */
-static const char *devgroup_id2name(int id)
-{
- struct devgroupname* cur;
-
- if ((devgroups == NULL) && (rdberr == 0))
- load_devgroups();
- cur = devgroups;
- if (cur == NULL)
- return NULL;
- while (cur) {
- if (id == cur->id)
- return cur->name;
- cur = cur->next;
- }
- return NULL;
+ const char file[] = "/etc/iproute2/group_map";
+ devgroups = xtables_lmap_init(file);
+ if (devgroups == NULL && errno != ENOENT)
+ fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno));
}
-static int devgroup_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void devgroup_parse(struct xt_option_call *cb)
{
- struct xt_devgroup_info *info = (struct xt_devgroup_info *)(*match)->data;
+ struct xt_devgroup_info *info = cb->data;
unsigned int id;
char *end;
- switch (c) {
- case XT_DEVGROUP_OPT_SRCGROUP:
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- end = optarg;
- info->src_group = strtoul(optarg, &end, 0);
- if (end != optarg && (*end == '/' || *end == '\0')) {
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SRC_GROUP:
+ info->src_group = strtoul(cb->arg, &end, 0);
+ if (end != cb->arg && (*end == '/' || *end == '\0')) {
if (*end == '/')
info->src_mask = strtoul(end+1, &end, 0);
else
info->src_mask = 0xffffffff;
- if (*end != '\0' || end == optarg)
+ if (*end != '\0' || end == cb->arg)
xtables_error(PARAMETER_PROBLEM,
"Bad src-group value `%s'",
- optarg);
+ cb->arg);
} else {
- id = devgroup_name2id(optarg);
+ id = xtables_lmap_name2id(devgroups, cb->arg);
if (id == -1)
xtables_error(PARAMETER_PROBLEM,
"Device group `%s' not found",
- optarg);
+ cb->arg);
info->src_group = id;
info->src_mask = 0xffffffff;
}
- info->flags |= XT_DEVGROUP_MATCH_SRC;
- if (invert)
+ if (cb->invert)
info->flags |= XT_DEVGROUP_INVERT_SRC;
- *flags |= c;
break;
- case XT_DEVGROUP_OPT_DSTGROUP:
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- end = optarg;
- info->dst_group = strtoul(optarg, &end, 0);
- if (end != optarg && (*end == '/' || *end == '\0')) {
+ case O_DST_GROUP:
+ info->dst_group = strtoul(cb->arg, &end, 0);
+ if (end != cb->arg && (*end == '/' || *end == '\0')) {
if (*end == '/')
info->dst_mask = strtoul(end+1, &end, 0);
else
info->dst_mask = 0xffffffff;
- if (*end != '\0' || end == optarg)
+ if (*end != '\0' || end == cb->arg)
xtables_error(PARAMETER_PROBLEM,
"Bad dst-group value `%s'",
- optarg);
+ cb->arg);
} else {
- id = devgroup_name2id(optarg);
+ id = xtables_lmap_name2id(devgroups, cb->arg);
if (id == -1)
xtables_error(PARAMETER_PROBLEM,
"Device group `%s' not found",
- optarg);
+ cb->arg);
info->dst_group = id;
info->dst_mask = 0xffffffff;
}
- info->flags |= XT_DEVGROUP_MATCH_DST;
- if (invert)
+ if (cb->invert)
info->flags |= XT_DEVGROUP_INVERT_DST;
- *flags |= c;
break;
}
- return 1;
}
static void
@@ -228,7 +108,7 @@ print_devgroup(unsigned int id, unsigned int mask, int numeric)
printf("0x%x/0x%x", id, mask);
else {
if (numeric == 0)
- name = devgroup_id2name(id);
+ name = xtables_lmap_id2name(devgroups, id);
if (name)
printf("%s", name);
else
@@ -269,9 +149,9 @@ static void devgroup_save(const void *ip, const struct xt_entry_match *match)
devgroup_show("--", info, 0);
}
-static void devgroup_check(unsigned int flags)
+static void devgroup_check(struct xt_fcheck_call *cb)
{
- if (!flags)
+ if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM,
"devgroup match: You must specify either "
"'--src-group' or '--dst-group'");
@@ -283,12 +163,13 @@ static struct xtables_match devgroup_mt_reg = {
.family = NFPROTO_UNSPEC,
.size = XT_ALIGN(sizeof(struct xt_devgroup_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_devgroup_info)),
+ .init = devgroup_init,
.help = devgroup_help,
- .parse = devgroup_parse,
- .final_check = devgroup_check,
.print = devgroup_print,
.save = devgroup_save,
- .extra_opts = devgroup_opts,
+ .x6_parse = devgroup_parse,
+ .x6_fcheck = devgroup_check,
+ .x6_options = devgroup_opts,
};
void _init(void)
diff --git a/extensions/libxt_length.c b/extensions/libxt_length.c
index a12aefef..4f3a3318 100644
--- a/extensions/libxt_length.c
+++ b/extensions/libxt_length.c
@@ -1,14 +1,11 @@
-/* Shared library add-on to iptables to add packet length matching support. */
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
#include <xtables.h>
#include <linux/netfilter/xt_length.h>
+enum {
+ O_LENGTH = 0,
+};
+
static void length_help(void)
{
printf(
@@ -17,75 +14,21 @@ static void length_help(void)
" of values (inclusive)\n");
}
-static const struct option length_opts[] = {
- {.name = "length", .has_arg = true, .val = '1'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry length_opts[] = {
+ {.name = "length", .id = O_LENGTH, .type = XTTYPE_UINT16RC,
+ .flags = XTOPT_MAND | XTOPT_INVERT},
+ XTOPT_TABLEEND,
};
-static uint16_t
-parse_length(const char *s)
-{
- unsigned int len;
-
- if (!xtables_strtoui(s, NULL, &len, 0, UINT32_MAX))
- xtables_error(PARAMETER_PROBLEM, "length invalid: \"%s\"\n", s);
- else
- return len;
-}
-
-/* If a single value is provided, min and max are both set to the value */
-static void
-parse_lengths(const char *s, struct xt_length_info *info)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(s);
- if ((cp = strchr(buffer, ':')) == NULL)
- info->min = info->max = parse_length(buffer);
- else {
- *cp = '\0';
- cp++;
-
- info->min = buffer[0] ? parse_length(buffer) : 0;
- info->max = cp[0] ? parse_length(cp) : 0xFFFF;
- }
- free(buffer);
-
- if (info->min > info->max)
- xtables_error(PARAMETER_PROBLEM,
- "length min. range value `%u' greater than max. "
- "range value `%u'", info->min, info->max);
-
-}
-
-static int
-length_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void length_parse(struct xt_option_call *cb)
{
- struct xt_length_info *info = (struct xt_length_info *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "length: `--length' may only be "
- "specified once");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- parse_lengths(optarg, info);
- if (invert)
- info->invert = 1;
- *flags = 1;
- break;
- }
- return 1;
-}
+ struct xt_length_info *info = cb->data;
-static void length_check(unsigned int flags)
-{
- if (!flags)
- xtables_error(PARAMETER_PROBLEM,
- "length: You must specify `--length'");
+ xtables_option_parse(cb);
+ info->min = cb->val.u16_range[0];
+ info->max = (cb->nvals == 2) ? cb->val.u16_range[1] : UINT16_MAX;
+ if (cb->invert)
+ info->invert = 1;
}
static void
@@ -118,11 +61,10 @@ static struct xtables_match length_match = {
.size = XT_ALIGN(sizeof(struct xt_length_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_length_info)),
.help = length_help,
- .parse = length_parse,
- .final_check = length_check,
.print = length_print,
.save = length_save,
- .extra_opts = length_opts,
+ .x6_parse = length_parse,
+ .x6_options = length_opts,
};
void _init(void)
diff --git a/extensions/libxt_mark.c b/extensions/libxt_mark.c
index d3c17277..7f8c995c 100644
--- a/extensions/libxt_mark.c
+++ b/extensions/libxt_mark.c
@@ -1,11 +1,5 @@
-/* Shared library add-on to iptables to add NFMARK matching support. */
#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
#include <xtables.h>
#include <linux/netfilter/xt_mark.h>
@@ -15,7 +9,7 @@ struct xt_mark_info {
};
enum {
- F_MARK = 1 << 0,
+ O_MARK = 0,
};
static void mark_mt_help(void)
@@ -25,62 +19,32 @@ static void mark_mt_help(void)
"[!] --mark value[/mask] Match nfmark value with optional mask\n");
}
-static const struct option mark_mt_opts[] = {
- {.name = "mark", .has_arg = true, .val = '1'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry mark_mt_opts[] = {
+ {.name = "mark", .id = O_MARK, .type = XTTYPE_MARKMASK32,
+ .flags = XTOPT_MAND | XTOPT_INVERT},
+ XTOPT_TABLEEND,
};
-static int mark_mt_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void mark_mt_parse(struct xt_option_call *cb)
{
- struct xt_mark_mtinfo1 *info = (void *)(*match)->data;
- unsigned int mark, mask = UINT32_MAX;
- char *end;
-
- switch (c) {
- case '1': /* --mark */
- xtables_param_act(XTF_ONLY_ONCE, "mark", "--mark", *flags & F_MARK);
- if (!xtables_strtoui(optarg, &end, &mark, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg);
- if (*end == '/')
- if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg);
- if (*end != '\0')
- xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg);
-
- if (invert)
- info->invert = true;
- info->mark = mark;
- info->mask = mask;
- *flags |= F_MARK;
- return true;
- }
- return false;
+ struct xt_mark_mtinfo1 *info = cb->data;
+
+ xtables_option_parse(cb);
+ if (cb->invert)
+ info->invert = true;
+ info->mark = cb->val.mark;
+ info->mask = cb->val.mask;
}
-static int
-mark_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void mark_parse(struct xt_option_call *cb)
{
- struct xt_mark_info *markinfo = (struct xt_mark_info *)(*match)->data;
-
- switch (c) {
- char *end;
- case '1':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- markinfo->mark = strtoul(optarg, &end, 0);
- if (*end == '/') {
- markinfo->mask = strtoul(end+1, &end, 0);
- } else
- markinfo->mask = 0xffffffff;
- if (*end != '\0' || end == optarg)
- xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
- if (invert)
- markinfo->invert = 1;
- *flags = 1;
- break;
- }
- return 1;
+ struct xt_mark_info *markinfo = cb->data;
+
+ xtables_option_parse(cb);
+ if (cb->invert)
+ markinfo->invert = 1;
+ markinfo->mark = cb->val.mark;
+ markinfo->mask = cb->val.mask;
}
static void print_mark(unsigned int mark, unsigned int mask)
@@ -91,13 +55,6 @@ static void print_mark(unsigned int mark, unsigned int mask)
printf(" 0x%x", mark);
}
-static void mark_mt_check(unsigned int flags)
-{
- if (flags == 0)
- xtables_error(PARAMETER_PROBLEM,
- "mark match: The --mark option is required");
-}
-
static void
mark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
@@ -154,11 +111,10 @@ static struct xtables_match mark_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_mark_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_mark_info)),
.help = mark_mt_help,
- .parse = mark_parse,
- .final_check = mark_mt_check,
.print = mark_print,
.save = mark_save,
- .extra_opts = mark_mt_opts,
+ .x6_parse = mark_parse,
+ .x6_options = mark_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -168,11 +124,10 @@ static struct xtables_match mark_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
.help = mark_mt_help,
- .parse = mark_mt_parse,
- .final_check = mark_mt_check,
.print = mark_mt_print,
.save = mark_mt_save,
- .extra_opts = mark_mt_opts,
+ .x6_parse = mark_mt_parse,
+ .x6_options = mark_mt_opts,
},
};
diff --git a/extensions/libxt_quota.c b/extensions/libxt_quota.c
index e3699ad7..988f404f 100644
--- a/extensions/libxt_quota.c
+++ b/extensions/libxt_quota.c
@@ -3,18 +3,18 @@
*
* Sam Johnston <samj@samj.net>
*/
-#include <stdbool.h>
-#include <stddef.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
-
#include <linux/netfilter/xt_quota.h>
-static const struct option quota_opts[] = {
- {.name = "quota", .has_arg = true, .val = '1'},
- XT_GETOPT_TABLEEND,
+enum {
+ O_QUOTA = 0,
+};
+
+static const struct xt_option_entry quota_opts[] = {
+ {.name = "quota", .id = O_QUOTA, .type = XTTYPE_UINT64,
+ .flags = XTOPT_MAND | XTOPT_INVERT},
+ XTOPT_TABLEEND,
};
static void quota_help(void)
@@ -40,49 +40,13 @@ quota_save(const void *ip, const struct xt_entry_match *match)
printf(" --quota %llu", (unsigned long long) q->quota);
}
-/* parse quota option */
-static int
-parse_quota(const char *s, uint64_t * quota)
-{
- *quota = strtoull(s, NULL, 10);
-
-#ifdef DEBUG_XT_QUOTA
- printf("Quota: %llu\n", *quota);
-#endif
-
- if (*quota == UINT64_MAX)
- xtables_error(PARAMETER_PROBLEM, "quota invalid: '%s'\n", s);
- else
- return 1;
-}
-
-static int
-quota_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void quota_parse(struct xt_option_call *cb)
{
- struct xt_quota_info *info = (struct xt_quota_info *) (*match)->data;
-
- switch (c) {
- case '1':
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM, "quota: unexpected '!'");
- if (!parse_quota(optarg, &info->quota))
- xtables_error(PARAMETER_PROBLEM,
- "bad quota: '%s'", optarg);
+ struct xt_quota_info *info = cb->data;
- if (invert)
- info->flags |= XT_QUOTA_INVERT;
- *flags |= 1;
- break;
- }
- return 1;
-}
-
-static void quota_check(unsigned int flags)
-{
- if (flags == 0)
- xtables_error(PARAMETER_PROBLEM,
- "quota: the --quota argument must be specified\n");
+ xtables_option_parse(cb);
+ if (cb->invert)
+ info->flags |= XT_QUOTA_INVERT;
}
static struct xtables_match quota_match = {
@@ -92,11 +56,10 @@ static struct xtables_match quota_match = {
.size = XT_ALIGN(sizeof (struct xt_quota_info)),
.userspacesize = offsetof(struct xt_quota_info, master),
.help = quota_help,
- .parse = quota_parse,
- .final_check = quota_check,
.print = quota_print,
.save = quota_save,
- .extra_opts = quota_opts,
+ .x6_parse = quota_parse,
+ .x6_options = quota_opts,
};
void
diff --git a/extensions/libxt_string.c b/extensions/libxt_string.c
index 1030d2e3..eef0b081 100644
--- a/extensions/libxt_string.c
+++ b/extensions/libxt_string.c
@@ -20,18 +20,25 @@
* updated to work with slightly modified
* ipt_string_info.
*/
-#define _GNU_SOURCE 1
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <ctype.h>
#include <xtables.h>
-#include <stddef.h>
#include <linux/netfilter/xt_string.h>
+enum {
+ O_FROM = 0,
+ O_TO,
+ O_ALGO,
+ O_ICASE,
+ O_STRING,
+ O_HEX_STRING,
+ F_STRING = 1 << O_STRING,
+ F_HEX_STRING = 1 << O_HEX_STRING,
+ F_OP_ANY = F_STRING | F_HEX_STRING,
+};
+
static void string_help(void)
{
printf(
@@ -44,15 +51,22 @@ static void string_help(void)
"[!] --hex-string string Match a hex string in a packet\n");
}
-static const struct option string_opts[] = {
- {.name = "from", .has_arg = true, .val = '1'},
- {.name = "to", .has_arg = true, .val = '2'},
- {.name = "algo", .has_arg = true, .val = '3'},
- {.name = "string", .has_arg = true, .val = '4'},
- {.name = "hex-string", .has_arg = true, .val = '5'},
- {.name = "icase", .has_arg = false, .val = '6'},
- XT_GETOPT_TABLEEND,
+#define s struct xt_string_info
+static const struct xt_option_entry string_opts[] = {
+ {.name = "from", .id = O_FROM, .type = XTTYPE_UINT16,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, from_offset)},
+ {.name = "to", .id = O_TO, .type = XTTYPE_UINT16,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, to_offset)},
+ {.name = "algo", .id = O_ALGO, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, algo)},
+ {.name = "string", .id = O_STRING, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT, .excl = F_HEX_STRING},
+ {.name = "hex-string", .id = O_HEX_STRING, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT, .excl = F_STRING},
+ {.name = "icase", .id = O_ICASE, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
+#undef s
static void string_init(struct xt_entry_match *m)
{
@@ -74,17 +88,6 @@ parse_string(const char *s, struct xt_string_info *info)
}
static void
-parse_algo(const char *s, struct xt_string_info *info)
-{
- /* xt_string needs \0 for algo name */
- if (strlen(s) < XT_STRING_MAX_ALGO_NAME_SIZE) {
- strncpy(info->algo, s, XT_STRING_MAX_ALGO_NAME_SIZE);
- return;
- }
- xtables_error(PARAMETER_PROBLEM, "ALGO too long \"%s\"", s);
-}
-
-static void
parse_hex_string(const char *s, struct xt_string_info *info)
{
int i=0, slen, sindex=0, schar;
@@ -162,94 +165,47 @@ parse_hex_string(const char *s, struct xt_string_info *info)
info->patlen = sindex;
}
-#define STRING 0x1
-#define ALGO 0x2
-#define FROM 0x4
-#define TO 0x8
-#define ICASE 0x10
-
-static int
-string_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void string_parse(struct xt_option_call *cb)
{
- struct xt_string_info *stringinfo =
- (struct xt_string_info *)(*match)->data;
- const int revision = (*match)->u.user.revision;
+ struct xt_string_info *stringinfo = cb->data;
+ const unsigned int revision = (*cb->match)->u.user.revision;
- switch (c) {
- case '1':
- if (*flags & FROM)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify multiple --from");
- stringinfo->from_offset = atoi(optarg);
- *flags |= FROM;
- break;
- case '2':
- if (*flags & TO)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify multiple --to");
- stringinfo->to_offset = atoi(optarg);
- *flags |= TO;
- break;
- case '3':
- if (*flags & ALGO)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify multiple --algo");
- parse_algo(optarg, stringinfo);
- *flags |= ALGO;
- break;
- case '4':
- if (*flags & STRING)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify multiple --string");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- parse_string(optarg, stringinfo);
- if (invert) {
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_STRING:
+ parse_string(cb->arg, stringinfo);
+ if (cb->invert) {
if (revision == 0)
stringinfo->u.v0.invert = 1;
else
stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT;
}
- *flags |= STRING;
break;
-
- case '5':
- if (*flags & STRING)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify multiple --hex-string");
-
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- parse_hex_string(optarg, stringinfo); /* sets length */
- if (invert) {
+ case O_HEX_STRING:
+ parse_hex_string(cb->arg, stringinfo); /* sets length */
+ if (cb->invert) {
if (revision == 0)
stringinfo->u.v0.invert = 1;
else
stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT;
}
- *flags |= STRING;
break;
-
- case '6':
+ case O_ICASE:
if (revision == 0)
xtables_error(VERSION_PROBLEM,
"Kernel doesn't support --icase");
stringinfo->u.v1.flags |= XT_STRING_FLAG_IGNORECASE;
- *flags |= ICASE;
break;
}
- return 1;
}
-static void string_check(unsigned int flags)
+static void string_check(struct xt_fcheck_call *cb)
{
- if (!(flags & STRING))
+ if (!(cb->xflags & F_OP_ANY))
xtables_error(PARAMETER_PROBLEM,
"STRING match: You must specify `--string' or "
"`--hex-string'");
- if (!(flags & ALGO))
- xtables_error(PARAMETER_PROBLEM,
- "STRING match: You must specify `--algo'");
}
/* Test to see if the string contains non-printable chars or quotes */
@@ -357,11 +313,11 @@ static struct xtables_match string_mt_reg[] = {
.userspacesize = offsetof(struct xt_string_info, config),
.help = string_help,
.init = string_init,
- .parse = string_parse,
- .final_check = string_check,
.print = string_print,
.save = string_save,
- .extra_opts = string_opts,
+ .x6_parse = string_parse,
+ .x6_fcheck = string_check,
+ .x6_options = string_opts,
},
{
.name = "string",
@@ -372,11 +328,11 @@ static struct xtables_match string_mt_reg[] = {
.userspacesize = offsetof(struct xt_string_info, config),
.help = string_help,
.init = string_init,
- .parse = string_parse,
- .final_check = string_check,
.print = string_print,
.save = string_save,
- .extra_opts = string_opts,
+ .x6_parse = string_parse,
+ .x6_fcheck = string_check,
+ .x6_options = string_opts,
},
};
diff --git a/extensions/libxt_tcpmss.c b/extensions/libxt_tcpmss.c
index 3dc35286..c7c59717 100644
--- a/extensions/libxt_tcpmss.c
+++ b/extensions/libxt_tcpmss.c
@@ -1,14 +1,11 @@
-/* Shared library add-on to iptables to add tcp MSS matching support. */
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
#include <xtables.h>
#include <linux/netfilter/xt_tcpmss.h>
+enum {
+ O_TCPMSS = 0,
+};
+
static void tcpmss_help(void)
{
printf(
@@ -17,71 +14,23 @@ static void tcpmss_help(void)
" (only valid for TCP SYN or SYN/ACK packets)\n");
}
-static const struct option tcpmss_opts[] = {
- {.name = "mss", .has_arg = true, .val = '1'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry tcpmss_opts[] = {
+ {.name = "mss", .id = O_TCPMSS, .type = XTTYPE_UINT16RC,
+ .flags = XTOPT_MAND | XTOPT_INVERT},
+ XTOPT_TABLEEND,
};
-static uint16_t
-parse_tcp_mssvalue(const char *mssvalue)
-{
- unsigned int mssvaluenum;
-
- if (xtables_strtoui(mssvalue, NULL, &mssvaluenum, 0, UINT16_MAX))
- return mssvaluenum;
-
- xtables_error(PARAMETER_PROBLEM,
- "Invalid mss `%s' specified", mssvalue);
-}
-
-static void
-parse_tcp_mssvalues(const char *mssvaluestring,
- uint16_t *mss_min, uint16_t *mss_max)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(mssvaluestring);
- if ((cp = strchr(buffer, ':')) == NULL)
- *mss_min = *mss_max = parse_tcp_mssvalue(buffer);
- else {
- *cp = '\0';
- cp++;
-
- *mss_min = buffer[0] ? parse_tcp_mssvalue(buffer) : 0;
- *mss_max = cp[0] ? parse_tcp_mssvalue(cp) : 0xFFFF;
- }
- free(buffer);
-}
-
-static int
-tcpmss_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- struct xt_tcpmss_match_info *mssinfo =
- (struct xt_tcpmss_match_info *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--mss' allowed");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- parse_tcp_mssvalues(optarg,
- &mssinfo->mss_min, &mssinfo->mss_max);
- if (invert)
- mssinfo->invert = 1;
- *flags = 1;
- break;
- }
- return 1;
-}
-
-static void tcpmss_check(unsigned int flags)
+static void tcpmss_parse(struct xt_option_call *cb)
{
- if (!flags)
- xtables_error(PARAMETER_PROBLEM,
- "tcpmss match: You must specify `--mss'");
+ struct xt_tcpmss_match_info *mssinfo = cb->data;
+
+ xtables_option_parse(cb);
+ mssinfo->mss_min = cb->val.u16_range[0];
+ mssinfo->mss_max = mssinfo->mss_min;
+ if (cb->nvals == 2)
+ mssinfo->mss_max = cb->val.u16_range[1];
+ if (cb->invert)
+ mssinfo->invert = 1;
}
static void
@@ -114,11 +63,10 @@ static struct xtables_match tcpmss_match = {
.size = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
.help = tcpmss_help,
- .parse = tcpmss_parse,
- .final_check = tcpmss_check,
.print = tcpmss_print,
.save = tcpmss_save,
- .extra_opts = tcpmss_opts,
+ .x6_parse = tcpmss_parse,
+ .x6_options = tcpmss_opts,
};
void _init(void)
diff --git a/include/xtables.h.in b/include/xtables.h.in
index b4915c41..b0802855 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -50,13 +50,28 @@ struct in_addr;
* %XTTYPE_UINT*: standard integer
* %XTTYPE_UINT*RC: colon-separated range of standard integers
* %XTTYPE_STRING: arbitrary string
+ * %XTTYPE_MARKMASK32: 32-bit mark with optional mask
+ * %XTTYPE_SYSLOGLEVEL: syslog level by name or number
+ * %XTTYPE_ONEHOST: one host or address (union nf_inet_addr)
+ * %XTTYPE_PORT: 16-bit port name or number
+ * %XTTYPE_PORT_NE: 16-bit port name or number, stored as network-endian
*/
enum xt_option_type {
XTTYPE_NONE,
XTTYPE_UINT8,
+ XTTYPE_UINT16,
XTTYPE_UINT32,
+ XTTYPE_UINT64,
+ XTTYPE_UINT8RC,
+ XTTYPE_UINT16RC,
XTTYPE_UINT32RC,
+ XTTYPE_UINT64RC,
XTTYPE_STRING,
+ XTTYPE_MARKMASK32,
+ XTTYPE_SYSLOGLEVEL,
+ XTTYPE_ONEHOST,
+ XTTYPE_PORT,
+ XTTYPE_PORT_NE,
};
/**
@@ -111,9 +126,19 @@ struct xt_option_call {
bool invert;
uint8_t nvals;
union {
- uint8_t u8;
+ uint8_t u8, u8_range[2], syslog_level;
+ uint16_t u16, u16_range[2], port;
uint32_t u32, u32_range[2];
+ uint64_t u64, u64_range[2];
+ union nf_inet_addr inetaddr;
+ struct {
+ uint32_t mark, mask;
+ };
} val;
+ union {
+ struct xt_entry_match **match;
+ struct xt_entry_target **target;
+ };
};
/**
@@ -127,6 +152,16 @@ struct xt_fcheck_call {
unsigned int xflags;
};
+/**
+ * A "linear"/linked-list based name<->id map, for files similar to
+ * /etc/iproute2/.
+ */
+struct xtables_lmap {
+ char *name;
+ int id;
+ struct xtables_lmap *next;
+};
+
/* Include file for additions: new matches and targets. */
struct xtables_match
{
@@ -412,6 +447,11 @@ extern void xtables_option_mfcall(struct xtables_match *);
extern void xtables_options_fcheck(const char *, unsigned int,
const struct xt_option_entry *);
+extern struct xtables_lmap *xtables_lmap_init(const char *);
+extern void xtables_lmap_free(struct xtables_lmap *);
+extern int xtables_lmap_name2id(const struct xtables_lmap *, const char *);
+extern const char *xtables_lmap_id2name(const struct xtables_lmap *, int);
+
#ifdef XTABLES_INTERNAL
/* Shipped modules rely on this... */
diff --git a/xtoptions.c b/xtoptions.c
index 631e7a3c..c3cc40e6 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -7,6 +7,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
+#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <limits.h>
@@ -16,6 +17,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <syslog.h>
#include <arpa/inet.h>
#include "xtables.h"
#include "xshared.h"
@@ -24,6 +26,14 @@
((void *)((char *)(cb)->data + (cb)->entry->ptroff))
/**
+ * Simple key-value pairs for syslog levels
+ */
+struct syslog_level {
+ char name[8];
+ uint8_t level;
+};
+
+/**
* Creates getopt options from the x6-style option map, and assigns each a
* getopt id.
*/
@@ -86,11 +96,15 @@ xtables_options_xfrm(struct option *orig_opts, struct option *oldopts,
static void xtopt_parse_int(struct xt_option_call *cb)
{
const struct xt_option_entry *entry = cb->entry;
- unsigned int lmin = 0, lmax = UINT32_MAX;
+ unsigned long long lmin = 0, lmax = UINT32_MAX;
unsigned int value;
if (entry->type == XTTYPE_UINT8)
lmax = UINT8_MAX;
+ else if (entry->type == XTTYPE_UINT16)
+ lmax = UINT16_MAX;
+ else if (entry->type == XTTYPE_UINT64)
+ lmax = UINT64_MAX;
if (cb->entry->min != 0)
lmin = cb->entry->min;
if (cb->entry->max != 0)
@@ -99,17 +113,25 @@ static void xtopt_parse_int(struct xt_option_call *cb)
if (!xtables_strtoui(cb->arg, NULL, &value, lmin, lmax))
xt_params->exit_err(PARAMETER_PROBLEM,
"%s: bad value for option \"--%s\", "
- "or out of range (%u-%u).\n",
+ "or out of range (%llu-%llu).\n",
cb->ext_name, entry->name, lmin, lmax);
if (entry->type == XTTYPE_UINT8) {
cb->val.u8 = value;
if (entry->flags & XTOPT_PUT)
*(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8;
+ } else if (entry->type == XTTYPE_UINT16) {
+ cb->val.u16 = value;
+ if (entry->flags & XTOPT_PUT)
+ *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16;
} else if (entry->type == XTTYPE_UINT32) {
cb->val.u32 = value;
if (entry->flags & XTOPT_PUT)
*(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32;
+ } else if (entry->type == XTTYPE_UINT64) {
+ cb->val.u64 = value;
+ if (entry->flags & XTOPT_PUT)
+ *(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64;
}
}
@@ -126,15 +148,22 @@ static void xtopt_parse_mint(struct xt_option_call *cb)
{
const struct xt_option_entry *entry = cb->entry;
const char *arg = cb->arg;
- uint32_t *put = XTOPT_MKPTR(cb);
+ size_t esize = sizeof(uint32_t);
+ char *put = XTOPT_MKPTR(cb);
unsigned int maxiter, value;
char *end = "";
char sep = ':';
- maxiter = entry->size / sizeof(uint32_t);
+ if (entry->type == XTTYPE_UINT8RC)
+ esize = sizeof(uint8_t);
+ else if (entry->type == XTTYPE_UINT16RC)
+ esize = sizeof(uint16_t);
+ else if (entry->type == XTTYPE_UINT64RC)
+ esize = sizeof(uint64_t);
+ maxiter = entry->size / esize;
if (maxiter == 0)
maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */
- if (entry->size % sizeof(uint32_t) != 0)
+ if (entry->size % esize != 0)
xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does "
"not have proper size\n", __func__);
@@ -154,10 +183,27 @@ static void xtopt_parse_mint(struct xt_option_call *cb)
"%s: Argument to \"--%s\" has unexpected "
"characters.\n", cb->ext_name, entry->name);
++cb->nvals;
- if (cb->nvals < ARRAY_SIZE(cb->val.u32_range))
- cb->val.u32_range[cb->nvals] = value;
- if (entry->flags & XTOPT_PUT)
- *put++ = value;
+ if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) {
+ if (entry->type == XTTYPE_UINT8RC)
+ cb->val.u8_range[cb->nvals] = value;
+ else if (entry->type == XTTYPE_UINT16RC)
+ cb->val.u16_range[cb->nvals] = value;
+ else if (entry->type == XTTYPE_UINT32RC)
+ cb->val.u32_range[cb->nvals] = value;
+ else if (entry->type == XTTYPE_UINT64RC)
+ cb->val.u64_range[cb->nvals] = value;
+ }
+ if (entry->flags & XTOPT_PUT) {
+ if (entry->type == XTTYPE_UINT8RC)
+ *(uint8_t *)put = value;
+ else if (entry->type == XTTYPE_UINT16RC)
+ *(uint16_t *)put = value;
+ else if (entry->type == XTTYPE_UINT32RC)
+ *(uint32_t *)put = value;
+ else if (entry->type == XTTYPE_UINT64RC)
+ *(uint64_t *)put = value;
+ put += esize;
+ }
if (*end == '\0')
break;
}
@@ -186,18 +232,206 @@ static void xtopt_parse_string(struct xt_option_call *cb)
p[z] = '\0';
}
+/**
+ * Validate the input for being conformant to "mark[/mask]".
+ */
+static void xtopt_parse_markmask(struct xt_option_call *cb)
+{
+ unsigned int mark = 0, mask = ~0U;
+ char *end;
+
+ if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX))
+ xt_params->exit_err(PARAMETER_PROBLEM,
+ "%s: bad mark value for option \"--%s\", "
+ "or out of range.\n",
+ cb->ext_name, cb->entry->name);
+ if (*end == '/' &&
+ !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
+ xt_params->exit_err(PARAMETER_PROBLEM,
+ "%s: bad mask value for option \"--%s\", "
+ "or out of range.\n",
+ cb->ext_name, cb->entry->name);
+ if (*end != '\0')
+ xt_params->exit_err(PARAMETER_PROBLEM,
+ "%s: trailing garbage after value "
+ "for option \"--%s\".\n",
+ cb->ext_name, cb->entry->name);
+ cb->val.mark = mark;
+ cb->val.mask = mask;
+}
+
+static int xtopt_sysloglvl_compare(const void *a, const void *b)
+{
+ const char *name = a;
+ const struct syslog_level *entry = b;
+
+ return strcmp(name, entry->name);
+}
+
+static void xtopt_parse_sysloglevel(struct xt_option_call *cb)
+{
+ static const struct syslog_level log_names[] = { /* must be sorted */
+ {"alert", LOG_ALERT},
+ {"crit", LOG_CRIT},
+ {"debug", LOG_DEBUG},
+ {"emerg", LOG_EMERG},
+ {"error", LOG_ERR}, /* deprecated */
+ {"info", LOG_INFO},
+ {"notice", LOG_NOTICE},
+ {"panic", LOG_EMERG}, /* deprecated */
+ {"warning", LOG_WARNING},
+ };
+ const struct syslog_level *e;
+ unsigned int num = 0;
+
+ if (!xtables_strtoui(cb->arg, NULL, &num, 0, 7)) {
+ e = bsearch(cb->arg, log_names, ARRAY_SIZE(log_names),
+ sizeof(*log_names), xtopt_sysloglvl_compare);
+ if (e == NULL)
+ xt_params->exit_err(PARAMETER_PROBLEM,
+ "log level \"%s\" unknown\n", cb->arg);
+ num = e->level;
+ }
+ cb->val.syslog_level = num;
+ if (cb->entry->flags & XTOPT_PUT)
+ *(uint8_t *)XTOPT_MKPTR(cb) = num;
+}
+
+static void *xtables_sa_host(const void *sa, unsigned int afproto)
+{
+ if (afproto == AF_INET6)
+ return &((struct sockaddr_in6 *)sa)->sin6_addr;
+ else if (afproto == AF_INET)
+ return &((struct sockaddr_in *)sa)->sin_addr;
+ return (void *)sa;
+}
+
+static socklen_t xtables_sa_hostlen(unsigned int afproto)
+{
+ if (afproto == AF_INET6)
+ return sizeof(struct in6_addr);
+ else if (afproto == AF_INET)
+ return sizeof(struct in_addr);
+ return 0;
+}
+
+/**
+ * Accepts: a hostname (DNS), or a single inetaddr.
+ */
+static void xtopt_parse_onehost(struct xt_option_call *cb)
+{
+ struct addrinfo hints = {.ai_family = afinfo->family};
+ unsigned int adcount = 0;
+ struct addrinfo *res, *p;
+ int ret;
+
+ ret = getaddrinfo(cb->arg, NULL, &hints, &res);
+ if (ret < 0)
+ xt_params->exit_err(PARAMETER_PROBLEM,
+ "getaddrinfo: %s\n", gai_strerror(ret));
+
+ for (p = res; p != NULL; p = p->ai_next) {
+ if (adcount == 0) {
+ memset(&cb->val.inetaddr, 0, sizeof(cb->val.inetaddr));
+ memcpy(&cb->val.inetaddr,
+ xtables_sa_host(p->ai_addr, p->ai_family),
+ xtables_sa_hostlen(p->ai_family));
+ ++adcount;
+ continue;
+ }
+ if (memcmp(&cb->val.inetaddr,
+ xtables_sa_host(p->ai_addr, p->ai_family),
+ xtables_sa_hostlen(p->ai_family)) != 0)
+ xt_params->exit_err(PARAMETER_PROBLEM,
+ "%s resolves to more than one address\n",
+ cb->arg);
+ }
+
+ freeaddrinfo(res);
+ if (cb->entry->flags & XTOPT_PUT)
+ /* Validation in xtables_option_metavalidate */
+ memcpy(XTOPT_MKPTR(cb), &cb->val.inetaddr,
+ sizeof(cb->val.inetaddr));
+}
+
+/**
+ * @name: port name, or number as a string (e.g. "http" or "80")
+ *
+ * Resolve a port name to a number. Returns the port number in integral
+ * form on success, or <0 on error. (errno will not be set.)
+ */
+static int xtables_getportbyname(const char *name)
+{
+ struct addrinfo *res = NULL, *p;
+ int ret;
+
+ ret = getaddrinfo(NULL, name, NULL, &res);
+ if (ret < 0)
+ return -1;
+ ret = -1;
+ for (p = res; p != NULL; p = p->ai_next) {
+ if (p->ai_family == AF_INET6) {
+ ret = ((struct sockaddr_in6 *)p->ai_addr)->sin6_port;
+ break;
+ } else if (p->ai_family == AF_INET) {
+ ret = ((struct sockaddr_in *)p->ai_addr)->sin_port;
+ break;
+ }
+ }
+ freeaddrinfo(res);
+ return ntohs(ret);
+}
+
+/**
+ * Validate and parse a port specification and put the result into @cb.
+ */
+static void xtopt_parse_port(struct xt_option_call *cb)
+{
+ int ret;
+
+ ret = xtables_getportbyname(cb->arg);
+ if (ret < 0)
+ xt_params->exit_err(PARAMETER_PROBLEM,
+ "Port \"%s\" does not resolve to anything.\n",
+ cb->arg);
+ cb->val.port = ret;
+ if (cb->entry->type == XTTYPE_PORT_NE)
+ cb->val.port = htons(cb->val.port);
+ if (cb->entry->flags & XTOPT_PUT)
+ *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port;
+}
+
static void (*const xtopt_subparse[])(struct xt_option_call *) = {
[XTTYPE_UINT8] = xtopt_parse_int,
+ [XTTYPE_UINT16] = xtopt_parse_int,
[XTTYPE_UINT32] = xtopt_parse_int,
+ [XTTYPE_UINT64] = xtopt_parse_int,
+ [XTTYPE_UINT8RC] = xtopt_parse_mint,
+ [XTTYPE_UINT16RC] = xtopt_parse_mint,
[XTTYPE_UINT32RC] = xtopt_parse_mint,
+ [XTTYPE_UINT64RC] = xtopt_parse_mint,
[XTTYPE_STRING] = xtopt_parse_string,
+ [XTTYPE_MARKMASK32] = xtopt_parse_markmask,
+ [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel,
+ [XTTYPE_ONEHOST] = xtopt_parse_onehost,
+ [XTTYPE_PORT] = xtopt_parse_port,
+ [XTTYPE_PORT_NE] = xtopt_parse_port,
};
static const size_t xtopt_psize[] = {
[XTTYPE_UINT8] = sizeof(uint8_t),
+ [XTTYPE_UINT16] = sizeof(uint16_t),
[XTTYPE_UINT32] = sizeof(uint32_t),
+ [XTTYPE_UINT64] = sizeof(uint64_t),
+ [XTTYPE_UINT8RC] = sizeof(uint8_t[2]),
+ [XTTYPE_UINT16RC] = sizeof(uint16_t[2]),
[XTTYPE_UINT32RC] = sizeof(uint32_t[2]),
+ [XTTYPE_UINT64RC] = sizeof(uint64_t[2]),
[XTTYPE_STRING] = -1,
+ [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t),
+ [XTTYPE_ONEHOST] = sizeof(union nf_inet_addr),
+ [XTTYPE_PORT] = sizeof(uint16_t),
+ [XTTYPE_PORT_NE] = sizeof(uint16_t),
};
/**
@@ -308,6 +542,7 @@ void xtables_option_tpcall(unsigned int c, char **argv, bool invert,
cb.ext_name = t->name;
cb.data = t->t->data;
cb.xflags = t->tflags;
+ cb.target = &t->t;
t->x6_parse(&cb);
t->tflags = cb.xflags;
}
@@ -341,6 +576,7 @@ void xtables_option_mpcall(unsigned int c, char **argv, bool invert,
cb.ext_name = m->name;
cb.data = m->m->data;
cb.xflags = m->mflags;
+ cb.match = &m->m;
m->x6_parse(&cb);
m->mflags = cb.xflags;
}
@@ -450,3 +686,101 @@ void xtables_option_mfcall(struct xtables_match *m)
if (m->x6_options != NULL)
xtables_options_fcheck(m->name, m->mflags, m->x6_options);
}
+
+struct xtables_lmap *xtables_lmap_init(const char *file)
+{
+ struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this;
+ char buf[512];
+ FILE *fp;
+ char *cur, *nxt;
+ int id;
+
+ fp = fopen(file, "re");
+ if (fp == NULL)
+ return NULL;
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ cur = buf;
+ while (isspace(*cur))
+ ++cur;
+ if (*cur == '#' || *cur == '\n' || *cur == '\0')
+ continue;
+
+ /* iproute2 allows hex and dec format */
+ errno = 0;
+ id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10);
+ if (nxt == cur || errno != 0)
+ continue;
+
+ /* same boundaries as in iproute2 */
+ if (id < 0 || id > 255)
+ continue;
+ cur = nxt;
+
+ if (!isspace(*cur))
+ continue;
+ while (isspace(*cur))
+ ++cur;
+ if (*cur == '#' || *cur == '\n' || *cur == '\0')
+ continue;
+ nxt = cur;
+ while (*nxt != '\0' && !isspace(*nxt))
+ ++nxt;
+ if (nxt == cur)
+ continue;
+ *nxt = '\0';
+
+ /* found valid data */
+ lmap_this = malloc(sizeof(*lmap_this));
+ if (lmap_this == NULL) {
+ perror("malloc");
+ goto out;
+ }
+ lmap_this->id = id;
+ lmap_this->name = strdup(cur);
+ if (lmap_this->name == NULL) {
+ free(lmap_this);
+ goto out;
+ }
+ lmap_this->next = NULL;
+
+ if (lmap_prev != NULL)
+ lmap_prev->next = lmap_this;
+ else
+ lmap_head = lmap_this;
+ lmap_prev = lmap_this;
+ }
+
+ fclose(fp);
+ return lmap_head;
+ out:
+ xtables_lmap_free(lmap_head);
+ return NULL;
+}
+
+void xtables_lmap_free(struct xtables_lmap *head)
+{
+ struct xtables_lmap *next;
+
+ for (; head != NULL; head = next) {
+ next = head->next;
+ free(head->name);
+ free(head);
+ }
+}
+
+int xtables_lmap_name2id(const struct xtables_lmap *head, const char *name)
+{
+ for (; head != NULL; head = head->next)
+ if (strcmp(head->name, name) == 0)
+ return head->id;
+ return -1;
+}
+
+const char *xtables_lmap_id2name(const struct xtables_lmap *head, int id)
+{
+ for (; head != NULL; head = head->next)
+ if (head->id == id)
+ return head->name;
+ return NULL;
+}