Merge branch 'opts' of git://dev.medozas.de/iptables
diff --git a/configure.ac b/configure.ac
index eb447e0..38b7b79 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
AC_INIT([iptables], [1.4.10])
# See libtool.info "Libtool's versioning system"
-libxtables_vcurrent=5
+libxtables_vcurrent=6
libxtables_vage=0
AC_CONFIG_HEADERS([config.h])
diff --git a/extensions/libxt_TEE.c b/extensions/libxt_TEE.c
index 00a4de6..fd9a1b2 100644
--- a/extensions/libxt_TEE.c
+++ b/extensions/libxt_TEE.c
@@ -25,15 +25,19 @@
#include <linux/netfilter/xt_TEE.h>
enum {
- FLAG_GATEWAY = 1 << 0,
- FLAG_OIF = 1 << 1,
+ O_GATEWAY = 0,
+ O_OIF,
};
-static const struct option tee_tg_opts[] = {
- {.name = "gateway", .has_arg = true, .val = 'g'},
- {.name = "oif", .has_arg = true, .val = 'o'},
- {NULL},
+#define s struct xt_tee_tginfo
+static const struct xt_option_entry tee_tg_opts[] = {
+ {.name = "gateway", .id = O_GATEWAY, .type = XTTYPE_ONEHOST,
+ .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, gw)},
+ {.name = "oif", .id = O_OIF, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, oif)},
+ XTOPT_TABLEEND,
};
+#undef s
static void tee_tg_help(void)
{
@@ -44,83 +48,6 @@
"\n");
}
-static int tee_tg_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct xt_tee_tginfo *info = (void *)(*target)->data;
- const struct in_addr *ia;
-
- switch (c) {
- case 'g':
- if (*flags & FLAG_GATEWAY)
- xtables_error(PARAMETER_PROBLEM,
- "Cannot specify --gateway more than once");
-
- ia = xtables_numeric_to_ipaddr(optarg);
- if (ia == NULL)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid IP address %s", optarg);
-
- memcpy(&info->gw, ia, sizeof(*ia));
- *flags |= FLAG_GATEWAY;
- return true;
- case 'o':
- if (*flags & FLAG_OIF)
- xtables_error(PARAMETER_PROBLEM,
- "Cannot specify --oif more than once");
- if (strlen(optarg) >= sizeof(info->oif))
- xtables_error(PARAMETER_PROBLEM,
- "oif name too long");
- strcpy(info->oif, optarg);
- *flags |= FLAG_OIF;
- return true;
- }
-
- return false;
-}
-
-static int tee_tg6_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct xt_tee_tginfo *info = (void *)(*target)->data;
- const struct in6_addr *ia;
-
- switch (c) {
- case 'g':
- if (*flags & FLAG_GATEWAY)
- xtables_error(PARAMETER_PROBLEM,
- "Cannot specify --gateway more than once");
-
- ia = xtables_numeric_to_ip6addr(optarg);
- if (ia == NULL)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid IP address %s", optarg);
-
- memcpy(&info->gw, ia, sizeof(*ia));
- *flags |= FLAG_GATEWAY;
- return true;
- case 'o':
- if (*flags & FLAG_OIF)
- xtables_error(PARAMETER_PROBLEM,
- "Cannot specify --oif more than once");
- if (strlen(optarg) >= sizeof(info->oif))
- xtables_error(PARAMETER_PROBLEM,
- "oif name too long");
- strcpy(info->oif, optarg);
- *flags |= FLAG_OIF;
- return true;
- }
-
- return false;
-}
-
-static void tee_tg_check(unsigned int flags)
-{
- if (flags == 0)
- xtables_error(PARAMETER_PROBLEM, "TEE target: "
- "--gateway parameter required");
-}
-
static void tee_tg_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
@@ -173,11 +100,10 @@
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.help = tee_tg_help,
- .parse = tee_tg_parse,
- .final_check = tee_tg_check,
.print = tee_tg_print,
.save = tee_tg_save,
- .extra_opts = tee_tg_opts,
+ .x6_parse = xtables_option_parse,
+ .x6_options = tee_tg_opts,
};
static struct xtables_target tee_tg6_reg = {
@@ -188,11 +114,10 @@
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.help = tee_tg_help,
- .parse = tee_tg6_parse,
- .final_check = tee_tg_check,
.print = tee_tg6_print,
.save = tee_tg6_save,
- .extra_opts = tee_tg_opts,
+ .x6_parse = xtables_option_parse,
+ .x6_options = tee_tg_opts,
};
void _init(void)
diff --git a/extensions/libxt_TOS.c b/extensions/libxt_TOS.c
index 58ff2fc..cef5876 100644
--- a/extensions/libxt_TOS.c
+++ b/extensions/libxt_TOS.c
@@ -2,7 +2,7 @@
* Shared library add-on to iptables to add TOS target support
*
* Copyright © CC Computer Consultants GmbH, 2007
- * Contact: Jan Engelhardt <jengelh@computergmbh.de>
+ * Contact: Jan Engelhardt <jengelh@medozas.de>
*/
#include <getopt.h>
#include <stdbool.h>
@@ -20,20 +20,33 @@
};
enum {
- FLAG_TOS = 1 << 0,
+ O_SET_TOS = 0,
+ O_AND_TOS,
+ O_OR_TOS,
+ O_XOR_TOS,
+ F_SET_TOS = 1 << O_SET_TOS,
+ F_AND_TOS = 1 << O_AND_TOS,
+ F_OR_TOS = 1 << O_OR_TOS,
+ F_XOR_TOS = 1 << O_XOR_TOS,
+ F_ANY = F_SET_TOS | F_AND_TOS | F_OR_TOS | F_XOR_TOS,
};
-static const struct option tos_tg_opts_v0[] = {
- {.name = "set-tos", .has_arg = true, .val = '='},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry tos_tg_opts_v0[] = {
+ {.name = "set-tos", .id = O_SET_TOS, .type = XTTYPE_TOSMASK,
+ .excl = F_ANY, .max = 0xFF},
+ XTOPT_TABLEEND,
};
-static const struct option tos_tg_opts[] = {
- {.name = "set-tos", .has_arg = true, .val = '='},
- {.name = "and-tos", .has_arg = true, .val = '&'},
- {.name = "or-tos", .has_arg = true, .val = '|'},
- {.name = "xor-tos", .has_arg = true, .val = '^'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry tos_tg_opts[] = {
+ {.name = "set-tos", .id = O_SET_TOS, .type = XTTYPE_TOSMASK,
+ .excl = F_ANY, .max = 0x3F},
+ {.name = "and-tos", .id = O_AND_TOS, .type = XTTYPE_UINT8,
+ .excl = F_ANY},
+ {.name = "or-tos", .id = O_OR_TOS, .type = XTTYPE_UINT8,
+ .excl = F_ANY},
+ {.name = "xor-tos", .id = O_XOR_TOS, .type = XTTYPE_UINT8,
+ .excl = F_ANY},
+ XTOPT_TABLEEND,
};
static void tos_tg_help_v0(void)
@@ -78,84 +91,48 @@
);
}
-static int tos_tg_parse_v0(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void tos_tg_parse_v0(struct xt_option_call *cb)
{
- struct ipt_tos_target_info *info = (void *)(*target)->data;
- struct tos_value_mask tvm;
+ struct ipt_tos_target_info *info = cb->data;
- switch (c) {
- case '=':
- xtables_param_act(XTF_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS);
- xtables_param_act(XTF_NO_INVERT, "TOS", "--set-tos", invert);
- if (!tos_parse_symbolic(optarg, &tvm, 0xFF))
- xtables_param_act(XTF_BAD_VALUE, "TOS", "--set-tos", optarg);
- if (tvm.mask != 0xFF)
- xtables_error(PARAMETER_PROBLEM, "tos match: Your kernel "
- "is too old to support anything besides "
- "/0xFF as a mask.");
- info->tos = tvm.value;
- *flags |= FLAG_TOS;
- return true;
- }
-
- return false;
+ xtables_option_parse(cb);
+ if (cb->val.tos_mask != 0xFF)
+ xtables_error(PARAMETER_PROBLEM, "tos match: Your kernel "
+ "is too old to support anything besides "
+ "/0xFF as a mask.");
+ info->tos = cb->val.tos_value;
}
-static int tos_tg_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void tos_tg_parse(struct xt_option_call *cb)
{
- struct xt_tos_target_info *info = (void *)(*target)->data;
- struct tos_value_mask tvm;
- unsigned int bits;
+ struct xt_tos_target_info *info = cb->data;
- switch (c) {
- case '=': /* --set-tos */
- xtables_param_act(XTF_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS);
- xtables_param_act(XTF_NO_INVERT, "TOS", "--set-tos", invert);
- if (!tos_parse_symbolic(optarg, &tvm, 0x3F))
- xtables_param_act(XTF_BAD_VALUE, "TOS", "--set-tos", optarg);
- info->tos_value = tvm.value;
- info->tos_mask = tvm.mask;
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SET_TOS:
+ info->tos_value = cb->val.tos_value;
+ info->tos_mask = cb->val.tos_mask;
break;
-
- case '&': /* --and-tos */
- xtables_param_act(XTF_ONLY_ONCE, "TOS", "--and-tos", *flags & FLAG_TOS);
- xtables_param_act(XTF_NO_INVERT, "TOS", "--and-tos", invert);
- if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX))
- xtables_param_act(XTF_BAD_VALUE, "TOS", "--and-tos", optarg);
+ case O_AND_TOS:
info->tos_value = 0;
- info->tos_mask = ~bits;
+ info->tos_mask = ~cb->val.u8;
break;
-
- case '|': /* --or-tos */
- xtables_param_act(XTF_ONLY_ONCE, "TOS", "--or-tos", *flags & FLAG_TOS);
- xtables_param_act(XTF_NO_INVERT, "TOS", "--or-tos", invert);
- if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX))
- xtables_param_act(XTF_BAD_VALUE, "TOS", "--or-tos", optarg);
- info->tos_value = bits;
- info->tos_mask = bits;
+ case O_OR_TOS:
+ info->tos_value = cb->val.u8;
+ info->tos_mask = cb->val.u8;
break;
-
- case '^': /* --xor-tos */
- xtables_param_act(XTF_ONLY_ONCE, "TOS", "--xor-tos", *flags & FLAG_TOS);
- xtables_param_act(XTF_NO_INVERT, "TOS", "--xor-tos", invert);
- if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX))
- xtables_param_act(XTF_BAD_VALUE, "TOS", "--xor-tos", optarg);
- info->tos_value = bits;
+ case O_XOR_TOS:
+ info->tos_value = cb->val.u8;
info->tos_mask = 0;
break;
}
-
- *flags |= FLAG_TOS;
- return true;
}
-static void tos_tg_check(unsigned int flags)
+static void tos_tg_check(struct xt_fcheck_call *cb)
{
- if (flags == 0)
+ if (!(cb->xflags & F_ANY))
xtables_error(PARAMETER_PROBLEM,
- "TOS: The --set-tos parameter is required");
+ "TOS: An action is required");
}
static void tos_tg_print_v0(const void *ip,
@@ -215,11 +192,11 @@
.size = XT_ALIGN(sizeof(struct xt_tos_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
.help = tos_tg_help_v0,
- .parse = tos_tg_parse_v0,
- .final_check = tos_tg_check,
.print = tos_tg_print_v0,
.save = tos_tg_save_v0,
- .extra_opts = tos_tg_opts_v0,
+ .x6_parse = tos_tg_parse_v0,
+ .x6_fcheck = tos_tg_check,
+ .x6_options = tos_tg_opts_v0,
},
{
.version = XTABLES_VERSION,
@@ -229,11 +206,11 @@
.size = XT_ALIGN(sizeof(struct xt_tos_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
.help = tos_tg_help,
- .parse = tos_tg_parse,
- .final_check = tos_tg_check,
.print = tos_tg_print,
.save = tos_tg_save,
- .extra_opts = tos_tg_opts,
+ .x6_parse = tos_tg_parse,
+ .x6_fcheck = tos_tg_check,
+ .x6_options = tos_tg_opts,
},
};
diff --git a/extensions/libxt_dccp.c b/extensions/libxt_dccp.c
index ee8e009..5aff262 100644
--- a/extensions/libxt_dccp.c
+++ b/extensions/libxt_dccp.c
@@ -5,15 +5,12 @@
* This program is distributed under the terms of GNU GPL v2, 1991
*
*/
-#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <netdb.h>
-#include <ctype.h>
-
-#include <netinet/in.h>
+#include <arpa/inet.h>
#include <xtables.h>
#include <linux/dccp.h>
#include <linux/netfilter/x_tables.h>
@@ -26,6 +23,13 @@
#define DEBUGP(format, fist...)
#endif
+enum {
+ O_SOURCE_PORT = 0,
+ O_DEST_PORT,
+ O_DCCP_TYPES,
+ O_DCCP_OPTION,
+};
+
static void dccp_help(void)
{
printf(
@@ -36,41 +40,23 @@
" --dport ...\n");
}
-static const struct option dccp_opts[] = {
- {.name = "source-port", .has_arg = true, .val = '1'},
- {.name = "sport", .has_arg = true, .val = '1'},
- {.name = "destination-port", .has_arg = true, .val = '2'},
- {.name = "dport", .has_arg = true, .val = '2'},
- {.name = "dccp-types", .has_arg = true, .val = '3'},
- {.name = "dccp-option", .has_arg = true, .val = '4'},
- XT_GETOPT_TABLEEND,
+#define s struct xt_dccp_info
+static const struct xt_option_entry dccp_opts[] = {
+ {.name = "source-port", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)},
+ {.name = "sport", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)},
+ {.name = "destination-port", .id = O_DEST_PORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)},
+ {.name = "dport", .id = O_DEST_PORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)},
+ {.name = "dccp-types", .id = O_DCCP_TYPES, .type = XTTYPE_STRING},
+ {.name = "dccp-option", .id = O_DCCP_OPTION, .type = XTTYPE_UINT8,
+ .min = 1, .max = UINT8_MAX, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, option)},
+ XTOPT_TABLEEND,
};
-
-static void
-parse_dccp_ports(const char *portstring,
- uint16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(portstring);
- DEBUGP("%s\n", portstring);
- if ((cp = strchr(buffer, ':')) == NULL) {
- ports[0] = ports[1] = xtables_parse_port(buffer, "dccp");
- }
- else {
- *cp = '\0';
- cp++;
-
- ports[0] = buffer[0] ? xtables_parse_port(buffer, "dccp") : 0;
- ports[1] = cp[0] ? xtables_parse_port(cp, "dccp") : 0xFFFF;
-
- if (ports[0] > ports[1])
- xtables_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- }
- free(buffer);
-}
+#undef s
static const char *const dccp_pkt_types[] = {
[DCCP_PKT_REQUEST] = "REQUEST",
@@ -110,74 +96,34 @@
return typemask;
}
-static uint8_t parse_dccp_option(char *optstring)
+static void dccp_parse(struct xt_option_call *cb)
{
- unsigned int ret;
+ struct xt_dccp_info *einfo = cb->data;
- if (!xtables_strtoui(optstring, NULL, &ret, 1, UINT8_MAX))
- xtables_error(PARAMETER_PROBLEM, "Bad DCCP option \"%s\"",
- optstring);
-
- return ret;
-}
-
-static int
-dccp_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- struct xt_dccp_info *einfo
- = (struct xt_dccp_info *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & XT_DCCP_SRC_PORTS)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--source-port' allowed");
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SOURCE_PORT:
einfo->flags |= XT_DCCP_SRC_PORTS;
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- parse_dccp_ports(optarg, einfo->spts);
- if (invert)
+ if (cb->invert)
einfo->invflags |= XT_DCCP_SRC_PORTS;
- *flags |= XT_DCCP_SRC_PORTS;
break;
-
- case '2':
- if (*flags & XT_DCCP_DEST_PORTS)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--destination-port' allowed");
+ case O_DEST_PORT:
einfo->flags |= XT_DCCP_DEST_PORTS;
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- parse_dccp_ports(optarg, einfo->dpts);
- if (invert)
+ if (cb->invert)
einfo->invflags |= XT_DCCP_DEST_PORTS;
- *flags |= XT_DCCP_DEST_PORTS;
break;
-
- case '3':
- if (*flags & XT_DCCP_TYPE)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--dccp-types' allowed");
+ case O_DCCP_TYPES:
einfo->flags |= XT_DCCP_TYPE;
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- einfo->typemask = parse_dccp_types(optarg);
- if (invert)
+ einfo->typemask = parse_dccp_types(cb->arg);
+ if (cb->invert)
einfo->invflags |= XT_DCCP_TYPE;
- *flags |= XT_DCCP_TYPE;
break;
-
- case '4':
- if (*flags & XT_DCCP_OPTION)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--dccp-option' allowed");
+ case O_DCCP_OPTION:
einfo->flags |= XT_DCCP_OPTION;
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- einfo->option = parse_dccp_option(optarg);
- if (invert)
+ if (cb->invert)
einfo->invflags |= XT_DCCP_OPTION;
- *flags |= XT_DCCP_OPTION;
break;
}
- return 1;
}
static char *
@@ -333,10 +279,10 @@
.size = XT_ALIGN(sizeof(struct xt_dccp_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_dccp_info)),
.help = dccp_help,
- .parse = dccp_parse,
.print = dccp_print,
.save = dccp_save,
- .extra_opts = dccp_opts,
+ .x6_parse = dccp_parse,
+ .x6_options = dccp_opts,
};
void _init(void)
diff --git a/extensions/libxt_tos.c b/extensions/libxt_tos.c
index 8b83e18..7646a4f 100644
--- a/extensions/libxt_tos.c
+++ b/extensions/libxt_tos.c
@@ -21,12 +21,19 @@
};
enum {
- FLAG_TOS = 1 << 0,
+ O_TOS = 1 << 0,
};
-static const struct option tos_mt_opts[] = {
- {.name = "tos", .has_arg = true, .val = 't'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry tos_mt_opts_v0[] = {
+ {.name = "tos", .id = O_TOS, .type = XTTYPE_TOSMASK,
+ .flags = XTOPT_MAND, .max = 0xFF},
+ XTOPT_TABLEEND,
+};
+
+static const struct xt_option_entry tos_mt_opts[] = {
+ {.name = "tos", .id = O_TOS, .type = XTTYPE_TOSMASK,
+ .flags = XTOPT_MAND, .max = 0x3F},
+ XTOPT_TABLEEND,
};
static void tos_mt_help(void)
@@ -46,56 +53,29 @@
printf("\n");
}
-static int tos_mt_parse_v0(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void tos_mt_parse_v0(struct xt_option_call *cb)
{
- struct ipt_tos_info *info = (void *)(*match)->data;
- struct tos_value_mask tvm;
+ struct ipt_tos_info *info = cb->data;
- switch (c) {
- case 't':
- xtables_param_act(XTF_ONLY_ONCE, "tos", "--tos", *flags & FLAG_TOS);
- if (!tos_parse_symbolic(optarg, &tvm, 0xFF))
- xtables_param_act(XTF_BAD_VALUE, "tos", "--tos", optarg);
- if (tvm.mask != 0xFF)
- xtables_error(PARAMETER_PROBLEM, "tos: Your kernel is "
- "too old to support anything besides /0xFF "
- "as a mask.");
- info->tos = tvm.value;
- if (invert)
- info->invert = true;
- *flags |= FLAG_TOS;
- return true;
- }
- return false;
+ xtables_option_parse(cb);
+ if (cb->val.tos_mask != 0xFF)
+ xtables_error(PARAMETER_PROBLEM, "tos: Your kernel is "
+ "too old to support anything besides /0xFF "
+ "as a mask.");
+ info->tos = cb->val.tos_value;
+ if (cb->invert)
+ info->invert = true;
}
-static int tos_mt_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void tos_mt_parse(struct xt_option_call *cb)
{
- struct xt_tos_match_info *info = (void *)(*match)->data;
- struct tos_value_mask tvm = {.mask = 0xFF};
+ struct xt_tos_match_info *info = cb->data;
- switch (c) {
- case 't':
- xtables_param_act(XTF_ONLY_ONCE, "tos", "--tos", *flags & FLAG_TOS);
- if (!tos_parse_symbolic(optarg, &tvm, 0x3F))
- xtables_param_act(XTF_BAD_VALUE, "tos", "--tos", optarg);
- info->tos_value = tvm.value;
- info->tos_mask = tvm.mask;
- if (invert)
- info->invert = true;
- *flags |= FLAG_TOS;
- return true;
- }
- return false;
-}
-
-static void tos_mt_check(unsigned int flags)
-{
- if (flags == 0)
- xtables_error(PARAMETER_PROBLEM,
- "tos: --tos parameter required");
+ xtables_option_parse(cb);
+ info->tos_value = cb->val.tos_value;
+ info->tos_mask = cb->val.tos_mask;
+ if (cb->invert)
+ info->invert = true;
}
static void tos_mt_print_v0(const void *ip, const struct xt_entry_match *match,
@@ -150,11 +130,10 @@
.size = XT_ALIGN(sizeof(struct ipt_tos_info)),
.userspacesize = XT_ALIGN(sizeof(struct ipt_tos_info)),
.help = tos_mt_help,
- .parse = tos_mt_parse_v0,
- .final_check = tos_mt_check,
.print = tos_mt_print_v0,
.save = tos_mt_save_v0,
- .extra_opts = tos_mt_opts,
+ .x6_parse = tos_mt_parse_v0,
+ .x6_options = tos_mt_opts_v0,
},
{
.version = XTABLES_VERSION,
@@ -164,11 +143,10 @@
.size = XT_ALIGN(sizeof(struct xt_tos_match_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tos_match_info)),
.help = tos_mt_help,
- .parse = tos_mt_parse,
- .final_check = tos_mt_check,
.print = tos_mt_print,
.save = tos_mt_save,
- .extra_opts = tos_mt_opts,
+ .x6_parse = tos_mt_parse,
+ .x6_options = tos_mt_opts,
},
};
diff --git a/extensions/libxt_udp.c b/extensions/libxt_udp.c
index 505b3c8..d493072 100644
--- a/extensions/libxt_udp.c
+++ b/extensions/libxt_udp.c
@@ -1,14 +1,15 @@
-/* Shared library add-on to iptables to add UDP support. */
-#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <netinet/in.h>
+#include <arpa/inet.h>
#include <xtables.h>
#include <linux/netfilter/xt_tcpudp.h>
+enum {
+ O_SOURCE_PORT = 0,
+ O_DEST_PORT,
+};
+
static void udp_help(void)
{
printf(
@@ -21,36 +22,19 @@
" match destination port(s)\n");
}
-static const struct option udp_opts[] = {
- {.name = "source-port", .has_arg = true, .val = '1'},
- {.name = "sport", .has_arg = true, .val = '1'}, /* synonym */
- {.name = "destination-port", .has_arg = true, .val = '2'},
- {.name = "dport", .has_arg = true, .val = '2'}, /* synonym */
- XT_GETOPT_TABLEEND,
+#define s struct xt_udp
+static const struct xt_option_entry udp_opts[] = {
+ {.name = "source-port", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)},
+ {.name = "sport", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)},
+ {.name = "destination-port", .id = O_DEST_PORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)},
+ {.name = "dport", .id = O_DEST_PORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)},
+ XTOPT_TABLEEND,
};
-
-static void
-parse_udp_ports(const char *portstring, uint16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(portstring);
- if ((cp = strchr(buffer, ':')) == NULL)
- ports[0] = ports[1] = xtables_parse_port(buffer, "udp");
- else {
- *cp = '\0';
- cp++;
-
- ports[0] = buffer[0] ? xtables_parse_port(buffer, "udp") : 0;
- ports[1] = cp[0] ? xtables_parse_port(cp, "udp") : 0xFFFF;
-
- if (ports[0] > ports[1])
- xtables_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- }
- free(buffer);
-}
+#undef s
static void udp_init(struct xt_entry_match *m)
{
@@ -59,40 +43,21 @@
udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF;
}
-#define UDP_SRC_PORTS 0x01
-#define UDP_DST_PORTS 0x02
-
-static int
-udp_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void udp_parse(struct xt_option_call *cb)
{
- struct xt_udp *udpinfo = (struct xt_udp *)(*match)->data;
+ struct xt_udp *udpinfo = cb->data;
- switch (c) {
- case '1':
- if (*flags & UDP_SRC_PORTS)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--source-port' allowed");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- parse_udp_ports(optarg, udpinfo->spts);
- if (invert)
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SOURCE_PORT:
+ if (cb->invert)
udpinfo->invflags |= XT_UDP_INV_SRCPT;
- *flags |= UDP_SRC_PORTS;
break;
-
- case '2':
- if (*flags & UDP_DST_PORTS)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--destination-port' allowed");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- parse_udp_ports(optarg, udpinfo->dpts);
- if (invert)
+ case O_DEST_PORT:
+ if (cb->invert)
udpinfo->invflags |= XT_UDP_INV_DSTPT;
- *flags |= UDP_DST_PORTS;
break;
}
-
- return 1;
}
static char *
@@ -195,10 +160,10 @@
.userspacesize = XT_ALIGN(sizeof(struct xt_udp)),
.help = udp_help,
.init = udp_init,
- .parse = udp_parse,
.print = udp_print,
.save = udp_save,
- .extra_opts = udp_opts,
+ .x6_parse = udp_parse,
+ .x6_options = udp_opts,
};
void
diff --git a/extensions/tos_values.c b/extensions/tos_values.c
index c5efd9d..6dc4743 100644
--- a/extensions/tos_values.c
+++ b/extensions/tos_values.c
@@ -23,64 +23,6 @@
{},
};
-/*
- * tos_parse_numeric - parse sth. like "15/255"
- *
- * @str: input string
- * @tvm: (value/mask) tuple
- * @max: maximum allowed value (must be pow(2,some_int)-1)
- */
-static bool tos_parse_numeric(const char *str, struct tos_value_mask *tvm,
- unsigned int max)
-{
- unsigned int value;
- char *end;
-
- xtables_strtoui(str, &end, &value, 0, max);
- tvm->value = value;
- tvm->mask = max;
-
- if (*end == '/') {
- const char *p = end + 1;
-
- if (!xtables_strtoui(p, &end, &value, 0, max))
- xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"",
- str);
- tvm->mask = value;
- }
-
- if (*end != '\0')
- xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str);
- return true;
-}
-
-/**
- * @str: input string
- * @tvm: (value/mask) tuple
- * @def_mask: mask to force when a symbolic name is used
- */
-static bool tos_parse_symbolic(const char *str, struct tos_value_mask *tvm,
- unsigned int def_mask)
-{
- static const unsigned int max = UINT8_MAX;
- const struct tos_symbol_info *symbol;
- char *tmp;
-
- if (xtables_strtoui(str, &tmp, NULL, 0, max))
- return tos_parse_numeric(str, tvm, max);
-
- /* Do not consider ECN bits when using preset names */
- tvm->mask = def_mask;
- for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
- if (strcasecmp(str, symbol->name) == 0) {
- tvm->value = symbol->value;
- return true;
- }
-
- xtables_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown", str);
- return false;
-}
-
static bool tos_try_print_symbolic(const char *prefix,
uint8_t value, uint8_t mask)
{
diff --git a/include/xtables.h.in b/include/xtables.h.in
index 1d91d4d..5563ecb 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -50,11 +50,14 @@
* %XTTYPE_UINT*: standard integer
* %XTTYPE_UINT*RC: colon-separated range of standard integers
* %XTTYPE_STRING: arbitrary string
+ * %XTTYPE_TOSMASK: 8-bit TOS value with optional mask
* %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
+ * %XTTYPE_PORTRC: colon-separated port range (names acceptable)
+ * %XTTYPE_PORTRC_NE: same as %XTTYPE_PORTRC, stored in network-endian
*/
enum xt_option_type {
XTTYPE_NONE,
@@ -67,11 +70,14 @@
XTTYPE_UINT32RC,
XTTYPE_UINT64RC,
XTTYPE_STRING,
+ XTTYPE_TOSMASK,
XTTYPE_MARKMASK32,
XTTYPE_SYSLOGLEVEL,
XTTYPE_ONEHOST,
XTTYPE_PORT,
XTTYPE_PORT_NE,
+ XTTYPE_PORTRC,
+ XTTYPE_PORTRC_NE,
};
/**
@@ -127,11 +133,14 @@
uint8_t nvals;
union {
uint8_t u8, u8_range[2], syslog_level;
- uint16_t u16, u16_range[2], port;
+ uint16_t u16, u16_range[2], port, port_range[2];
uint32_t u32, u32_range[2];
uint64_t u64, u64_range[2];
union nf_inet_addr inetaddr;
struct {
+ uint8_t tos_value, tos_mask;
+ };
+ struct {
uint32_t mark, mask;
};
} val;
diff --git a/xtoptions.c b/xtoptions.c
index c3cc40e..5b1df88 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -19,8 +19,12 @@
#include <string.h>
#include <syslog.h>
#include <arpa/inet.h>
+#include <netinet/ip.h>
#include "xtables.h"
#include "xshared.h"
+#ifndef IPTOS_NORMALSVC
+# define IPTOS_NORMALSVC 0
+#endif
#define XTOPT_MKPTR(cb) \
((void *)((char *)(cb)->data + (cb)->entry->ptroff))
@@ -33,6 +37,10 @@
uint8_t level;
};
+struct tos_value_mask {
+ uint8_t value, mask;
+};
+
/**
* Creates getopt options from the x6-style option map, and assigns each a
* getopt id.
@@ -232,6 +240,78 @@
p[z] = '\0';
}
+static const struct tos_symbol_info {
+ unsigned char value;
+ const char *name;
+} tos_symbol_names[] = {
+ {IPTOS_LOWDELAY, "Minimize-Delay"},
+ {IPTOS_THROUGHPUT, "Maximize-Throughput"},
+ {IPTOS_RELIABILITY, "Maximize-Reliability"},
+ {IPTOS_MINCOST, "Minimize-Cost"},
+ {IPTOS_NORMALSVC, "Normal-Service"},
+ {},
+};
+
+/*
+ * tos_parse_numeric - parse a string like "15/255"
+ *
+ * @str: input string
+ * @tvm: (value/mask) tuple
+ * @max: maximum allowed value (must be pow(2,some_int)-1)
+ */
+static bool tos_parse_numeric(const char *str, struct xt_option_call *cb,
+ unsigned int max)
+{
+ unsigned int value;
+ char *end;
+
+ xtables_strtoui(str, &end, &value, 0, max);
+ cb->val.tos_value = value;
+ cb->val.tos_mask = max;
+
+ if (*end == '/') {
+ const char *p = end + 1;
+
+ if (!xtables_strtoui(p, &end, &value, 0, max))
+ xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"",
+ str);
+ cb->val.tos_mask = value;
+ }
+
+ if (*end != '\0')
+ xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str);
+ return true;
+}
+
+/**
+ * @str: input string
+ * @tvm: (value/mask) tuple
+ * @def_mask: mask to force when a symbolic name is used
+ */
+static void xtopt_parse_tosmask(struct xt_option_call *cb)
+{
+ const struct tos_symbol_info *symbol;
+ char *tmp;
+
+ if (xtables_strtoui(cb->arg, &tmp, NULL, 0, UINT8_MAX)) {
+ tos_parse_numeric(cb->arg, cb, UINT8_MAX);
+ return;
+ }
+ /*
+ * This is our way we deal with different defaults
+ * for different revisions.
+ */
+ cb->val.tos_mask = cb->entry->max;
+ for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+ if (strcasecmp(cb->arg, symbol->name) == 0) {
+ cb->val.tos_value = symbol->value;
+ return;
+ }
+
+ xtables_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown",
+ cb->arg);
+}
+
/**
* Validate the input for being conformant to "mark[/mask]".
*/
@@ -379,6 +459,8 @@
}
}
freeaddrinfo(res);
+ if (ret < 0)
+ return ret;
return ntohs(ret);
}
@@ -401,6 +483,61 @@
*(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port;
}
+static void xtopt_parse_mport(struct xt_option_call *cb)
+{
+ static const size_t esize = sizeof(uint16_t);
+ const struct xt_option_entry *entry = cb->entry;
+ char *lo_arg, *wp_arg, *arg;
+ unsigned int maxiter;
+ int value;
+
+ wp_arg = lo_arg = strdup(cb->arg);
+ if (lo_arg == NULL)
+ xt_params->exit_err(RESOURCE_PROBLEM, "strdup");
+
+ maxiter = entry->size / esize;
+ if (maxiter == 0)
+ maxiter = 2; /* ARRAY_SIZE(cb->val.port_range) */
+ if (entry->size % esize != 0)
+ xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does "
+ "not have proper size\n", __func__);
+
+ cb->val.port_range[0] = 0;
+ cb->val.port_range[1] = UINT16_MAX;
+ cb->nvals = 0;
+
+ while ((arg = strsep(&wp_arg, ":")) != NULL) {
+ if (cb->nvals == maxiter)
+ xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many "
+ "components for option \"--%s\" (max: %u)\n",
+ cb->ext_name, entry->name, maxiter);
+ if (*arg == '\0') {
+ ++cb->nvals;
+ continue;
+ }
+
+ value = xtables_getportbyname(arg);
+ if (value < 0)
+ xt_params->exit_err(PARAMETER_PROBLEM,
+ "Port \"%s\" does not resolve to "
+ "anything.\n", arg);
+ if (entry->type == XTTYPE_PORTRC_NE)
+ value = htons(value);
+ if (cb->nvals < ARRAY_SIZE(cb->val.port_range))
+ cb->val.port_range[cb->nvals] = value;
+ ++cb->nvals;
+ }
+
+ if (cb->nvals == 1) {
+ cb->val.port_range[1] = cb->val.port_range[0];
+ ++cb->nvals;
+ }
+ if (entry->flags & XTOPT_PUT)
+ memcpy(XTOPT_MKPTR(cb), cb->val.port_range, sizeof(uint16_t) *
+ (cb->nvals <= maxiter ? cb->nvals : maxiter));
+ free(lo_arg);
+}
+
static void (*const xtopt_subparse[])(struct xt_option_call *) = {
[XTTYPE_UINT8] = xtopt_parse_int,
[XTTYPE_UINT16] = xtopt_parse_int,
@@ -411,11 +548,14 @@
[XTTYPE_UINT32RC] = xtopt_parse_mint,
[XTTYPE_UINT64RC] = xtopt_parse_mint,
[XTTYPE_STRING] = xtopt_parse_string,
+ [XTTYPE_TOSMASK] = xtopt_parse_tosmask,
[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,
+ [XTTYPE_PORTRC] = xtopt_parse_mport,
+ [XTTYPE_PORTRC_NE] = xtopt_parse_mport,
};
static const size_t xtopt_psize[] = {
@@ -432,6 +572,8 @@
[XTTYPE_ONEHOST] = sizeof(union nf_inet_addr),
[XTTYPE_PORT] = sizeof(uint16_t),
[XTTYPE_PORT_NE] = sizeof(uint16_t),
+ [XTTYPE_PORTRC] = sizeof(uint16_t[2]),
+ [XTTYPE_PORTRC_NE] = sizeof(uint16_t[2]),
};
/**