summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2011-05-11 13:43:44 +0200
committerPatrick McHardy <kaber@trash.net>2011-05-11 13:43:44 +0200
commit8075493a00e06857147263574333df4073ea671b (patch)
tree6d8b7e0d6179282f0e4037a52c1f834c835780ea
parent77b6230adfe51836ad5b31b41638b43e9b0062e2 (diff)
parent73425492d4c57d34a616d948666ac75ecc612eed (diff)
Merge branch 'opts' of git://dev.medozas.de/iptables
-rw-r--r--extensions/libipt_NETMAP.c106
-rw-r--r--extensions/libxt_TEE.c2
-rw-r--r--extensions/libxt_TPROXY.c6
-rw-r--r--extensions/libxt_connlimit.c176
-rw-r--r--extensions/libxt_conntrack.c670
-rw-r--r--extensions/libxt_hashlimit.c419
-rw-r--r--extensions/libxt_ipvs.c208
-rw-r--r--extensions/libxt_limit.c53
-rw-r--r--extensions/libxt_multiport.c178
-rw-r--r--extensions/libxt_osf.c97
-rw-r--r--extensions/libxt_owner.c288
-rw-r--r--extensions/libxt_policy.c269
-rw-r--r--extensions/libxt_recent.c186
-rw-r--r--include/xtables.h.in28
-rw-r--r--xtoptions.c147
15 files changed, 1050 insertions, 1783 deletions
diff --git a/extensions/libipt_NETMAP.c b/extensions/libipt_NETMAP.c
index 0e85dec1..5c4471a9 100644
--- a/extensions/libipt_NETMAP.c
+++ b/extensions/libipt_NETMAP.c
@@ -1,7 +1,6 @@
/* Shared library add-on to iptables to add static NAT support.
Author: Svenning Soerensen <svenning@post5.tele.dk>
*/
-#include <stdbool.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
@@ -12,9 +11,14 @@
#define MODULENAME "NETMAP"
-static const struct option NETMAP_opts[] = {
- {.name = "to", .has_arg = true, .val = '1'},
- XT_GETOPT_TABLEEND,
+enum {
+ O_TO = 0,
+};
+
+static const struct xt_option_entry NETMAP_opts[] = {
+ {.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_MAND},
+ XTOPT_TABLEEND,
};
static void NETMAP_help(void)
@@ -25,18 +29,6 @@ static void NETMAP_help(void)
NETMAP_opts[0].name);
}
-static uint32_t
-bits2netmask(int bits)
-{
- uint32_t netmask, bm;
-
- if (bits >= 32 || bits < 0)
- return(~0);
- for (netmask = 0, bm = 0x80000000; bits; bits--, bm >>= 1)
- netmask |= bm;
- return htonl(netmask);
-}
-
static int
netmask2bits(uint32_t netmask)
{
@@ -57,82 +49,17 @@ static void NETMAP_init(struct xt_entry_target *t)
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
-
}
-/* Parses network address */
-static void
-parse_to(char *arg, struct nf_nat_range *range)
+static void NETMAP_parse(struct xt_option_call *cb)
{
- char *slash;
- const struct in_addr *ip;
- uint32_t netmask;
- unsigned int bits;
+ struct nf_nat_multi_range *mr = cb->data;
+ struct nf_nat_range *range = &mr->range[0];
+ xtables_option_parse(cb);
range->flags |= IP_NAT_RANGE_MAP_IPS;
- slash = strchr(arg, '/');
- if (slash)
- *slash = '\0';
-
- ip = xtables_numeric_to_ipaddr(arg);
- if (!ip)
- xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
- arg);
- range->min_ip = ip->s_addr;
- if (slash) {
- if (strchr(slash+1, '.')) {
- ip = xtables_numeric_to_ipmask(slash+1);
- if (!ip)
- xtables_error(PARAMETER_PROBLEM, "Bad netmask \"%s\"\n",
- slash+1);
- netmask = ip->s_addr;
- }
- else {
- if (!xtables_strtoui(slash+1, NULL, &bits, 0, 32))
- xtables_error(PARAMETER_PROBLEM, "Bad netmask \"%s\"\n",
- slash+1);
- netmask = bits2netmask(bits);
- }
- /* Don't allow /0 (/1 is probably insane, too) */
- if (netmask == 0)
- xtables_error(PARAMETER_PROBLEM, "Netmask needed\n");
- }
- else
- netmask = ~0;
-
- if (range->min_ip & ~netmask) {
- if (slash)
- *slash = '/';
- xtables_error(PARAMETER_PROBLEM, "Bad network address \"%s\"\n",
- arg);
- }
- range->max_ip = range->min_ip | ~netmask;
-}
-
-static int NETMAP_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct nf_nat_multi_range *mr
- = (struct nf_nat_multi_range *)(*target)->data;
-
- switch (c) {
- case '1':
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --%s", NETMAP_opts[0].name);
-
- parse_to(optarg, &mr->range[0]);
- *flags = 1;
- return 1;
- }
- return 0;
-}
-
-static void NETMAP_check(unsigned int flags)
-{
- if (!flags)
- xtables_error(PARAMETER_PROBLEM,
- MODULENAME" needs --%s", NETMAP_opts[0].name);
+ range->min_ip = cb->val.haddr.ip & cb->val.hmask.ip;
+ range->max_ip = range->min_ip | ~cb->val.hmask.ip;
}
static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
@@ -167,11 +94,10 @@ static struct xtables_target netmap_tg_reg = {
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
.help = NETMAP_help,
.init = NETMAP_init,
- .parse = NETMAP_parse,
- .final_check = NETMAP_check,
+ .x6_parse = NETMAP_parse,
.print = NETMAP_print,
.save = NETMAP_save,
- .extra_opts = NETMAP_opts,
+ .x6_options = NETMAP_opts,
};
void _init(void)
diff --git a/extensions/libxt_TEE.c b/extensions/libxt_TEE.c
index fd9a1b23..c89e5809 100644
--- a/extensions/libxt_TEE.c
+++ b/extensions/libxt_TEE.c
@@ -31,7 +31,7 @@ enum {
#define s struct xt_tee_tginfo
static const struct xt_option_entry tee_tg_opts[] = {
- {.name = "gateway", .id = O_GATEWAY, .type = XTTYPE_ONEHOST,
+ {.name = "gateway", .id = O_GATEWAY, .type = XTTYPE_HOST,
.flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, gw)},
{.name = "oif", .id = O_OIF, .type = XTTYPE_STRING,
.flags = XTOPT_PUT, XTOPT_POINTER(s, oif)},
diff --git a/extensions/libxt_TPROXY.c b/extensions/libxt_TPROXY.c
index 5264ea7d..61646c93 100644
--- a/extensions/libxt_TPROXY.c
+++ b/extensions/libxt_TPROXY.c
@@ -22,7 +22,7 @@ enum {
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 = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST},
{.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
XTOPT_TABLEEND,
};
@@ -31,7 +31,7 @@ static const struct xt_option_entry tproxy_tg0_opts[] = {
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,
+ {.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST,
.flags = XTOPT_PUT, XTOPT_POINTER(s, laddr)},
{.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
XTOPT_TABLEEND,
@@ -129,7 +129,7 @@ static void tproxy_tg0_parse(struct xt_option_call *cb)
info->mark_mask = cb->val.mask;
break;
case P_ADDR:
- info->laddr = cb->val.inetaddr.ip;
+ info->laddr = cb->val.haddr.ip;
break;
}
}
diff --git a/extensions/libxt_connlimit.c b/extensions/libxt_connlimit.c
index badf68c0..a569f86a 100644
--- a/extensions/libxt_connlimit.c
+++ b/extensions/libxt_connlimit.c
@@ -1,18 +1,20 @@
-/* Shared library add-on to iptables to add connection limit support. */
-#include <stdbool.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter/xt_connlimit.h>
enum {
- FL_LIMIT = 1 << 0,
- FL_MASK = 1 << 1,
- FL_ADDR = 1 << 2,
+ O_UPTO = 0,
+ O_ABOVE,
+ O_MASK,
+ O_SADDR,
+ O_DADDR,
+ F_UPTO = 1 << O_UPTO,
+ F_ABOVE = 1 << O_ABOVE,
+ F_MASK = 1 << O_MASK,
+ F_SADDR = 1 << O_SADDR,
+ F_DADDR = 1 << O_DADDR,
};
static void connlimit_help(void)
@@ -26,14 +28,23 @@ static void connlimit_help(void)
" --connlimit-daddr select destination addresses for grouping\n");
}
-static const struct option connlimit_opts[] = {
- {.name = "connlimit-upto", .has_arg = true, .val = 'U'},
- {.name = "connlimit-above", .has_arg = true, .val = 'A'},
- {.name = "connlimit-mask", .has_arg = true, .val = 'M'},
- {.name = "connlimit-saddr", .has_arg = false, .val = 's'},
- {.name = "connlimit-daddr", .has_arg = false, .val = 'd'},
- XT_GETOPT_TABLEEND,
+#define s struct xt_connlimit_info
+static const struct xt_option_entry connlimit_opts[] = {
+ {.name = "connlimit-upto", .id = O_UPTO, .excl = F_ABOVE,
+ .type = XTTYPE_UINT32, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(s, limit)},
+ {.name = "connlimit-above", .id = O_ABOVE, .excl = F_UPTO,
+ .type = XTTYPE_UINT32, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(s, limit)},
+ {.name = "connlimit-mask", .id = O_MASK, .type = XTTYPE_PLENMASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, mask)},
+ {.name = "connlimit-saddr", .id = O_SADDR, .excl = F_DADDR,
+ .type = XTTYPE_NONE},
+ {.name = "connlimit-daddr", .id = O_DADDR, .excl = F_SADDR,
+ .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
+#undef s
static void connlimit_init(struct xt_entry_match *match)
{
@@ -43,111 +54,54 @@ static void connlimit_init(struct xt_entry_match *match)
memset(info->v6_mask, 0xFF, sizeof(info->v6_mask));
}
-static void prefix_to_netmask(uint32_t *mask, unsigned int prefix_len)
+static void connlimit_parse(struct xt_option_call *cb, uint8_t family)
{
- if (prefix_len == 0) {
- mask[0] = mask[1] = mask[2] = mask[3] = 0;
- } else if (prefix_len <= 32) {
- mask[0] <<= 32 - prefix_len;
- mask[1] = mask[2] = mask[3] = 0;
- } else if (prefix_len <= 64) {
- mask[1] <<= 32 - (prefix_len - 32);
- mask[2] = mask[3] = 0;
- } else if (prefix_len <= 96) {
- mask[2] <<= 32 - (prefix_len - 64);
- mask[3] = 0;
- } else if (prefix_len <= 128) {
- mask[3] <<= 32 - (prefix_len - 96);
- }
- mask[0] = htonl(mask[0]);
- mask[1] = htonl(mask[1]);
- mask[2] = htonl(mask[2]);
- mask[3] = htonl(mask[3]);
-}
-
-static int
-connlimit_parse(int c, char **argv, int invert, unsigned int *flags,
- struct xt_entry_match **match, unsigned int family)
-{
- struct xt_connlimit_info *info = (void *)(*match)->data;
- const unsigned int revision = (*match)->u.user.revision;
- char *err;
- int i;
+ struct xt_connlimit_info *info = cb->data;
+ const unsigned int revision = (*cb->match)->u.user.revision;
- switch (c) {
- case 'A': /* --connlimit-above */
- xtables_param_act(XTF_ONLY_ONCE, "connlimit",
- "--connlimit-{upto,above}", *flags & FL_LIMIT);
- *flags |= FL_LIMIT;
- if (invert)
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_ABOVE:
+ if (cb->invert)
info->flags |= XT_CONNLIMIT_INVERT;
- info->limit = strtoul(optarg, NULL, 0);
- return true;
- case 'U': /* --connlimit-upto */
- xtables_param_act(XTF_ONLY_ONCE, "connlimit",
- "--connlimit-{upto,above}", *flags & FL_LIMIT);
- *flags |= FL_LIMIT;
- if (!invert)
+ break;
+ case O_UPTO:
+ if (!cb->invert)
info->flags |= XT_CONNLIMIT_INVERT;
- info->limit = strtoul(optarg, NULL, 0);
- return true;
- case 'M': /* --connlimit-mask */
- xtables_param_act(XTF_NO_INVERT, "connlimit",
- "--connlimit-mask", invert);
- xtables_param_act(XTF_ONLY_ONCE, "connlimit",
- "--connlimit-mask", *flags & FL_MASK);
- *flags |= FL_MASK;
- i = strtoul(optarg, &err, 0);
- if (family == NFPROTO_IPV6) {
- if (i > 128 || *err != '\0')
- xtables_error(PARAMETER_PROBLEM,
- "--connlimit-mask must be between "
- "0 and 128");
- prefix_to_netmask(info->v6_mask, i);
- } else {
- if (i > 32 || *err != '\0')
- xtables_error(PARAMETER_PROBLEM,
- "--connlimit-mask must be between "
- "0 and 32");
- if (i == 0)
- info->v4_mask = 0;
- else
- info->v4_mask = htonl(0xFFFFFFFF << (32 - i));
- }
- return true;
- case 's': /* --connlimit-saddr */
+ break;
+ case O_SADDR:
+ if (revision < 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "xt_connlimit.0 does not support "
+ "--connlimit-daddr");
info->flags &= ~XT_CONNLIMIT_DADDR;
- return true;
- case 'd': /* --connlimit-daddr */
+ break;
+ case O_DADDR:
if (revision < 1)
xtables_error(PARAMETER_PROBLEM,
"xt_connlimit.0 does not support "
"--connlimit-daddr");
info->flags |= XT_CONNLIMIT_DADDR;
- return true;
+ break;
}
- return false;
}
-static int connlimit_parse4(int c, char **argv, int invert,
- unsigned int *flags, const void *entry,
- struct xt_entry_match **match)
+static void connlimit_parse4(struct xt_option_call *cb)
{
- return connlimit_parse(c, argv, invert, flags, match, NFPROTO_IPV4);
+ return connlimit_parse(cb, NFPROTO_IPV4);
}
-static int connlimit_parse6(int c, char **argv, int invert,
- unsigned int *flags, const void *entry,
- struct xt_entry_match **match)
+static void connlimit_parse6(struct xt_option_call *cb)
{
- return connlimit_parse(c, argv, invert, flags, match, NFPROTO_IPV6);
+ return connlimit_parse(cb, NFPROTO_IPV6);
}
-static void connlimit_check(unsigned int flags)
+static void connlimit_check(struct xt_fcheck_call *cb)
{
- if (!(flags & 0x1))
+ if ((cb->xflags & (F_UPTO | F_ABOVE)) == 0)
xtables_error(PARAMETER_PROBLEM,
- "You must specify \"--connlimit-above\"");
+ "You must specify \"--connlimit-above\" or "
+ "\"--connlimit-upto\".");
}
static unsigned int count_bits4(uint32_t mask)
@@ -239,11 +193,11 @@ static struct xtables_match connlimit_mt_reg[] = {
.userspacesize = offsetof(struct xt_connlimit_info, data),
.help = connlimit_help,
.init = connlimit_init,
- .parse = connlimit_parse4,
- .final_check = connlimit_check,
+ .x6_parse = connlimit_parse4,
+ .x6_fcheck = connlimit_check,
.print = connlimit_print4,
.save = connlimit_save4,
- .extra_opts = connlimit_opts,
+ .x6_options = connlimit_opts,
},
{
.name = "connlimit",
@@ -254,11 +208,11 @@ static struct xtables_match connlimit_mt_reg[] = {
.userspacesize = offsetof(struct xt_connlimit_info, data),
.help = connlimit_help,
.init = connlimit_init,
- .parse = connlimit_parse6,
- .final_check = connlimit_check,
+ .x6_parse = connlimit_parse6,
+ .x6_fcheck = connlimit_check,
.print = connlimit_print6,
.save = connlimit_save6,
- .extra_opts = connlimit_opts,
+ .x6_options = connlimit_opts,
},
{
.name = "connlimit",
@@ -269,11 +223,11 @@ static struct xtables_match connlimit_mt_reg[] = {
.userspacesize = offsetof(struct xt_connlimit_info, data),
.help = connlimit_help,
.init = connlimit_init,
- .parse = connlimit_parse4,
- .final_check = connlimit_check,
+ .x6_parse = connlimit_parse4,
+ .x6_fcheck = connlimit_check,
.print = connlimit_print4,
.save = connlimit_save4,
- .extra_opts = connlimit_opts,
+ .x6_options = connlimit_opts,
},
{
.name = "connlimit",
@@ -284,11 +238,11 @@ static struct xtables_match connlimit_mt_reg[] = {
.userspacesize = offsetof(struct xt_connlimit_info, data),
.help = connlimit_help,
.init = connlimit_init,
- .parse = connlimit_parse6,
- .final_check = connlimit_check,
+ .x6_parse = connlimit_parse6,
+ .x6_fcheck = connlimit_check,
.print = connlimit_print6,
.save = connlimit_save6,
- .extra_opts = connlimit_opts,
+ .x6_options = connlimit_opts,
},
};
diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c
index 8312d042..2fb3644d 100644
--- a/extensions/libxt_conntrack.c
+++ b/extensions/libxt_conntrack.c
@@ -6,21 +6,14 @@
* Copyright © CC Computer Consultants GmbH, 2007 - 2008
* Jan Engelhardt <jengelh@computergmbh.de>
*/
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include <getopt.h>
-#include <netdb.h>
#include <stdbool.h>
-#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xtables.h>
-#include <linux/netfilter.h>
#include <linux/netfilter/xt_conntrack.h>
#include <linux/netfilter/nf_conntrack_common.h>
-#include <arpa/inet.h>
struct ip_conntrack_old_tuple {
struct {
@@ -55,6 +48,22 @@ struct xt_conntrack_info {
uint8_t invflags;
};
+enum {
+ O_CTSTATE = 0,
+ O_CTPROTO,
+ O_CTORIGSRC,
+ O_CTORIGDST,
+ O_CTREPLSRC,
+ O_CTREPLDST,
+ O_CTORIGSRCPORT,
+ O_CTORIGDSTPORT,
+ O_CTREPLSRCPORT,
+ O_CTREPLDSTPORT,
+ O_CTSTATUS,
+ O_CTEXPIRE,
+ O_CTDIR,
+};
+
static void conntrack_mt_help(void)
{
printf(
@@ -79,34 +88,59 @@ static void conntrack_mt_help(void)
" --ctdir {ORIGINAL|REPLY} Flow direction of packet\n");
}
-static const struct option conntrack_mt_opts_v0[] = {
- {.name = "ctstate", .has_arg = true, .val = '1'},
- {.name = "ctproto", .has_arg = true, .val = '2'},
- {.name = "ctorigsrc", .has_arg = true, .val = '3'},
- {.name = "ctorigdst", .has_arg = true, .val = '4'},
- {.name = "ctreplsrc", .has_arg = true, .val = '5'},
- {.name = "ctrepldst", .has_arg = true, .val = '6'},
- {.name = "ctstatus", .has_arg = true, .val = '7'},
- {.name = "ctexpire", .has_arg = true, .val = '8'},
- XT_GETOPT_TABLEEND,
+#define s struct xt_conntrack_info /* for v0 */
+static const struct xt_option_entry conntrack_mt_opts_v0[] = {
+ {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT},
+ {.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOST,
+ .flags = XTOPT_INVERT},
+ {.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOST,
+ .flags = XTOPT_INVERT},
+ {.name = "ctreplsrc", .id = O_CTREPLSRC, .type = XTTYPE_HOST,
+ .flags = XTOPT_INVERT},
+ {.name = "ctrepldst", .id = O_CTREPLDST, .type = XTTYPE_HOST,
+ .flags = XTOPT_INVERT},
+ {.name = "ctstatus", .id = O_CTSTATUS, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "ctexpire", .id = O_CTEXPIRE, .type = XTTYPE_UINT32RC,
+ .flags = XTOPT_INVERT},
+ XTOPT_TABLEEND,
};
-
-static const struct option conntrack_mt_opts[] = {
- {.name = "ctstate", .has_arg = true, .val = '1'},
- {.name = "ctproto", .has_arg = true, .val = '2'},
- {.name = "ctorigsrc", .has_arg = true, .val = '3'},
- {.name = "ctorigdst", .has_arg = true, .val = '4'},
- {.name = "ctreplsrc", .has_arg = true, .val = '5'},
- {.name = "ctrepldst", .has_arg = true, .val = '6'},
- {.name = "ctstatus", .has_arg = true, .val = '7'},
- {.name = "ctexpire", .has_arg = true, .val = '8'},
- {.name = "ctorigsrcport", .has_arg = true, .val = 'a'},
- {.name = "ctorigdstport", .has_arg = true, .val = 'b'},
- {.name = "ctreplsrcport", .has_arg = true, .val = 'c'},
- {.name = "ctrepldstport", .has_arg = true, .val = 'd'},
- {.name = "ctdir", .has_arg = true, .val = 'e'},
- {.name = NULL},
+#undef s
+
+#define s struct xt_conntrack_mtinfo3 /* for v1-v3 */
+/* We exploit the fact that v1-v3 share the same layout */
+static const struct xt_option_entry conntrack_mt_opts[] = {
+ {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT},
+ {.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT},
+ {.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT},
+ {.name = "ctreplsrc", .id = O_CTREPLSRC, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT},
+ {.name = "ctrepldst", .id = O_CTREPLDST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT},
+ {.name = "ctstatus", .id = O_CTSTATUS, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "ctexpire", .id = O_CTEXPIRE, .type = XTTYPE_UINT32RC,
+ .flags = XTOPT_INVERT},
+ {.name = "ctorigsrcport", .id = O_CTORIGSRCPORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT},
+ {.name = "ctorigdstport", .id = O_CTORIGDSTPORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT},
+ {.name = "ctreplsrcport", .id = O_CTREPLSRCPORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT},
+ {.name = "ctrepldstport", .id = O_CTREPLDSTPORT, .type = XTTYPE_PORTRC,
+ .flags = XTOPT_INVERT},
+ {.name = "ctdir", .id = O_CTDIR, .type = XTTYPE_STRING},
+ XTOPT_TABLEEND,
};
+#undef s
static int
parse_state(const char *state, size_t len, struct xt_conntrack_info *sinfo)
@@ -320,39 +354,21 @@ conntrack_ps_expires(struct xt_conntrack_mtinfo3 *info, const char *s)
info->expires_max = max;
}
-static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void conntrack_parse(struct xt_option_call *cb)
{
- struct xt_conntrack_info *sinfo = (void *)(*match)->data;
- char *protocol = NULL;
- unsigned int naddrs = 0;
- struct in_addr *addrs = NULL;
+ struct xt_conntrack_info *sinfo = cb->data;
-
- switch (c) {
- case '1':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
- parse_states(optarg, sinfo);
- if (invert) {
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_CTSTATE:
+ parse_states(cb->arg, sinfo);
+ if (cb->invert)
sinfo->invflags |= XT_CONNTRACK_STATE;
- }
- sinfo->flags |= XT_CONNTRACK_STATE;
break;
-
- case '2':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
- if(invert)
+ case O_CTPROTO:
+ if (cb->invert)
sinfo->invflags |= XT_CONNTRACK_PROTO;
-
- /* Canonicalize into lower case */
- for (protocol = optarg; *protocol; protocol++)
- *protocol = tolower(*protocol);
-
- protocol = optarg;
- sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum =
- xtables_parse_protocol(protocol);
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = cb->val.protocol;
if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0
&& (sinfo->invflags & XT_INV_PROTO))
@@ -361,390 +377,151 @@ static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags,
sinfo->flags |= XT_CONNTRACK_PROTO;
break;
-
- case '3':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
- if (invert)
+ case O_CTORIGSRC:
+ if (cb->invert)
sinfo->invflags |= XT_CONNTRACK_ORIGSRC;
-
- xtables_ipparse_any(optarg, &addrs,
- &sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
- &naddrs);
- if(naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
-
- if(naddrs == 1) {
- sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr;
- }
-
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = cb->val.haddr.ip;
sinfo->flags |= XT_CONNTRACK_ORIGSRC;
break;
-
- case '4':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
- if (invert)
+ case O_CTORIGDST:
+ if (cb->invert)
sinfo->invflags |= XT_CONNTRACK_ORIGDST;
-
- xtables_ipparse_any(optarg, &addrs,
- &sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
- &naddrs);
- if(naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
-
- if(naddrs == 1) {
- sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr;
- }
-
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = cb->val.haddr.ip;
sinfo->flags |= XT_CONNTRACK_ORIGDST;
break;
-
- case '5':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
- if (invert)
+ case O_CTREPLSRC:
+ if (cb->invert)
sinfo->invflags |= XT_CONNTRACK_REPLSRC;
-
- xtables_ipparse_any(optarg, &addrs,
- &sinfo->sipmsk[IP_CT_DIR_REPLY],
- &naddrs);
- if(naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
-
- if(naddrs == 1) {
- sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr;
- }
-
+ sinfo->tuple[IP_CT_DIR_REPLY].src.ip = cb->val.haddr.ip;
sinfo->flags |= XT_CONNTRACK_REPLSRC;
break;
-
- case '6':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
- if (invert)
+ case O_CTREPLDST:
+ if (cb->invert)
sinfo->invflags |= XT_CONNTRACK_REPLDST;
-
- xtables_ipparse_any(optarg, &addrs,
- &sinfo->dipmsk[IP_CT_DIR_REPLY],
- &naddrs);
- if(naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
-
- if(naddrs == 1) {
- sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr;
- }
-
+ sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = cb->val.haddr.ip;
sinfo->flags |= XT_CONNTRACK_REPLDST;
break;
-
- case '7':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
- parse_statuses(optarg, sinfo);
- if (invert) {
+ case O_CTSTATUS:
+ parse_statuses(cb->arg, sinfo);
+ if (cb->invert)
sinfo->invflags |= XT_CONNTRACK_STATUS;
- }
sinfo->flags |= XT_CONNTRACK_STATUS;
break;
-
- case '8':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
- parse_expires(optarg, sinfo);
- if (invert) {
+ case O_CTEXPIRE:
+ parse_expires(cb->arg, sinfo);
+ if (cb->invert)
sinfo->invflags |= XT_CONNTRACK_EXPIRES;
- }
sinfo->flags |= XT_CONNTRACK_EXPIRES;
break;
}
-
- *flags = sinfo->flags;
- return 1;
}
-static void
-ct_parse_ports(const char *param, const char *str,
- u_int16_t *port_low, u_int16_t *port_high)
+static void conntrack_mt_parse(struct xt_option_call *cb, uint8_t rev)
{
- unsigned int port;
- char *buf, *cp;
+ struct xt_conntrack_mtinfo3 *info = cb->data;
- buf = strdup(str);
- cp = strchr(buf, ':');
- if (cp != NULL)
- *cp = '\0';
-
- if (!xtables_strtoui(buf, NULL, &port, 0, UINT16_MAX))
- xtables_param_act(XTF_BAD_VALUE, "conntrack", param, buf);
-
- if (port_high == NULL) {
- /* revision 0-2 do not support ranges */
- if (cp != NULL)
- xtables_error(PARAMETER_PROBLEM, "conntrack: "
- "port ranges not supported");
-
- *port_low = htons(port);
- } else {
- *port_low = port;
-
- if (cp != NULL) {
- if (!xtables_strtoui(cp + 1, NULL, &port, 0, UINT16_MAX))
- xtables_param_act(XTF_BAD_VALUE, "conntrack", param, buf);
-
- *port_high = port;
- if (*port_low > *port_high)
- xtables_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- } else
- *port_high = port;
- }
-
- free(buf);
-}
-
-
-static int
-conntrack_mt_parse(int c, bool invert, unsigned int *flags,
- struct xt_conntrack_mtinfo3 *info, bool v3)
-{
- char *p;
-
- switch (c) {
- case '1': /* --ctstate */
- conntrack_ps_states(info, optarg);
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_CTSTATE:
+ conntrack_ps_states(info, cb->arg);
info->match_flags |= XT_CONNTRACK_STATE;
- if (invert)
+ if (cb->invert)
info->invert_flags |= XT_CONNTRACK_STATE;
break;
-
- case '2': /* --ctproto */
- /* Canonicalize into lower case */
- for (p = optarg; *p != '\0'; ++p)
- *p = tolower(*p);
- info->l4proto = xtables_parse_protocol(optarg);
-
+ case O_CTPROTO:
+ info->l4proto = cb->val.protocol;
if (info->l4proto == 0 && (info->invert_flags & XT_INV_PROTO))
xtables_error(PARAMETER_PROBLEM, "conntrack: rule would "
"never match protocol");
info->match_flags |= XT_CONNTRACK_PROTO;
- if (invert)
+ if (cb->invert)
info->invert_flags |= XT_CONNTRACK_PROTO;
break;
-
- case '7': /* --ctstatus */
- conntrack_ps_statuses(info, optarg);
+ case O_CTORIGSRC:
+ info->origsrc_addr = cb->val.haddr;
+ info->origsrc_mask = cb->val.hmask;
+ info->match_flags |= XT_CONNTRACK_ORIGSRC;
+ if (cb->invert)
+ info->invert_flags |= XT_CONNTRACK_ORIGSRC;
+ break;
+ case O_CTORIGDST:
+ info->origdst_addr = cb->val.haddr;
+ info->origdst_mask = cb->val.hmask;
+ info->match_flags |= XT_CONNTRACK_ORIGDST;
+ if (cb->invert)
+ info->invert_flags |= XT_CONNTRACK_ORIGDST;
+ break;
+ case O_CTREPLSRC:
+ info->replsrc_addr = cb->val.haddr;
+ info->replsrc_mask = cb->val.hmask;
+ info->match_flags |= XT_CONNTRACK_REPLSRC;
+ if (cb->invert)
+ info->invert_flags |= XT_CONNTRACK_REPLSRC;
+ break;
+ case O_CTREPLDST:
+ info->repldst_addr = cb->val.haddr;
+ info->repldst_mask = cb->val.hmask;
+ info->match_flags |= XT_CONNTRACK_REPLDST;
+ if (cb->invert)
+ info->invert_flags |= XT_CONNTRACK_REPLDST;
+ break;
+ case O_CTSTATUS:
+ conntrack_ps_statuses(info, cb->arg);
info->match_flags |= XT_CONNTRACK_STATUS;
- if (invert)
+ if (cb->invert)
info->invert_flags |= XT_CONNTRACK_STATUS;
break;
-
- case '8': /* --ctexpire */
- conntrack_ps_expires(info, optarg);
+ case O_CTEXPIRE:
+ conntrack_ps_expires(info, cb->arg);
info->match_flags |= XT_CONNTRACK_EXPIRES;
- if (invert)
+ if (cb->invert)
info->invert_flags |= XT_CONNTRACK_EXPIRES;
break;
-
- case 'a': /* --ctorigsrcport */
- ct_parse_ports("--ctorigsrcport", optarg,
- &info->origsrc_port,
- v3 ? &info->origsrc_port_high : NULL);
-
+ case O_CTORIGSRCPORT:
+ info->origsrc_port = cb->val.port_range[0];
+ info->origsrc_port = (cb->nvals == 2) ? cb->val.port_range[1] :
+ cb->val.port_range[0];
info->match_flags |= XT_CONNTRACK_ORIGSRC_PORT;
- if (invert)
+ if (cb->invert)
info->invert_flags |= XT_CONNTRACK_ORIGSRC_PORT;
break;
-
- case 'b': /* --ctorigdstport */
- ct_parse_ports("--ctorigdstport", optarg,
- &info->origdst_port,
- v3 ? &info->origdst_port_high : NULL);
-
+ case O_CTORIGDSTPORT:
+ info->origdst_port = cb->val.port_range[0];
+ info->origdst_port = (cb->nvals == 2) ? cb->val.port_range[1] :
+ cb->val.port_range[0];
info->match_flags |= XT_CONNTRACK_ORIGDST_PORT;
- if (invert)
+ if (cb->invert)
info->invert_flags |= XT_CONNTRACK_ORIGDST_PORT;
break;
-
- case 'c': /* --ctreplsrcport */
- ct_parse_ports("--ctreplsrcport", optarg,
- &info->replsrc_port,
- v3 ? &info->replsrc_port_high : NULL);
-
+ case O_CTREPLSRCPORT:
+ info->replsrc_port = cb->val.port_range[0];
+ info->replsrc_port = (cb->nvals == 2) ? cb->val.port_range[1] :
+ cb->val.port_range[0];
info->match_flags |= XT_CONNTRACK_REPLSRC_PORT;
- if (invert)
+ if (cb->invert)
info->invert_flags |= XT_CONNTRACK_REPLSRC_PORT;
break;
-
- case 'd': /* --ctrepldstport */
- ct_parse_ports("--ctrepldstport", optarg,
- &info->repldst_port,
- v3 ? &info->repldst_port_high : NULL);
-
+ case O_CTREPLDSTPORT:
+ info->repldst_port = cb->val.port_range[0];
+ info->repldst_port = (cb->nvals == 2) ? cb->val.port_range[1] :
+ cb->val.port_range[0];
info->match_flags |= XT_CONNTRACK_REPLDST_PORT;
- if (invert)
+ if (cb->invert)
info->invert_flags |= XT_CONNTRACK_REPLDST_PORT;
break;
-
- case 'e': /* --ctdir */
- xtables_param_act(XTF_NO_INVERT, "conntrack", "--ctdir", invert);
- if (strcasecmp(optarg, "ORIGINAL") == 0) {
+ case O_CTDIR:
+ if (strcasecmp(cb->arg, "ORIGINAL") == 0) {
info->match_flags |= XT_CONNTRACK_DIRECTION;
info->invert_flags &= ~XT_CONNTRACK_DIRECTION;
- } else if (strcasecmp(optarg, "REPLY") == 0) {
+ } else if (strcasecmp(cb->arg, "REPLY") == 0) {
info->match_flags |= XT_CONNTRACK_DIRECTION;
info->invert_flags |= XT_CONNTRACK_DIRECTION;
} else {
- xtables_param_act(XTF_BAD_VALUE, "conntrack", "--ctdir", optarg);
+ xtables_param_act(XTF_BAD_VALUE, "conntrack", "--ctdir", cb->arg);
}
break;
}
-
- *flags = info->match_flags;
- return true;
-}
-
-static int
-conntrack_mt4_parse(int c, bool invert, unsigned int *flags,
- struct xt_conntrack_mtinfo3 *info, bool v3)
-{
- struct in_addr *addr = NULL;
- unsigned int naddrs = 0;
-
- switch (c) {
- case '3': /* --ctorigsrc */
- xtables_ipparse_any(optarg, &addr, &info->origsrc_mask.in,
- &naddrs);
- if (naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
- if (naddrs == 1)
- memcpy(&info->origsrc_addr.in, addr, sizeof(*addr));
- info->match_flags |= XT_CONNTRACK_ORIGSRC;
- if (invert)
- info->invert_flags |= XT_CONNTRACK_ORIGSRC;
- break;
-
- case '4': /* --ctorigdst */
- xtables_ipparse_any(optarg, &addr, &info->origdst_mask.in,
- &naddrs);
- if (naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
- if (naddrs == 1)
- memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
- info->match_flags |= XT_CONNTRACK_ORIGDST;
- if (invert)
- info->invert_flags |= XT_CONNTRACK_ORIGDST;
- break;
-
- case '5': /* --ctreplsrc */
- xtables_ipparse_any(optarg, &addr, &info->replsrc_mask.in,
- &naddrs);
- if (naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
- if (naddrs == 1)
- memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
- info->match_flags |= XT_CONNTRACK_REPLSRC;
- if (invert)
- info->invert_flags |= XT_CONNTRACK_REPLSRC;
- break;
-
- case '6': /* --ctrepldst */
- xtables_ipparse_any(optarg, &addr, &info->repldst_mask.in,
- &naddrs);
- if (naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
- if (naddrs == 1)
- memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
- info->match_flags |= XT_CONNTRACK_REPLDST;
- if (invert)
- info->invert_flags |= XT_CONNTRACK_REPLDST;
- break;
-
-
- default:
- return conntrack_mt_parse(c, invert, flags, info, v3);
- }
-
- *flags = info->match_flags;
- return true;
-}
-
-static int
-conntrack_mt6_parse(int c, bool invert, unsigned int *flags,
- struct xt_conntrack_mtinfo3 *info, bool v3)
-{
- struct in6_addr *addr = NULL;
- unsigned int naddrs = 0;
-
- switch (c) {
- case '3': /* --ctorigsrc */
- xtables_ip6parse_any(optarg, &addr,
- &info->origsrc_mask.in6, &naddrs);
- if (naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
- if (naddrs == 1)
- memcpy(&info->origsrc_addr.in6, addr, sizeof(*addr));
- info->match_flags |= XT_CONNTRACK_ORIGSRC;
- if (invert)
- info->invert_flags |= XT_CONNTRACK_ORIGSRC;
- break;
-
- case '4': /* --ctorigdst */
- xtables_ip6parse_any(optarg, &addr,
- &info->origdst_mask.in6, &naddrs);
- if (naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
- if (naddrs == 1)
- memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
- info->match_flags |= XT_CONNTRACK_ORIGDST;
- if (invert)
- info->invert_flags |= XT_CONNTRACK_ORIGDST;
- break;
-
- case '5': /* --ctreplsrc */
- xtables_ip6parse_any(optarg, &addr,
- &info->replsrc_mask.in6, &naddrs);
- if (naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
- if (naddrs == 1)
- memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
- info->match_flags |= XT_CONNTRACK_REPLSRC;
- if (invert)
- info->invert_flags |= XT_CONNTRACK_REPLSRC;
- break;
-
- case '6': /* --ctrepldst */
- xtables_ip6parse_any(optarg, &addr,
- &info->repldst_mask.in6, &naddrs);
- if (naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
- if (naddrs == 1)
- memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
- info->match_flags |= XT_CONNTRACK_REPLDST;
- if (invert)
- info->invert_flags |= XT_CONNTRACK_REPLDST;
- break;
-
-
- default:
- return conntrack_mt_parse(c, invert, flags, info, v3);
- }
-
- *flags = info->match_flags;
- return true;
}
#define cinfo_transform(r, l) \
@@ -754,65 +531,56 @@ conntrack_mt6_parse(int c, bool invert, unsigned int *flags,
(r)->status_mask = (l)->status_mask; \
} while (false);
-static int
-conntrack1_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void conntrack1_mt_parse(struct xt_option_call *cb)
{
- struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
+ struct xt_conntrack_mtinfo1 *info = cb->data;
struct xt_conntrack_mtinfo3 up;
+ memset(&up, 0, sizeof(up));
cinfo_transform(&up, info);
- if (!conntrack_mt4_parse(c, invert, flags, &up, false))
- return false;
- cinfo_transform(info, &up);
- return true;
-}
-
-static int
-conntrack1_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
- struct xt_conntrack_mtinfo3 up;
-
- cinfo_transform(&up, info);
- if (!conntrack_mt6_parse(c, invert, flags, &up, false))
- return false;
+ cb->data = &up;
+ conntrack_mt_parse(cb, 3);
+ if (up.origsrc_port != up.origsrc_port_high ||
+ up.origdst_port != up.origdst_port_high ||
+ up.replsrc_port != up.replsrc_port_high ||
+ up.repldst_port != up.repldst_port_high)
+ xtables_error(PARAMETER_PROBLEM,
+ "connlimit rev 1 does not support port ranges");
cinfo_transform(info, &up);
- return true;
+ cb->data = info;
}
-static int
-conntrack2_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void conntrack2_mt_parse(struct xt_option_call *cb)
{
- return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data, false);
-}
+#define cinfo2_transform(r, l) \
+ memcpy((r), (l), offsetof(typeof(*(l)), sizeof(*info));
-static int
-conntrack2_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data, false);
-}
+ struct xt_conntrack_mtinfo2 *info = cb->data;
+ struct xt_conntrack_mtinfo3 up;
-static int
-conntrack3_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data, true);
+ memset(&up, 0, sizeof(up));
+ memcpy(&up, info, sizeof(*info));
+ cb->data = &up;
+ conntrack_mt_parse(cb, 3);
+ if (up.origsrc_port != up.origsrc_port_high ||
+ up.origdst_port != up.origdst_port_high ||
+ up.replsrc_port != up.replsrc_port_high ||
+ up.repldst_port != up.repldst_port_high)
+ xtables_error(PARAMETER_PROBLEM,
+ "connlimit rev 2 does not support port ranges");
+ memcpy(info, &up, sizeof(*info));
+ cb->data = info;
+#undef cinfo2_transform
}
-static int
-conntrack3_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void conntrack3_mt_parse(struct xt_option_call *cb)
{
- return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data, true);
+ conntrack_mt_parse(cb, 3);
}
-static void conntrack_mt_check(unsigned int flags)
+static void conntrack_mt_check(struct xt_fcheck_call *cb)
{
- if (flags == 0)
+ if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM, "conntrack: At least one option "
"is required");
}
@@ -1259,11 +1027,11 @@ static struct xtables_match conntrack_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_conntrack_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_info)),
.help = conntrack_mt_help,
- .parse = conntrack_parse,
- .final_check = conntrack_mt_check,
+ .x6_parse = conntrack_parse,
+ .x6_fcheck = conntrack_mt_check,
.print = conntrack_print,
.save = conntrack_save,
- .extra_opts = conntrack_mt_opts_v0,
+ .x6_options = conntrack_mt_opts_v0,
},
{
.version = XTABLES_VERSION,
@@ -1273,11 +1041,11 @@ static struct xtables_match conntrack_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
.help = conntrack_mt_help,
- .parse = conntrack1_mt4_parse,
- .final_check = conntrack_mt_check,
+ .x6_parse = conntrack1_mt_parse,
+ .x6_fcheck = conntrack_mt_check,
.print = conntrack1_mt4_print,
.save = conntrack1_mt4_save,
- .extra_opts = conntrack_mt_opts,
+ .x6_options = conntrack_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -1287,11 +1055,11 @@ static struct xtables_match conntrack_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
.help = conntrack_mt_help,
- .parse = conntrack1_mt6_parse,
- .final_check = conntrack_mt_check,
+ .x6_parse = conntrack1_mt_parse,
+ .x6_fcheck = conntrack_mt_check,
.print = conntrack1_mt6_print,
.save = conntrack1_mt6_save,
- .extra_opts = conntrack_mt_opts,
+ .x6_options = conntrack_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -1301,11 +1069,11 @@ static struct xtables_match conntrack_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
.help = conntrack_mt_help,
- .parse = conntrack2_mt4_parse,
- .final_check = conntrack_mt_check,
+ .x6_parse = conntrack2_mt_parse,
+ .x6_fcheck = conntrack_mt_check,
.print = conntrack2_mt_print,
.save = conntrack2_mt_save,
- .extra_opts = conntrack_mt_opts,
+ .x6_options = conntrack_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -1315,11 +1083,11 @@ static struct xtables_match conntrack_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
.help = conntrack_mt_help,
- .parse = conntrack2_mt6_parse,
- .final_check = conntrack_mt_check,
+ .x6_parse = conntrack2_mt_parse,
+ .x6_fcheck = conntrack_mt_check,
.print = conntrack2_mt6_print,
.save = conntrack2_mt6_save,
- .extra_opts = conntrack_mt_opts,
+ .x6_options = conntrack_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -1329,11 +1097,11 @@ static struct xtables_match conntrack_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
.help = conntrack_mt_help,
- .parse = conntrack3_mt4_parse,
- .final_check = conntrack_mt_check,
+ .x6_parse = conntrack3_mt_parse,
+ .x6_fcheck = conntrack_mt_check,
.print = conntrack3_mt_print,
.save = conntrack3_mt_save,
- .extra_opts = conntrack_mt_opts,
+ .x6_options = conntrack_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -1343,11 +1111,11 @@ static struct xtables_match conntrack_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
.help = conntrack_mt_help,
- .parse = conntrack3_mt6_parse,
- .final_check = conntrack_mt_check,
+ .x6_parse = conntrack3_mt_parse,
+ .x6_fcheck = conntrack_mt_check,
.print = conntrack3_mt6_print,
.save = conntrack3_mt6_save,
- .extra_opts = conntrack_mt_opts,
+ .x6_options = conntrack_mt_opts,
},
};
diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c
index cd057c5f..e683f9ad 100644
--- a/extensions/libxt_hashlimit.c
+++ b/extensions/libxt_hashlimit.c
@@ -15,9 +15,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
-#include <stddef.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_hashlimit.h>
@@ -45,6 +43,23 @@ static void hashlimit_help(void)
XT_HASHLIMIT_BURST);
}
+enum {
+ O_UPTO = 0,
+ O_ABOVE,
+ O_LIMIT,
+ O_MODE,
+ O_SRCMASK,
+ O_DSTMASK,
+ O_NAME,
+ O_BURST,
+ O_HTABLE_SIZE,
+ O_HTABLE_MAX,
+ O_HTABLE_GCINT,
+ O_HTABLE_EXPIRE,
+ F_UPTO = 1 << O_UPTO,
+ F_ABOVE = 1 << O_ABOVE,
+};
+
static void hashlimit_mt_help(void)
{
printf(
@@ -66,33 +81,64 @@ static void hashlimit_mt_help(void)
"\n", XT_HASHLIMIT_BURST);
}
-static const struct option hashlimit_opts[] = {
- {.name = "hashlimit", .has_arg = true, .val = '%'},
- {.name = "hashlimit-burst", .has_arg = true, .val = '$'},
- {.name = "hashlimit-htable-size", .has_arg = true, .val = '&'},
- {.name = "hashlimit-htable-max", .has_arg = true, .val = '*'},
- {.name = "hashlimit-htable-gcinterval", .has_arg = true, .val = '('},
- {.name = "hashlimit-htable-expire", .has_arg = true, .val = ')'},
- {.name = "hashlimit-mode", .has_arg = true, .val = '_'},
- {.name = "hashlimit-name", .has_arg = true, .val = '"'},
- XT_GETOPT_TABLEEND,
+#define s struct xt_hashlimit_info
+static const struct xt_option_entry hashlimit_opts[] = {
+ {.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
+ .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
+ {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32,
+ .min = 1, .max = 10000, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.burst)},
+ {.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.size)},
+ {.name = "hashlimit-htable-max", .id = O_HTABLE_MAX,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.max)},
+ {.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.gc_interval)},
+ {.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.expire)},
+ {.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND},
+ {.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1},
+ XTOPT_TABLEEND,
};
-
-static const struct option hashlimit_mt_opts[] = {
- {.name = "hashlimit-upto", .has_arg = true, .val = '%'},
- {.name = "hashlimit-above", .has_arg = true, .val = '^'},
- {.name = "hashlimit", .has_arg = true, .val = '%'},
- {.name = "hashlimit-srcmask", .has_arg = true, .val = '<'},
- {.name = "hashlimit-dstmask", .has_arg = true, .val = '>'},
- {.name = "hashlimit-burst", .has_arg = true, .val = '$'},
- {.name = "hashlimit-htable-size", .has_arg = true, .val = '&'},
- {.name = "hashlimit-htable-max", .has_arg = true, .val = '*'},
- {.name = "hashlimit-htable-gcinterval", .has_arg = true, .val = '('},
- {.name = "hashlimit-htable-expire", .has_arg = true, .val = ')'},
- {.name = "hashlimit-mode", .has_arg = true, .val = '_'},
- {.name = "hashlimit-name", .has_arg = true, .val = '"'},
- XT_GETOPT_TABLEEND,
+#undef s
+
+#define s struct xt_hashlimit_mtinfo1
+static const struct xt_option_entry hashlimit_mt_opts[] = {
+ {.name = "hashlimit-upto", .id = O_UPTO, .excl = F_ABOVE,
+ .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
+ {.name = "hashlimit-above", .id = O_ABOVE, .excl = F_UPTO,
+ .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
+ {.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
+ .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, /* old name */
+ {.name = "hashlimit-srcmask", .id = O_SRCMASK, .type = XTTYPE_PLEN},
+ {.name = "hashlimit-dstmask", .id = O_DSTMASK, .type = XTTYPE_PLEN},
+ {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32,
+ .min = 1, .max = 10000, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.burst)},
+ {.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.size)},
+ {.name = "hashlimit-htable-max", .id = O_HTABLE_MAX,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.max)},
+ {.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.gc_interval)},
+ {.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE,
+ .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+ XTOPT_POINTER(s, cfg.expire)},
+ {.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING},
+ {.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1},
+ XTOPT_TABLEEND,
};
+#undef s
static
int parse_rate(const char *rate, uint32_t *val)
@@ -165,7 +211,7 @@ static void hashlimit_mt6_init(struct xt_entry_match *match)
}
/* Parse a 'mode' parameter into the required bitmask */
-static int parse_mode(uint32_t *mode, char *option_arg)
+static int parse_mode(uint32_t *mode, const char *option_arg)
{
char *tok;
char *arg = strdup(option_arg);
@@ -193,280 +239,73 @@ static int parse_mode(uint32_t *mode, char *option_arg)
return 0;
}
-enum {
- PARAM_LIMIT = 1 << 0,
- PARAM_BURST = 1 << 1,
- PARAM_MODE = 1 << 2,
- PARAM_NAME = 1 << 3,
- PARAM_SIZE = 1 << 4,
- PARAM_MAX = 1 << 5,
- PARAM_GCINTERVAL = 1 << 6,
- PARAM_EXPIRE = 1 << 7,
- PARAM_SRCMASK = 1 << 8,
- PARAM_DSTMASK = 1 << 9,
-};
-
-static int
-hashlimit_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void hashlimit_parse(struct xt_option_call *cb)
{
- struct xt_hashlimit_info *r =
- (struct xt_hashlimit_info *)(*match)->data;
- unsigned int num;
-
- switch(c) {
- case '%':
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit",
- *flags & PARAM_LIMIT);
- if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
- if (!parse_rate(optarg, &r->cfg.avg))
- xtables_error(PARAMETER_PROBLEM,
- "bad rate `%s'", optarg);
- *flags |= PARAM_LIMIT;
- break;
+ struct xt_hashlimit_info *info = cb->data;
- case '$':
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-burst",
- *flags & PARAM_BURST);
- if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
- if (!xtables_strtoui(optarg, NULL, &num, 0, 10000))
- xtables_error(PARAMETER_PROBLEM,
- "bad --hashlimit-burst `%s'", optarg);
- r->cfg.burst = num;
- *flags |= PARAM_BURST;
- break;
- case '&':
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-size",
- *flags & PARAM_SIZE);
- if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
- if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
- xtables_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-size: `%s'", optarg);
- r->cfg.size = num;
- *flags |= PARAM_SIZE;
- break;
- case '*':
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-max",
- *flags & PARAM_MAX);
- if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
- if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
- xtables_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-max: `%s'", optarg);
- r->cfg.max = num;
- *flags |= PARAM_MAX;
- break;
- case '(':
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
- "--hashlimit-htable-gcinterval",
- *flags & PARAM_GCINTERVAL);
- if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
- if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
- xtables_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-gcinterval: `%s'",
- optarg);
- /* FIXME: not HZ dependent!! */
- r->cfg.gc_interval = num;
- *flags |= PARAM_GCINTERVAL;
- break;
- case ')':
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
- "--hashlimit-htable-expire", *flags & PARAM_EXPIRE);
- if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
- if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
- xtables_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-expire: `%s'", optarg);
- /* FIXME: not HZ dependent */
- r->cfg.expire = num;
- *flags |= PARAM_EXPIRE;
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_UPTO:
+ if (cb->invert)
+ info->cfg.mode |= XT_HASHLIMIT_INVERT;
+ if (!parse_rate(cb->arg, &info->cfg.avg))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-upto", cb->arg);
break;
- case '_':
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-mode",
- *flags & PARAM_MODE);
- if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
- if (parse_mode(&r->cfg.mode, optarg) < 0)
- xtables_error(PARAMETER_PROBLEM,
- "bad --hashlimit-mode: `%s'\n", optarg);
- *flags |= PARAM_MODE;
+ case O_ABOVE:
+ if (!cb->invert)
+ info->cfg.mode |= XT_HASHLIMIT_INVERT;
+ if (!parse_rate(cb->arg, &info->cfg.avg))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-above", cb->arg);
break;
- case '"':
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-name",
- *flags & PARAM_NAME);
- if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
- if (strlen(optarg) == 0)
- xtables_error(PARAMETER_PROBLEM, "Zero-length name?");
- strncpy(r->name, optarg, sizeof(r->name));
- *flags |= PARAM_NAME;
+ case O_MODE:
+ if (parse_mode(&info->cfg.mode, cb->arg) < 0)
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-mode", cb->arg);
break;
}
-
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "hashlimit does not support invert");
-
- return 1;
}
-static int
-hashlimit_mt_parse(struct xt_hashlimit_mtinfo1 *info, unsigned int *flags,
- int c, int invert, unsigned int maxmask)
+static void hashlimit_mt_parse(struct xt_option_call *cb)
{
- unsigned int num;
+ struct xt_hashlimit_mtinfo1 *info = cb->data;
- switch(c) {
- case '%': /* --hashlimit / --hashlimit-below */
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-upto",
- *flags & PARAM_LIMIT);
- if (invert)
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_UPTO:
+ if (cb->invert)
info->cfg.mode |= XT_HASHLIMIT_INVERT;
- if (!parse_rate(optarg, &info->cfg.avg))
+ if (!parse_rate(cb->arg, &info->cfg.avg))
xtables_param_act(XTF_BAD_VALUE, "hashlimit",
- "--hashlimit-upto", optarg);
- *flags |= PARAM_LIMIT;
- return true;
-
- case '^': /* --hashlimit-above == !--hashlimit-below */
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-above",
- *flags & PARAM_LIMIT);
- if (!invert)
+ "--hashlimit-upto", cb->arg);
+ break;
+ case O_ABOVE:
+ if (!cb->invert)
info->cfg.mode |= XT_HASHLIMIT_INVERT;
- if (!parse_rate(optarg, &info->cfg.avg))
- xtables_param_act(XTF_BAD_VALUE, "hashlimit",
- "--hashlimit-above", optarg);
- *flags |= PARAM_LIMIT;
- return true;
-
- case '$': /* --hashlimit-burst */
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-burst",
- *flags & PARAM_BURST);
- if (!xtables_strtoui(optarg, NULL, &num, 0, 10000))
+ if (!parse_rate(cb->arg, &info->cfg.avg))
xtables_param_act(XTF_BAD_VALUE, "hashlimit",
- "--hashlimit-burst", optarg);
- info->cfg.burst = num;
- *flags |= PARAM_BURST;
- return true;
-
- case '&': /* --hashlimit-htable-size */
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-size",
- *flags & PARAM_SIZE);
- if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "hashlimit",
- "--hashlimit-htable-size", optarg);
- info->cfg.size = num;
- *flags |= PARAM_SIZE;
- return true;
-
- case '*': /* --hashlimit-htable-max */
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-max",
- *flags & PARAM_MAX);
- if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "hashlimit",
- "--hashlimit-htable-max", optarg);
- info->cfg.max = num;
- *flags |= PARAM_MAX;
- return true;
-
- case '(': /* --hashlimit-htable-gcinterval */
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
- "--hashlimit-htable-gcinterval",
- *flags & PARAM_GCINTERVAL);
- if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "hashlimit",
- "--hashlimit-htable-gcinterval", optarg);
- /* FIXME: not HZ dependent!! */
- info->cfg.gc_interval = num;
- *flags |= PARAM_GCINTERVAL;
- return true;
-
- case ')': /* --hashlimit-htable-expire */
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
- "--hashlimit-htable-expire", *flags & PARAM_EXPIRE);
- if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "hashlimit",
- "--hashlimit-htable-expire", optarg);
- /* FIXME: not HZ dependent */
- info->cfg.expire = num;
- *flags |= PARAM_EXPIRE;
- return true;
-
- case '_':
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-mode",
- *flags & PARAM_MODE);
- if (parse_mode(&info->cfg.mode, optarg) < 0)
- xtables_param_act(XTF_BAD_VALUE, "hashlimit",
- "--hashlimit-mode", optarg);
- *flags |= PARAM_MODE;
- return true;
-
- case '"': /* --hashlimit-name */
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-name",
- *flags & PARAM_NAME);
- if (strlen(optarg) == 0)
- xtables_error(PARAMETER_PROBLEM, "Zero-length name?");
- strncpy(info->name, optarg, sizeof(info->name));
- info->name[sizeof(info->name)-1] = '\0';
- *flags |= PARAM_NAME;
- return true;
-
- case '<': /* --hashlimit-srcmask */
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-srcmask",
- *flags & PARAM_SRCMASK);
- if (!xtables_strtoui(optarg, NULL, &num, 0, maxmask))
- xtables_param_act(XTF_BAD_VALUE, "hashlimit",
- "--hashlimit-srcmask", optarg);
- info->cfg.srcmask = num;
- *flags |= PARAM_SRCMASK;
- return true;
-
- case '>': /* --hashlimit-dstmask */
- xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-dstmask",
- *flags & PARAM_DSTMASK);
- if (!xtables_strtoui(optarg, NULL, &num, 0, maxmask))
+ "--hashlimit-above", cb->arg);
+ break;
+ case O_MODE:
+ if (parse_mode(&info->cfg.mode, cb->arg) < 0)
xtables_param_act(XTF_BAD_VALUE, "hashlimit",
- "--hashlimit-dstmask", optarg);
- info->cfg.dstmask = num;
- *flags |= PARAM_DSTMASK;
- return true;
+ "--hashlimit-mode", cb->arg);
+ break;
+ case O_SRCMASK:
+ info->cfg.srcmask = cb->val.hlen;
+ break;
+ case O_DSTMASK:
+ info->cfg.dstmask = cb->val.hlen;
+ break;
}
- return false;
-}
-
-static int
-hashlimit_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- return hashlimit_mt_parse((void *)(*match)->data,
- flags, c, invert, 32);
-}
-
-static int
-hashlimit_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- return hashlimit_mt_parse((void *)(*match)->data,
- flags, c, invert, 128);
}
-static void hashlimit_check(unsigned int flags)
+static void hashlimit_check(struct xt_fcheck_call *cb)
{
- if (!(flags & PARAM_LIMIT))
+ if (!(cb->xflags & (F_UPTO | F_ABOVE)))
xtables_error(PARAMETER_PROBLEM,
"You have to specify --hashlimit");
- if (!(flags & PARAM_MODE))
- xtables_error(PARAMETER_PROBLEM,
- "You have to specify --hashlimit-mode");
- if (!(flags & PARAM_NAME))
- xtables_error(PARAMETER_PROBLEM,
- "You have to specify --hashlimit-name");
-}
-
-static void hashlimit_mt_check(unsigned int flags)
-{
- if (!(flags & PARAM_LIMIT))
- xtables_error(PARAMETER_PROBLEM, "You have to specify "
- "--hashlimit-upto or --hashlimit-above");
- if (!(flags & PARAM_NAME))
- xtables_error(PARAMETER_PROBLEM,
- "You have to specify --hashlimit-name");
}
static const struct rates
@@ -664,11 +503,11 @@ static struct xtables_match hashlimit_mt_reg[] = {
.userspacesize = offsetof(struct xt_hashlimit_info, hinfo),
.help = hashlimit_help,
.init = hashlimit_init,
- .parse = hashlimit_parse,
- .final_check = hashlimit_check,
+ .x6_parse = hashlimit_parse,
+ .x6_fcheck = hashlimit_check,
.print = hashlimit_print,
.save = hashlimit_save,
- .extra_opts = hashlimit_opts,
+ .x6_options = hashlimit_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -679,11 +518,11 @@ static struct xtables_match hashlimit_mt_reg[] = {
.userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
.help = hashlimit_mt_help,
.init = hashlimit_mt4_init,
- .parse = hashlimit_mt4_parse,
- .final_check = hashlimit_mt_check,
+ .x6_parse = hashlimit_mt_parse,
+ .x6_fcheck = hashlimit_check,
.print = hashlimit_mt4_print,
.save = hashlimit_mt4_save,
- .extra_opts = hashlimit_mt_opts,
+ .x6_options = hashlimit_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -694,11 +533,11 @@ static struct xtables_match hashlimit_mt_reg[] = {
.userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
.help = hashlimit_mt_help,
.init = hashlimit_mt6_init,
- .parse = hashlimit_mt6_parse,
- .final_check = hashlimit_mt_check,
+ .x6_parse = hashlimit_mt_parse,
+ .x6_fcheck = hashlimit_check,
.print = hashlimit_mt6_print,
.save = hashlimit_mt6_save,
- .extra_opts = hashlimit_mt_opts,
+ .x6_options = hashlimit_mt_opts,
},
};
diff --git a/extensions/libxt_ipvs.c b/extensions/libxt_ipvs.c
index 89303a11..88d235f6 100644
--- a/extensions/libxt_ipvs.c
+++ b/extensions/libxt_ipvs.c
@@ -5,31 +5,43 @@
*
* Author: Hannes Eder <heder@google.com>
*/
-#include <sys/types.h>
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <getopt.h>
-#include <netdb.h>
#include <stdbool.h>
-#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <xtables.h>
#include <linux/ip_vs.h>
#include <linux/netfilter/xt_ipvs.h>
-static const struct option ipvs_mt_opts[] = {
- { .name = "ipvs", .has_arg = false, .val = '0' },
- { .name = "vproto", .has_arg = true, .val = '1' },
- { .name = "vaddr", .has_arg = true, .val = '2' },
- { .name = "vport", .has_arg = true, .val = '3' },
- { .name = "vdir", .has_arg = true, .val = '4' },
- { .name = "vmethod", .has_arg = true, .val = '5' },
- { .name = "vportctl", .has_arg = true, .val = '6' },
- XT_GETOPT_TABLEEND,
+enum {
+ /* For xt_ipvs: make sure this matches up with %XT_IPVS_*'s order */
+ O_IPVS = 0,
+ O_VPROTO,
+ O_VADDR,
+ O_VPORT,
+ O_VDIR,
+ O_VMETHOD,
+ O_VPORTCTL,
};
+#define s struct xt_ipvs_mtinfo
+static const struct xt_option_entry ipvs_mt_opts[] = {
+ {.name = "ipvs", .id = O_IPVS, .type = XTTYPE_NONE,
+ .flags = XTOPT_INVERT},
+ {.name = "vproto", .id = O_VPROTO, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, l4proto)},
+ {.name = "vaddr", .id = O_VADDR, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT},
+ {.name = "vport", .id = O_VPORT, .type = XTTYPE_PORT,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, vport)},
+ {.name = "vdir", .id = O_VDIR, .type = XTTYPE_STRING},
+ {.name = "vmethod", .id = O_VMETHOD, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "vportctl", .id = O_VPORTCTL, .type = XTTYPE_PORT,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, vportctl)},
+ XTOPT_TABLEEND,
+};
+#undef s
+
static void ipvs_mt_help(void)
{
printf(
@@ -49,152 +61,62 @@ static void ipvs_mt_help(void)
);
}
-static void ipvs_mt_parse_addr_and_mask(const char *arg,
- union nf_inet_addr *address,
- union nf_inet_addr *mask,
- unsigned int family)
-{
- struct in_addr *addr = NULL;
- struct in6_addr *addr6 = NULL;
- unsigned int naddrs = 0;
-
- if (family == NFPROTO_IPV4) {
- xtables_ipparse_any(arg, &addr, &mask->in, &naddrs);
- if (naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
- if (naddrs == 1)
- memcpy(&address->in, addr, sizeof(*addr));
- } else if (family == NFPROTO_IPV6) {
- xtables_ip6parse_any(arg, &addr6, &mask->in6, &naddrs);
- if (naddrs > 1)
- xtables_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
- if (naddrs == 1)
- memcpy(&address->in6, addr6, sizeof(*addr6));
- } else {
- /* Hu? */
- assert(false);
- }
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int ipvs_mt_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match,
- unsigned int family)
+static void ipvs_mt_parse(struct xt_option_call *cb)
{
- struct xt_ipvs_mtinfo *data = (void *)(*match)->data;
- char *p = NULL;
- uint8_t op = 0;
-
- if ('0' <= c && c <= '6') {
- static const int ops[] = {
- XT_IPVS_IPVS_PROPERTY,
- XT_IPVS_PROTO,
- XT_IPVS_VADDR,
- XT_IPVS_VPORT,
- XT_IPVS_DIR,
- XT_IPVS_METHOD,
- XT_IPVS_VPORTCTL
- };
- op = ops[c - '0'];
- } else
- return 0;
-
- if (*flags & op & XT_IPVS_ONCE_MASK)
- goto multiple_use;
-
- switch (c) {
- case '0': /* --ipvs */
- /* Nothing to do here. */
- break;
+ struct xt_ipvs_mtinfo *data = cb->data;
- case '1': /* --vproto */
- /* Canonicalize into lower case */
- for (p = optarg; *p != '\0'; ++p)
- *p = tolower(*p);
-
- data->l4proto = xtables_parse_protocol(optarg);
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_VPROTO:
+ data->l4proto = cb->val.protocol;
break;
-
- case '2': /* --vaddr */
- ipvs_mt_parse_addr_and_mask(optarg, &data->vaddr,
- &data->vmask, family);
+ case O_VADDR:
+ memcpy(&data->vaddr, &cb->val.haddr, sizeof(cb->val.haddr));
+ memcpy(&data->vmask, &cb->val.hmask, sizeof(cb->val.hmask));
break;
-
- case '3': /* --vport */
- data->vport = htons(xtables_parse_port(optarg, "tcp"));
- break;
-
- case '4': /* --vdir */
- xtables_param_act(XTF_NO_INVERT, "ipvs", "--vdir", invert);
- if (strcasecmp(optarg, "ORIGINAL") == 0) {
+ case O_VDIR:
+ if (strcasecmp(cb->arg, "ORIGINAL") == 0) {
data->bitmask |= XT_IPVS_DIR;
data->invert &= ~XT_IPVS_DIR;
- } else if (strcasecmp(optarg, "REPLY") == 0) {
+ } else if (strcasecmp(cb->arg, "REPLY") == 0) {
data->bitmask |= XT_IPVS_DIR;
data->invert |= XT_IPVS_DIR;
} else {
xtables_param_act(XTF_BAD_VALUE,
- "ipvs", "--vdir", optarg);
+ "ipvs", "--vdir", cb->arg);
}
break;
-
- case '5': /* --vmethod */
- if (strcasecmp(optarg, "GATE") == 0)
+ case O_VMETHOD:
+ if (strcasecmp(cb->arg, "GATE") == 0)
data->fwd_method = IP_VS_CONN_F_DROUTE;
- else if (strcasecmp(optarg, "IPIP") == 0)
+ else if (strcasecmp(cb->arg, "IPIP") == 0)
data->fwd_method = IP_VS_CONN_F_TUNNEL;
- else if (strcasecmp(optarg, "MASQ") == 0)
+ else if (strcasecmp(cb->arg, "MASQ") == 0)
data->fwd_method = IP_VS_CONN_F_MASQ;
else
xtables_param_act(XTF_BAD_VALUE,
- "ipvs", "--vmethod", optarg);
- break;
-
- case '6': /* --vportctl */
- data->vportctl = htons(xtables_parse_port(optarg, "tcp"));
+ "ipvs", "--vmethod", cb->arg);
break;
}
-
- if (op & XT_IPVS_ONCE_MASK) {
- if (data->invert & XT_IPVS_IPVS_PROPERTY)
- xtables_error(PARAMETER_PROBLEM,
- "! --ipvs cannot be together with"
- " other options");
- data->bitmask |= XT_IPVS_IPVS_PROPERTY;
- }
-
- data->bitmask |= op;
- if (invert)
- data->invert |= op;
- *flags |= op;
- return 1;
-
-multiple_use:
- xtables_error(PARAMETER_PROBLEM,
- "multiple use of the same IPVS option is not allowed");
+ data->bitmask |= 1 << cb->entry->id;
+ if (cb->invert)
+ data->invert |= 1 << cb->entry->id;
}
-static int ipvs_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void ipvs_mt_check(struct xt_fcheck_call *cb)
{
- return ipvs_mt_parse(c, argv, invert, flags, entry, match,
- NFPROTO_IPV4);
-}
-
-static int ipvs_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- return ipvs_mt_parse(c, argv, invert, flags, entry, match,
- NFPROTO_IPV6);
-}
+ struct xt_ipvs_mtinfo *info = cb->data;
-static void ipvs_mt_check(unsigned int flags)
-{
- if (flags == 0)
+ if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM,
"IPVS: At least one option is required");
+ if (info->bitmask & XT_IPVS_ONCE_MASK) {
+ if (info->invert & XT_IPVS_IPVS_PROPERTY)
+ xtables_error(PARAMETER_PROBLEM,
+ "! --ipvs cannot be together with"
+ " other options");
+ info->bitmask |= XT_IPVS_IPVS_PROPERTY;
+ }
}
/* Shamelessly copied from libxt_conntrack.c */
@@ -332,11 +254,11 @@ static struct xtables_match ipvs_matches_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)),
.help = ipvs_mt_help,
- .parse = ipvs_mt4_parse,
- .final_check = ipvs_mt_check,
+ .x6_parse = ipvs_mt_parse,
+ .x6_fcheck = ipvs_mt_check,
.print = ipvs_mt4_print,
.save = ipvs_mt4_save,
- .extra_opts = ipvs_mt_opts,
+ .x6_options = ipvs_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -346,11 +268,11 @@ static struct xtables_match ipvs_matches_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)),
.help = ipvs_mt_help,
- .parse = ipvs_mt6_parse,
- .final_check = ipvs_mt_check,
+ .x6_parse = ipvs_mt_parse,
+ .x6_fcheck = ipvs_mt_check,
.print = ipvs_mt6_print,
.save = ipvs_mt6_save,
- .extra_opts = ipvs_mt_opts,
+ .x6_options = ipvs_mt_opts,
},
};
diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c
index c4ba58bb..b15b02f2 100644
--- a/extensions/libxt_limit.c
+++ b/extensions/libxt_limit.c
@@ -3,20 +3,21 @@
* Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
* Hervé Eychenne <rv@wallfire.org>
*/
-#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
-#include <stddef.h>
#include <linux/netfilter/x_tables.h>
-/* For 64bit kernel / 32bit userspace */
#include <linux/netfilter/xt_limit.h>
#define XT_LIMIT_AVG "3/hour"
#define XT_LIMIT_BURST 5
+enum {
+ O_LIMIT = 0,
+ O_BURST,
+};
+
static void limit_help(void)
{
printf(
@@ -28,10 +29,12 @@ static void limit_help(void)
XT_LIMIT_BURST);
}
-static const struct option limit_opts[] = {
- {.name = "limit", .has_arg = true, .val = '%'},
- {.name = "limit-burst", .has_arg = true, .val = '$'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry limit_opts[] = {
+ {.name = "limit", .id = O_LIMIT, .type = XTTYPE_STRING},
+ {.name = "limit-burst", .id = O_BURST, .type = XTTYPE_UINT32,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_rateinfo, burst),
+ .min = 0, .max = 10000},
+ XTOPT_TABLEEND,
};
static
@@ -85,35 +88,21 @@ static void limit_init(struct xt_entry_match *m)
"Sorry: burst too large for that avg rate.\n");
*/
-static int
-limit_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void limit_parse(struct xt_option_call *cb)
{
- struct xt_rateinfo *r = (struct xt_rateinfo *)(*match)->data;
- unsigned int num;
-
- switch(c) {
- case '%':
- if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
- if (!parse_rate(optarg, &r->avg))
- xtables_error(PARAMETER_PROBLEM,
- "bad rate `%s'", optarg);
- break;
+ struct xt_rateinfo *r = cb->data;
- case '$':
- if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
- if (!xtables_strtoui(optarg, NULL, &num, 0, 10000))
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_LIMIT:
+ if (!parse_rate(cb->arg, &r->avg))
xtables_error(PARAMETER_PROBLEM,
- "bad --limit-burst `%s'", optarg);
- r->burst = num;
+ "bad rate \"%s\"'", cb->arg);
break;
}
-
- if (invert)
+ if (cb->invert)
xtables_error(PARAMETER_PROBLEM,
"limit does not support invert");
-
- return 1;
}
static const struct rates
@@ -162,10 +151,10 @@ static struct xtables_match limit_match = {
.userspacesize = offsetof(struct xt_rateinfo, prev),
.help = limit_help,
.init = limit_init,
- .parse = limit_parse,
+ .x6_parse = limit_parse,
.print = limit_print,
.save = limit_save,
- .extra_opts = limit_opts,
+ .x6_options = limit_opts,
};
void _init(void)
diff --git a/extensions/libxt_multiport.c b/extensions/libxt_multiport.c
index 7fa537e0..03af5a96 100644
--- a/extensions/libxt_multiport.c
+++ b/extensions/libxt_multiport.c
@@ -1,19 +1,23 @@
-/* Shared library add-on to iptables to add multiple TCP port support. */
-#include <stdbool.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
-
#include <xtables.h>
-#include <libiptc/libiptc.h>
-#include <libiptc/libip6tc.h>
#include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter/xt_multiport.h>
+enum {
+ O_SOURCE_PORTS = 0,
+ O_DEST_PORTS,
+ O_SD_PORTS,
+ F_SOURCE_PORTS = 1 << O_SOURCE_PORTS,
+ F_DEST_PORTS = 1 << O_DEST_PORTS,
+ F_SD_PORTS = 1 << O_SD_PORTS,
+ F_ANY = F_SOURCE_PORTS | F_DEST_PORTS | F_SD_PORTS,
+};
+
/* Function which prints out usage message. */
static void multiport_help(void)
{
@@ -44,13 +48,18 @@ static void multiport_help_v1(void)
" match both source and destination port(s)\n");
}
-static const struct option multiport_opts[] = {
- {.name = "source-ports", .has_arg = true, .val = '1'},
- {.name = "sports", .has_arg = true, .val = '1'}, /* synonym */
- {.name = "destination-ports", .has_arg = true, .val = '2'},
- {.name = "dports", .has_arg = true, .val = '2'}, /* synonym */
- {.name = "ports", .has_arg = true, .val = '3'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry multiport_opts[] = {
+ {.name = "source-ports", .id = O_SOURCE_PORTS, .type = XTTYPE_STRING,
+ .excl = F_ANY, .flags = XTOPT_INVERT},
+ {.name = "sports", .id = O_SOURCE_PORTS, .type = XTTYPE_STRING,
+ .excl = F_ANY, .flags = XTOPT_INVERT},
+ {.name = "destination-ports", .id = O_DEST_PORTS,
+ .type = XTTYPE_STRING, .excl = F_ANY, .flags = XTOPT_INVERT},
+ {.name = "dports", .id = O_DEST_PORTS, .type = XTTYPE_STRING,
+ .excl = F_ANY, .flags = XTOPT_INVERT},
+ {.name = "ports", .id = O_SD_PORTS, .type = XTTYPE_STRING,
+ .excl = F_ANY, .flags = XTOPT_INVERT},
+ XTOPT_TABLEEND,
};
static const char *
@@ -152,136 +161,97 @@ check_proto(uint16_t pnum, uint8_t invflags)
"multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-__multiport_parse(int c, char **argv, int invert, unsigned int *flags,
- struct xt_entry_match **match, uint16_t pnum,
- uint8_t invflags)
+static void __multiport_parse(struct xt_option_call *cb, uint16_t pnum,
+ uint8_t invflags)
{
const char *proto;
- struct xt_multiport *multiinfo
- = (struct xt_multiport *)(*match)->data;
+ struct xt_multiport *multiinfo = cb->data;
- switch (c) {
- case '1':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SOURCE_PORTS:
proto = check_proto(pnum, invflags);
- multiinfo->count = parse_multi_ports(optarg,
+ multiinfo->count = parse_multi_ports(cb->arg,
multiinfo->ports, proto);
multiinfo->flags = XT_MULTIPORT_SOURCE;
break;
-
- case '2':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ case O_DEST_PORTS:
proto = check_proto(pnum, invflags);
- multiinfo->count = parse_multi_ports(optarg,
+ multiinfo->count = parse_multi_ports(cb->arg,
multiinfo->ports, proto);
multiinfo->flags = XT_MULTIPORT_DESTINATION;
break;
-
- case '3':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ case O_SD_PORTS:
proto = check_proto(pnum, invflags);
- multiinfo->count = parse_multi_ports(optarg,
+ multiinfo->count = parse_multi_ports(cb->arg,
multiinfo->ports, proto);
multiinfo->flags = XT_MULTIPORT_EITHER;
break;
}
-
- if (invert)
+ if (cb->invert)
xtables_error(PARAMETER_PROBLEM,
- "multiport does not support invert");
-
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "multiport can only have one option");
- *flags = 1;
- return 1;
+ "multiport.0 does not support invert");
}
-static int
-multiport_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *e, struct xt_entry_match **match)
+static void multiport_parse(struct xt_option_call *cb)
{
- const struct ipt_entry *entry = e;
- return __multiport_parse(c, argv, invert, flags, match,
+ const struct ipt_entry *entry = cb->xt_entry;
+ return __multiport_parse(cb,
entry->ip.proto, entry->ip.invflags);
}
-static int
-multiport_parse6(int c, char **argv, int invert, unsigned int *flags,
- const void *e, struct xt_entry_match **match)
+static void multiport_parse6(struct xt_option_call *cb)
{
- const struct ip6t_entry *entry = e;
- return __multiport_parse(c, argv, invert, flags, match,
+ const struct ip6t_entry *entry = cb->xt_entry;
+ return __multiport_parse(cb,
entry->ipv6.proto, entry->ipv6.invflags);
}
-static int
-__multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
- struct xt_entry_match **match, uint16_t pnum,
- uint8_t invflags)
+static void __multiport_parse_v1(struct xt_option_call *cb, uint16_t pnum,
+ uint8_t invflags)
{
const char *proto;
- struct xt_multiport_v1 *multiinfo
- = (struct xt_multiport_v1 *)(*match)->data;
+ struct xt_multiport_v1 *multiinfo = cb->data;
- switch (c) {
- case '1':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SOURCE_PORTS:
proto = check_proto(pnum, invflags);
- parse_multi_ports_v1(optarg, multiinfo, proto);
+ parse_multi_ports_v1(cb->arg, multiinfo, proto);
multiinfo->flags = XT_MULTIPORT_SOURCE;
break;
-
- case '2':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ case O_DEST_PORTS:
proto = check_proto(pnum, invflags);
- parse_multi_ports_v1(optarg, multiinfo, proto);
+ parse_multi_ports_v1(cb->arg, multiinfo, proto);
multiinfo->flags = XT_MULTIPORT_DESTINATION;
break;
-
- case '3':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ case O_SD_PORTS:
proto = check_proto(pnum, invflags);
- parse_multi_ports_v1(optarg, multiinfo, proto);
+ parse_multi_ports_v1(cb->arg, multiinfo, proto);
multiinfo->flags = XT_MULTIPORT_EITHER;
break;
}
-
- if (invert)
+ if (cb->invert)
multiinfo->invert = 1;
-
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "multiport can only have one option");
- *flags = 1;
- return 1;
}
-static int
-multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
- const void *e, struct xt_entry_match **match)
+static void multiport_parse_v1(struct xt_option_call *cb)
{
- const struct ipt_entry *entry = e;
- return __multiport_parse_v1(c, argv, invert, flags, match,
+ const struct ipt_entry *entry = cb->xt_entry;
+ return __multiport_parse_v1(cb,
entry->ip.proto, entry->ip.invflags);
}
-static int
-multiport_parse6_v1(int c, char **argv, int invert, unsigned int *flags,
- const void *e, struct xt_entry_match **match)
+static void multiport_parse6_v1(struct xt_option_call *cb)
{
- const struct ip6t_entry *entry = e;
- return __multiport_parse_v1(c, argv, invert, flags, match,
+ const struct ip6t_entry *entry = cb->xt_entry;
+ return __multiport_parse_v1(cb,
entry->ipv6.proto, entry->ipv6.invflags);
}
-/* Final check; must specify something. */
-static void multiport_check(unsigned int flags)
+static void multiport_check(struct xt_fcheck_call *cb)
{
- if (!flags)
+ if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM, "multiport expection an option");
}
@@ -307,7 +277,6 @@ print_port(uint16_t port, uint8_t protocol, int numeric)
printf("%s", service);
}
-/* Prints out the matchinfo. */
static void
__multiport_print(const struct xt_entry_match *match, int numeric,
uint16_t proto)
@@ -410,7 +379,6 @@ static void multiport_print6_v1(const void *ip_void,
__multiport_print_v1(match, numeric, ip->proto);
}
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
static void __multiport_save(const struct xt_entry_match *match,
uint16_t proto)
{
@@ -509,11 +477,11 @@ static struct xtables_match multiport_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_multiport)),
.userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
.help = multiport_help,
- .parse = multiport_parse,
- .final_check = multiport_check,
+ .x6_parse = multiport_parse,
+ .x6_fcheck = multiport_check,
.print = multiport_print,
.save = multiport_save,
- .extra_opts = multiport_opts,
+ .x6_options = multiport_opts,
},
{
.family = NFPROTO_IPV6,
@@ -523,11 +491,11 @@ static struct xtables_match multiport_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_multiport)),
.userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
.help = multiport_help,
- .parse = multiport_parse6,
- .final_check = multiport_check,
+ .x6_parse = multiport_parse6,
+ .x6_fcheck = multiport_check,
.print = multiport_print6,
.save = multiport_save6,
- .extra_opts = multiport_opts,
+ .x6_options = multiport_opts,
},
{
.family = NFPROTO_IPV4,
@@ -537,11 +505,11 @@ static struct xtables_match multiport_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_multiport_v1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)),
.help = multiport_help_v1,
- .parse = multiport_parse_v1,
- .final_check = multiport_check,
+ .x6_parse = multiport_parse_v1,
+ .x6_fcheck = multiport_check,
.print = multiport_print_v1,
.save = multiport_save_v1,
- .extra_opts = multiport_opts,
+ .x6_options = multiport_opts,
},
{
.family = NFPROTO_IPV6,
@@ -551,11 +519,11 @@ static struct xtables_match multiport_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_multiport_v1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)),
.help = multiport_help_v1,
- .parse = multiport_parse6_v1,
- .final_check = multiport_check,
+ .x6_parse = multiport_parse6_v1,
+ .x6_fcheck = multiport_check,
.print = multiport_print6_v1,
.save = multiport_save6_v1,
- .extra_opts = multiport_opts,
+ .x6_options = multiport_opts,
},
};
diff --git a/extensions/libxt_osf.c b/extensions/libxt_osf.c
index 20acfeab..88274a0e 100644
--- a/extensions/libxt_osf.c
+++ b/extensions/libxt_osf.c
@@ -20,23 +20,19 @@
/*
* xtables interface for OS fingerprint matching module.
*/
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-
-#include <linux/types.h>
-
#include <xtables.h>
-
#include <netinet/ip.h>
#include <netinet/tcp.h>
-
#include <linux/netfilter/xt_osf.h>
+enum {
+ O_GENRE = 0,
+ O_TTL,
+ O_LOGLEVEL,
+};
+
static void osf_help(void)
{
printf("OS fingerprint match options:\n"
@@ -52,71 +48,37 @@ static void osf_help(void)
);
}
-
-static const struct option osf_opts[] = {
- {.name = "genre", .has_arg = true, .val = '1'},
- {.name = "ttl", .has_arg = true, .val = '2'},
- {.name = "log", .has_arg = true, .val = '3'},
- XT_GETOPT_TABLEEND,
+#define s struct xt_osf_info
+static const struct xt_option_entry osf_opts[] = {
+ {.name = "genre", .id = O_GENRE, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND | XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(s, genre)},
+ {.name = "ttl", .id = O_TTL, .type = XTTYPE_UINT32,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, ttl), .min = 0, .max = 2},
+ {.name = "log", .id = O_LOGLEVEL, .type = XTTYPE_UINT32,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, loglevel), .min = 0, .max = 2},
+ XTOPT_TABLEEND,
};
+#undef s
-
-static void osf_parse_string(const char *s, struct xt_osf_info *info)
+static void osf_parse(struct xt_option_call *cb)
{
- if (strlen(s) < MAXGENRELEN)
- strcpy(info->genre, s);
- else
- xtables_error(PARAMETER_PROBLEM,
- "Genre string too long `%s' [%zd], max=%d",
- s, strlen(s), MAXGENRELEN);
-}
-
-static int osf_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry,
- struct xt_entry_match **match)
-{
- struct xt_osf_info *info = (struct xt_osf_info *)(*match)->data;
+ struct xt_osf_info *info = cb->data;
- switch(c) {
- case '1': /* --genre */
- if (*flags & XT_OSF_GENRE)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify multiple genre parameter");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- osf_parse_string(argv[optind-1], info);
- if (invert)
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_GENRE:
+ if (cb->invert)
info->flags |= XT_OSF_INVERT;
- info->len=strlen(info->genre);
- *flags |= XT_OSF_GENRE;
+ info->len = strlen(info->genre);
break;
- case '2': /* --ttl */
- if (*flags & XT_OSF_TTL)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify multiple ttl parameter");
- *flags |= XT_OSF_TTL;
+ case O_TTL:
info->flags |= XT_OSF_TTL;
- if (!xtables_strtoui(argv[optind-1], NULL, &info->ttl, 0, 2))
- xtables_error(PARAMETER_PROBLEM, "TTL parameter is too big");
break;
- case '3': /* --log */
- if (*flags & XT_OSF_LOG)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify multiple log parameter");
- *flags |= XT_OSF_LOG;
- if (!xtables_strtoui(argv[optind-1], NULL, &info->loglevel, 0, 2))
- xtables_error(PARAMETER_PROBLEM, "Log level parameter is too big");
+ case O_LOGLEVEL:
info->flags |= XT_OSF_LOG;
break;
}
-
- return 1;
-}
-
-static void osf_final_check(unsigned int flags)
-{
- if (!(flags & XT_OSF_GENRE))
- xtables_error(PARAMETER_PROBLEM,
- "OS fingerprint match: You must specify `--genre'");
}
static void osf_print(const void *ip, const struct xt_entry_match *match, int numeric)
@@ -139,12 +101,11 @@ static struct xtables_match osf_match = {
.size = XT_ALIGN(sizeof(struct xt_osf_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_osf_info)),
.help = osf_help,
- .parse = osf_parse,
+ .x6_parse = osf_parse,
.print = osf_print,
- .final_check = osf_final_check,
.save = osf_save,
- .extra_opts = osf_opts,
- .family = NFPROTO_IPV4
+ .x6_options = osf_opts,
+ .family = NFPROTO_IPV4,
};
void _init(void)
diff --git a/extensions/libxt_owner.c b/extensions/libxt_owner.c
index f930cf45..b60f9071 100644
--- a/extensions/libxt_owner.c
+++ b/extensions/libxt_owner.c
@@ -4,16 +4,11 @@
* Copyright © CC Computer Consultants GmbH, 2007 - 2008
* Jan Engelhardt <jengelh@computergmbh.de>
*/
-#include <getopt.h>
#include <grp.h>
-#include <netdb.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <limits.h>
-
#include <xtables.h>
#include <linux/netfilter/xt_owner.h>
@@ -55,12 +50,12 @@ struct ip6t_owner_info {
*/
enum {
- FLAG_UID_OWNER = 1 << 0,
- FLAG_GID_OWNER = 1 << 1,
- FLAG_SOCKET_EXISTS = 1 << 2,
- FLAG_PID_OWNER = 1 << 3,
- FLAG_SID_OWNER = 1 << 4,
- FLAG_COMM = 1 << 5,
+ O_USER = 0,
+ O_GROUP,
+ O_SOCK_EXISTS,
+ O_PROCESS,
+ O_SESSION,
+ O_COMM,
};
static void owner_mt_help_v0(void)
@@ -95,170 +90,134 @@ static void owner_mt_help(void)
"[!] --socket-exists Match if socket exists\n");
}
-static const struct option owner_mt_opts_v0[] = {
- {.name = "uid-owner", .has_arg = true, .val = 'u'},
- {.name = "gid-owner", .has_arg = true, .val = 'g'},
- {.name = "pid-owner", .has_arg = true, .val = 'p'},
- {.name = "sid-owner", .has_arg = true, .val = 's'},
- {.name = "cmd-owner", .has_arg = true, .val = 'c'},
- XT_GETOPT_TABLEEND,
+#define s struct ipt_owner_info
+static const struct xt_option_entry owner_mt_opts_v0[] = {
+ {.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "pid-owner", .id = O_PROCESS, .type = XTTYPE_UINT32,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, pid),
+ .max = INT_MAX},
+ {.name = "sid-owner", .id = O_SESSION, .type = XTTYPE_UINT32,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, sid),
+ .max = INT_MAX},
+ {.name = "cmd-owner", .id = O_COMM, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, comm)},
+ XTOPT_TABLEEND,
};
-
-static const struct option owner_mt6_opts_v0[] = {
- {.name = "uid-owner", .has_arg = true, .val = 'u'},
- {.name = "gid-owner", .has_arg = true, .val = 'g'},
- {.name = "pid-owner", .has_arg = true, .val = 'p'},
- {.name = "sid-owner", .has_arg = true, .val = 's'},
- XT_GETOPT_TABLEEND,
+#undef s
+
+#define s struct ip6t_owner_info
+static const struct xt_option_entry owner_mt6_opts_v0[] = {
+ {.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "pid-owner", .id = O_PROCESS, .type = XTTYPE_UINT32,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, pid),
+ .max = INT_MAX},
+ {.name = "sid-owner", .id = O_SESSION, .type = XTTYPE_UINT32,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, sid),
+ .max = INT_MAX},
+ XTOPT_TABLEEND,
};
+#undef s
-static const struct option owner_mt_opts[] = {
- {.name = "uid-owner", .has_arg = true, .val = 'u'},
- {.name = "gid-owner", .has_arg = true, .val = 'g'},
- {.name = "socket-exists", .has_arg = false, .val = 'k'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry owner_mt_opts[] = {
+ {.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING},
+ {.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING},
+ {.name = "socket-exists", .id = O_SOCK_EXISTS, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
-static int
-owner_mt_parse_v0(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void owner_mt_parse_v0(struct xt_option_call *cb)
{
- struct ipt_owner_info *info = (void *)(*match)->data;
+ struct ipt_owner_info *info = cb->data;
struct passwd *pwd;
struct group *grp;
unsigned int id;
- switch (c) {
- case 'u':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner", *flags & FLAG_UID_OWNER);
- if ((pwd = getpwnam(optarg)) != NULL)
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_USER:
+ if ((pwd = getpwnam(cb->arg)) != NULL)
id = pwd->pw_uid;
- else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
- xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", optarg);
- if (invert)
+ else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", cb->arg);
+ if (cb->invert)
info->invert |= IPT_OWNER_UID;
info->match |= IPT_OWNER_UID;
info->uid = id;
- *flags |= FLAG_UID_OWNER;
- return true;
-
- case 'g':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner", *flags & FLAG_GID_OWNER);
- if ((grp = getgrnam(optarg)) != NULL)
+ break;
+ case O_GROUP:
+ if ((grp = getgrnam(cb->arg)) != NULL)
id = grp->gr_gid;
- else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
- xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", optarg);
- if (invert)
+ else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", cb->arg);
+ if (cb->invert)
info->invert |= IPT_OWNER_GID;
info->match |= IPT_OWNER_GID;
info->gid = id;
- *flags |= FLAG_GID_OWNER;
- return true;
-
- case 'p':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--pid-owner", *flags & FLAG_PID_OWNER);
- if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
- xtables_param_act(XTF_BAD_VALUE, "owner", "--pid-owner", optarg);
- if (invert)
+ break;
+ case O_PROCESS:
+ if (cb->invert)
info->invert |= IPT_OWNER_PID;
info->match |= IPT_OWNER_PID;
- info->pid = id;
- *flags |= FLAG_PID_OWNER;
- return true;
-
- case 's':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--sid-owner", *flags & FLAG_SID_OWNER);
- if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
- xtables_param_act(XTF_BAD_VALUE, "owner", "--sid-value", optarg);
- if (invert)
+ break;
+ case O_SESSION:
+ if (cb->invert)
info->invert |= IPT_OWNER_SID;
info->match |= IPT_OWNER_SID;
- info->sid = id;
- *flags |= FLAG_SID_OWNER;
- return true;
-
- case 'c':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--cmd-owner", *flags & FLAG_COMM);
- if (strlen(optarg) > sizeof(info->comm))
- xtables_error(PARAMETER_PROBLEM, "owner match: command "
- "\"%s\" too long, max. %zu characters",
- optarg, sizeof(info->comm));
-
- info->comm[sizeof(info->comm)-1] = '\0';
- strncpy(info->comm, optarg, sizeof(info->comm));
-
- if (invert)
+ break;
+ case O_COMM:
+ if (cb->invert)
info->invert |= IPT_OWNER_COMM;
info->match |= IPT_OWNER_COMM;
- *flags |= FLAG_COMM;
- return true;
+ break;
}
- return false;
}
-static int
-owner_mt6_parse_v0(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void owner_mt6_parse_v0(struct xt_option_call *cb)
{
- struct ip6t_owner_info *info = (void *)(*match)->data;
+ struct ip6t_owner_info *info = cb->data;
struct passwd *pwd;
struct group *grp;
unsigned int id;
- switch (c) {
- case 'u':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner",
- *flags & FLAG_UID_OWNER);
- if ((pwd = getpwnam(optarg)) != NULL)
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_USER:
+ if ((pwd = getpwnam(cb->arg)) != NULL)
id = pwd->pw_uid;
- else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
- xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", optarg);
- if (invert)
+ else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", cb->arg);
+ if (cb->invert)
info->invert |= IP6T_OWNER_UID;
info->match |= IP6T_OWNER_UID;
info->uid = id;
- *flags |= FLAG_UID_OWNER;
- return true;
-
- case 'g':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner",
- *flags & FLAG_GID_OWNER);
- if ((grp = getgrnam(optarg)) != NULL)
+ break;
+ case O_GROUP:
+ if ((grp = getgrnam(cb->arg)) != NULL)
id = grp->gr_gid;
- else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
- xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", optarg);
- if (invert)
+ else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", cb->arg);
+ if (cb->invert)
info->invert |= IP6T_OWNER_GID;
info->match |= IP6T_OWNER_GID;
info->gid = id;
- *flags |= FLAG_GID_OWNER;
- return true;
-
- case 'p':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--pid-owner",
- *flags & FLAG_PID_OWNER);
- if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
- xtables_param_act(XTF_BAD_VALUE, "owner", "--pid-owner", optarg);
- if (invert)
+ break;
+ case O_PROCESS:
+ if (cb->invert)
info->invert |= IP6T_OWNER_PID;
info->match |= IP6T_OWNER_PID;
- info->pid = id;
- *flags |= FLAG_PID_OWNER;
- return true;
-
- case 's':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--sid-owner",
- *flags & FLAG_SID_OWNER);
- if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
- xtables_param_act(XTF_BAD_VALUE, "owner", "--sid-owner", optarg);
- if (invert)
+ break;
+ case O_SESSION:
+ if (cb->invert)
info->invert |= IP6T_OWNER_SID;
info->match |= IP6T_OWNER_SID;
- info->sid = id;
- *flags |= FLAG_SID_OWNER;
- return true;
+ break;
}
- return false;
}
static void owner_parse_range(const char *s, unsigned int *from,
@@ -277,61 +236,48 @@ static void owner_parse_range(const char *s, unsigned int *from,
xtables_param_act(XTF_BAD_VALUE, "owner", opt, s);
}
-static int owner_mt_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void owner_mt_parse(struct xt_option_call *cb)
{
- struct xt_owner_match_info *info = (void *)(*match)->data;
+ struct xt_owner_match_info *info = cb->data;
struct passwd *pwd;
struct group *grp;
unsigned int from, to;
- switch (c) {
- case 'u':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner",
- *flags & FLAG_UID_OWNER);
- if ((pwd = getpwnam(optarg)) != NULL)
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_USER:
+ if ((pwd = getpwnam(cb->arg)) != NULL)
from = to = pwd->pw_uid;
else
- owner_parse_range(optarg, &from, &to, "--uid-owner");
- if (invert)
+ owner_parse_range(cb->arg, &from, &to, "--uid-owner");
+ if (cb->invert)
info->invert |= XT_OWNER_UID;
info->match |= XT_OWNER_UID;
info->uid_min = from;
info->uid_max = to;
- *flags |= FLAG_UID_OWNER;
- return true;
-
- case 'g':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner",
- *flags & FLAG_GID_OWNER);
- if ((grp = getgrnam(optarg)) != NULL)
+ break;
+ case O_GROUP:
+ if ((grp = getgrnam(cb->arg)) != NULL)
from = to = grp->gr_gid;
else
- owner_parse_range(optarg, &from, &to, "--gid-owner");
- if (invert)
+ owner_parse_range(cb->arg, &from, &to, "--gid-owner");
+ if (cb->invert)
info->invert |= XT_OWNER_GID;
info->match |= XT_OWNER_GID;
info->gid_min = from;
info->gid_max = to;
- *flags |= FLAG_GID_OWNER;
- return true;
-
- case 'k':
- xtables_param_act(XTF_ONLY_ONCE, "owner", "--socket-exists",
- *flags & FLAG_SOCKET_EXISTS);
- if (invert)
+ break;
+ case O_SOCK_EXISTS:
+ if (cb->invert)
info->invert |= XT_OWNER_SOCKET;
info->match |= XT_OWNER_SOCKET;
- *flags |= FLAG_SOCKET_EXISTS;
- return true;
-
+ break;
}
- return false;
}
-static void owner_mt_check(unsigned int flags)
+static void owner_mt_check(struct xt_fcheck_call *cb)
{
- if (flags == 0)
+ if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM, "owner: At least one of "
"--uid-owner, --gid-owner or --socket-exists "
"is required");
@@ -552,11 +498,11 @@ static struct xtables_match owner_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct ipt_owner_info)),
.userspacesize = XT_ALIGN(sizeof(struct ipt_owner_info)),
.help = owner_mt_help_v0,
- .parse = owner_mt_parse_v0,
- .final_check = owner_mt_check,
+ .x6_parse = owner_mt_parse_v0,
+ .x6_fcheck = owner_mt_check,
.print = owner_mt_print_v0,
.save = owner_mt_save_v0,
- .extra_opts = owner_mt_opts_v0,
+ .x6_options = owner_mt_opts_v0,
},
{
.version = XTABLES_VERSION,
@@ -566,11 +512,11 @@ static struct xtables_match owner_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct ip6t_owner_info)),
.userspacesize = XT_ALIGN(sizeof(struct ip6t_owner_info)),
.help = owner_mt6_help_v0,
- .parse = owner_mt6_parse_v0,
- .final_check = owner_mt_check,
+ .x6_parse = owner_mt6_parse_v0,
+ .x6_fcheck = owner_mt_check,
.print = owner_mt6_print_v0,
.save = owner_mt6_save_v0,
- .extra_opts = owner_mt6_opts_v0,
+ .x6_options = owner_mt6_opts_v0,
},
{
.version = XTABLES_VERSION,
@@ -580,11 +526,11 @@ static struct xtables_match owner_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_owner_match_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_owner_match_info)),
.help = owner_mt_help,
- .parse = owner_mt_parse,
- .final_check = owner_mt_check,
+ .x6_parse = owner_mt_parse,
+ .x6_fcheck = owner_mt_check,
.print = owner_mt_print,
.save = owner_mt_save,
- .extra_opts = owner_mt_opts,
+ .x6_options = owner_mt_opts,
},
};
diff --git a/extensions/libxt_policy.c b/extensions/libxt_policy.c
index 16e8c535..a514246c 100644
--- a/extensions/libxt_policy.c
+++ b/extensions/libxt_policy.c
@@ -1,25 +1,23 @@
-/* Shared library add-on to iptables to add policy support. */
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
#include <netdb.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
#include <xtables.h>
-
#include <linux/netfilter/xt_policy.h>
-/*
- * HACK: global pointer to current matchinfo for making
- * final checks and adjustments in final_check.
- */
-static struct xt_policy_info *policy_info;
+enum {
+ O_DIRECTION = 0,
+ O_POLICY,
+ O_STRICT,
+ O_REQID,
+ O_SPI,
+ O_PROTO,
+ O_MODE,
+ O_TUNNELSRC,
+ O_TUNNELDST,
+ O_NEXT
+};
static void policy_help(void)
{
@@ -39,62 +37,22 @@ static void policy_help(void)
" --next begin next element in policy\n");
}
-static const struct option policy_opts[] =
-{
- {
- .name = "dir",
- .has_arg = true,
- .val = '1',
- },
- {
- .name = "pol",
- .has_arg = true,
- .val = '2',
- },
- {
- .name = "strict",
- .has_arg = false,
- .val = '3'
- },
- {
- .name = "reqid",
- .has_arg = true,
- .val = '4',
- },
- {
- .name = "spi",
- .has_arg = true,
- .val = '5'
- },
- {
- .name = "tunnel-src",
- .has_arg = true,
- .val = '6'
- },
- {
- .name = "tunnel-dst",
- .has_arg = true,
- .val = '7'
- },
- {
- .name = "proto",
- .has_arg = true,
- .val = '8'
- },
- {
- .name = "mode",
- .has_arg = true,
- .val = '9'
- },
- {
- .name = "next",
- .has_arg = false,
- .val = 'a'
- },
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry policy_opts[] = {
+ {.name = "dir", .id = O_DIRECTION, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "pol", .id = O_POLICY, .type = XTTYPE_STRING},
+ {.name = "strict", .id = O_STRICT, .type = XTTYPE_NONE},
+ {.name = "reqid", .id = O_REQID, .type = XTTYPE_UINT32},
+ {.name = "spi", .id = O_SPI, .type = XTTYPE_UINT32},
+ {.name = "tunnel-src", .id = O_TUNNELSRC, .type = XTTYPE_HOSTMASK},
+ {.name = "tunnel-dst", .id = O_TUNNELDST, .type = XTTYPE_HOSTMASK},
+ {.name = "proto", .id = O_PROTO, .type = XTTYPE_STRING},
+ {.name = "mode", .id = O_MODE, .type = XTTYPE_STRING},
+ {.name = "next", .id = O_NEXT, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
-static int parse_direction(char *s)
+static int parse_direction(const char *s)
{
if (strcmp(s, "in") == 0)
return XT_POLICY_MATCH_IN;
@@ -103,7 +61,7 @@ static int parse_direction(char *s)
xtables_error(PARAMETER_PROBLEM, "policy_match: invalid dir \"%s\"", s);
}
-static int parse_policy(char *s)
+static int parse_policy(const char *s)
{
if (strcmp(s, "none") == 0)
return XT_POLICY_MATCH_NONE;
@@ -112,7 +70,7 @@ static int parse_policy(char *s)
xtables_error(PARAMETER_PROBLEM, "policy match: invalid policy \"%s\"", s);
}
-static int parse_mode(char *s)
+static int parse_mode(const char *s)
{
if (strcmp(s, "transport") == 0)
return XT_POLICY_MODE_TRANSPORT;
@@ -121,176 +79,95 @@ static int parse_mode(char *s)
xtables_error(PARAMETER_PROBLEM, "policy match: invalid mode \"%s\"", s);
}
-static int policy_parse(int c, char **argv, int invert, unsigned int *flags,
- struct xt_policy_info *info, uint8_t family)
+static void policy_parse(struct xt_option_call *cb)
{
+ struct xt_policy_info *info = cb->data;
struct xt_policy_elem *e = &info->pol[info->len];
- struct in_addr *addr = NULL, mask;
- struct in6_addr *addr6 = NULL, mask6;
- unsigned int naddr = 0, num;
- int mode;
-
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- switch (c) {
- case '1':
- if (info->flags & (XT_POLICY_MATCH_IN | XT_POLICY_MATCH_OUT))
- xtables_error(PARAMETER_PROBLEM,
- "policy match: double --dir option");
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "policy match: can't invert --dir option");
-
- info->flags |= parse_direction(optarg);
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_DIRECTION:
+ info->flags |= parse_direction(cb->arg);
break;
- case '2':
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "policy match: can't invert --policy option");
-
- info->flags |= parse_policy(optarg);
+ case O_POLICY:
+ info->flags |= parse_policy(cb->arg);
break;
- case '3':
- if (info->flags & XT_POLICY_MATCH_STRICT)
- xtables_error(PARAMETER_PROBLEM,
- "policy match: double --strict option");
-
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "policy match: can't invert --strict option");
-
+ case O_STRICT:
info->flags |= XT_POLICY_MATCH_STRICT;
break;
- case '4':
+ case O_REQID:
if (e->match.reqid)
xtables_error(PARAMETER_PROBLEM,
"policy match: double --reqid option");
-
e->match.reqid = 1;
- e->invert.reqid = invert;
- if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "policy", "--spi", optarg);
- e->reqid = num;
+ e->invert.reqid = cb->invert;
+ e->reqid = cb->val.u32;
break;
- case '5':
+ case O_SPI:
if (e->match.spi)
xtables_error(PARAMETER_PROBLEM,
"policy match: double --spi option");
-
e->match.spi = 1;
- e->invert.spi = invert;
- if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "policy", "--spi", optarg);
- e->spi = num;
+ e->invert.spi = cb->invert;
+ e->spi = cb->val.u32;
break;
- case '6':
+ case O_TUNNELSRC:
if (e->match.saddr)
xtables_error(PARAMETER_PROBLEM,
"policy match: double --tunnel-src option");
- if (family == NFPROTO_IPV6)
- xtables_ip6parse_any(optarg, &addr6, &mask6, &naddr);
- else
- xtables_ipparse_any(optarg, &addr, &mask, &naddr);
- if (naddr > 1)
- xtables_error(PARAMETER_PROBLEM,
- "policy match: name resolves to multiple IPs");
-
e->match.saddr = 1;
- e->invert.saddr = invert;
- if (family == NFPROTO_IPV6) {
- memcpy(&e->saddr.a6, addr6, sizeof(*addr6));
- memcpy(&e->smask.a6, &mask6, sizeof(mask6));
- } else {
- e->saddr.a4 = addr[0];
- e->smask.a4 = mask;
- }
+ e->invert.saddr = cb->invert;
+ memcpy(&e->saddr, &cb->val.haddr, sizeof(cb->val.haddr));
+ memcpy(&e->smask, &cb->val.hmask, sizeof(cb->val.hmask));
break;
- case '7':
+ case O_TUNNELDST:
if (e->match.daddr)
xtables_error(PARAMETER_PROBLEM,
"policy match: double --tunnel-dst option");
-
- if (family == NFPROTO_IPV6)
- xtables_ip6parse_any(optarg, &addr6, &mask6, &naddr);
- else
- xtables_ipparse_any(optarg, &addr, &mask, &naddr);
- if (naddr > 1)
- xtables_error(PARAMETER_PROBLEM,
- "policy match: name resolves to multiple IPs");
-
e->match.daddr = 1;
- e->invert.daddr = invert;
- if (family == NFPROTO_IPV6) {
- memcpy(&e->daddr.a6, addr6, sizeof(*addr6));
- memcpy(&e->dmask.a6, &mask6, sizeof(mask6));
- } else {
- e->daddr.a4 = addr[0];
- e->dmask.a4 = mask;
- }
+ e->invert.daddr = cb->invert;
+ memcpy(&e->daddr, &cb->val.haddr, sizeof(cb->val.haddr));
+ memcpy(&e->dmask, &cb->val.hmask, sizeof(cb->val.hmask));
break;
- case '8':
+ case O_PROTO:
if (e->match.proto)
xtables_error(PARAMETER_PROBLEM,
"policy match: double --proto option");
-
- e->proto = xtables_parse_protocol(optarg);
+ e->proto = xtables_parse_protocol(cb->arg);
if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
e->proto != IPPROTO_COMP)
xtables_error(PARAMETER_PROBLEM,
- "policy match: protocol must ah/esp/ipcomp");
+ "policy match: protocol must be ah/esp/ipcomp");
e->match.proto = 1;
- e->invert.proto = invert;
+ e->invert.proto = cb->invert;
break;
- case '9':
+ case O_MODE:
if (e->match.mode)
xtables_error(PARAMETER_PROBLEM,
"policy match: double --mode option");
-
- mode = parse_mode(optarg);
e->match.mode = 1;
- e->invert.mode = invert;
- e->mode = mode;
+ e->invert.mode = cb->invert;
+ e->mode = parse_mode(cb->arg);
break;
- case 'a':
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "policy match: can't invert --next option");
-
+ case O_NEXT:
if (++info->len == XT_POLICY_MAX_ELEM)
xtables_error(PARAMETER_PROBLEM,
"policy match: maximum policy depth reached");
break;
}
-
- policy_info = info;
- return 1;
-}
-
-static int policy4_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- return policy_parse(c, argv, invert, flags, (void *)(*match)->data,
- NFPROTO_IPV4);
}
-static int policy6_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void policy_check(struct xt_fcheck_call *cb)
{
- return policy_parse(c, argv, invert, flags, (void *)(*match)->data,
- NFPROTO_IPV6);
-}
-
-static void policy_check(unsigned int flags)
-{
- struct xt_policy_info *info = policy_info;
- struct xt_policy_elem *e;
+ struct xt_policy_info *info = cb->data;
+ const struct xt_policy_elem *e;
int i;
- if (info == NULL)
- xtables_error(PARAMETER_PROBLEM,
- "policy match: no parameters given");
-
+ /*
+ * The old "no parameters given" check is carried out
+ * by testing for --dir.
+ */
if (!(info->flags & (XT_POLICY_MATCH_IN | XT_POLICY_MATCH_OUT)))
xtables_error(PARAMETER_PROBLEM,
"policy match: neither --dir in nor --dir out specified");
@@ -487,11 +364,11 @@ static struct xtables_match policy_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_policy_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_policy_info)),
.help = policy_help,
- .parse = policy4_parse,
- .final_check = policy_check,
+ .x6_parse = policy_parse,
+ .x6_fcheck = policy_check,
.print = policy4_print,
.save = policy4_save,
- .extra_opts = policy_opts,
+ .x6_options = policy_opts,
},
{
.name = "policy",
@@ -500,11 +377,11 @@ static struct xtables_match policy_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_policy_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_policy_info)),
.help = policy_help,
- .parse = policy6_parse,
- .final_check = policy_check,
+ .x6_parse = policy_parse,
+ .x6_fcheck = policy_check,
.print = policy6_print,
.save = policy6_save,
- .extra_opts = policy_opts,
+ .x6_options = policy_opts,
},
};
diff --git a/extensions/libxt_recent.c b/extensions/libxt_recent.c
index f8a5a18d..1e1a111f 100644
--- a/extensions/libxt_recent.c
+++ b/extensions/libxt_recent.c
@@ -1,27 +1,50 @@
-/* Shared library add-on to iptables to add recent 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_recent.h>
-static const struct option recent_opts[] = {
- {.name = "set", .has_arg = false, .val = 201},
- {.name = "rcheck", .has_arg = false, .val = 202},
- {.name = "update", .has_arg = false, .val = 203},
- {.name = "seconds", .has_arg = true, .val = 204},
- {.name = "hitcount", .has_arg = true, .val = 205},
- {.name = "remove", .has_arg = false, .val = 206},
- {.name = "rttl", .has_arg = false, .val = 207},
- {.name = "name", .has_arg = true, .val = 208},
- {.name = "rsource", .has_arg = false, .val = 209},
- {.name = "rdest", .has_arg = false, .val = 210},
- XT_GETOPT_TABLEEND,
+enum {
+ O_SET = 0,
+ O_RCHECK,
+ O_UPDATE,
+ O_REMOVE,
+ O_SECONDS,
+ O_HITCOUNT,
+ O_RTTL,
+ O_NAME,
+ O_RSOURCE,
+ O_RDEST,
+ F_SET = 1 << O_SET,
+ F_RCHECK = 1 << O_RCHECK,
+ F_UPDATE = 1 << O_UPDATE,
+ F_REMOVE = 1 << O_REMOVE,
+ F_ANY_OP = F_SET | F_RCHECK | F_UPDATE | F_REMOVE,
+};
+
+#define s struct xt_recent_mtinfo
+static const struct xt_option_entry recent_opts[] = {
+ {.name = "set", .id = O_SET, .type = XTTYPE_NONE,
+ .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+ {.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE,
+ .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+ {.name = "update", .id = O_UPDATE, .type = XTTYPE_NONE,
+ .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+ {.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE,
+ .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+ {.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds)},
+ {.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)},
+ {.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE,
+ .excl = F_SET | F_REMOVE},
+ {.name = "name", .id = O_NAME, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, name)},
+ {.name = "rsource", .id = O_RSOURCE, .type = XTTYPE_NONE},
+ {.name = "rdest", .id = O_RDEST, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
+#undef s
static void recent_help(void)
{
@@ -59,101 +82,50 @@ static void recent_init(struct xt_entry_match *match)
info->side = XT_RECENT_SOURCE;
}
-#define RECENT_CMDS \
- (XT_RECENT_SET | XT_RECENT_CHECK | \
- XT_RECENT_UPDATE | XT_RECENT_REMOVE)
-
-static int recent_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void recent_parse(struct xt_option_call *cb)
{
- struct xt_recent_mtinfo *info = (void *)(*match)->data;
-
- switch (c) {
- case 201:
- if (*flags & RECENT_CMDS)
- xtables_error(PARAMETER_PROBLEM,
- "recent: only one of `--set', `--rcheck' "
- "`--update' or `--remove' may be set");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- info->check_set |= XT_RECENT_SET;
- if (invert) info->invert = 1;
- *flags |= XT_RECENT_SET;
- break;
-
- case 202:
- if (*flags & RECENT_CMDS)
- xtables_error(PARAMETER_PROBLEM,
- "recent: only one of `--set', `--rcheck' "
- "`--update' or `--remove' may be set");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- info->check_set |= XT_RECENT_CHECK;
- if(invert) info->invert = 1;
- *flags |= XT_RECENT_CHECK;
- break;
-
- case 203:
- if (*flags & RECENT_CMDS)
- xtables_error(PARAMETER_PROBLEM,
- "recent: only one of `--set', `--rcheck' "
- "`--update' or `--remove' may be set");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- info->check_set |= XT_RECENT_UPDATE;
- if (invert) info->invert = 1;
- *flags |= XT_RECENT_UPDATE;
- break;
-
- case 204:
- info->seconds = atoi(optarg);
- break;
-
- case 205:
- info->hit_count = atoi(optarg);
- break;
-
- case 206:
- if (*flags & RECENT_CMDS)
- xtables_error(PARAMETER_PROBLEM,
- "recent: only one of `--set', `--rcheck' "
- "`--update' or `--remove' may be set");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- info->check_set |= XT_RECENT_REMOVE;
- if (invert) info->invert = 1;
- *flags |= XT_RECENT_REMOVE;
- break;
-
- case 207:
- info->check_set |= XT_RECENT_TTL;
- *flags |= XT_RECENT_TTL;
- break;
-
- case 208:
- strncpy(info->name,optarg, XT_RECENT_NAME_LEN);
- info->name[XT_RECENT_NAME_LEN-1] = '\0';
- break;
-
- case 209:
- info->side = XT_RECENT_SOURCE;
- break;
-
- case 210:
- info->side = XT_RECENT_DEST;
- break;
+ struct xt_recent_mtinfo *info = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SET:
+ info->check_set |= XT_RECENT_SET;
+ if (cb->invert)
+ info->invert = true;
+ break;
+ case O_RCHECK:
+ info->check_set |= XT_RECENT_CHECK;
+ if (cb->invert)
+ info->invert = true;
+ break;
+ case O_UPDATE:
+ info->check_set |= XT_RECENT_UPDATE;
+ if (cb->invert)
+ info->invert = true;
+ break;
+ case O_REMOVE:
+ info->check_set |= XT_RECENT_REMOVE;
+ if (cb->invert)
+ info->invert = true;
+ break;
+ case O_RTTL:
+ info->check_set |= XT_RECENT_TTL;
+ break;
+ case O_RSOURCE:
+ info->side = XT_RECENT_SOURCE;
+ break;
+ case O_RDEST:
+ info->side = XT_RECENT_DEST;
+ break;
}
-
- return 1;
}
-static void recent_check(unsigned int flags)
+static void recent_check(struct xt_fcheck_call *cb)
{
- if (!(flags & RECENT_CMDS))
+ if (!(cb->xflags & F_ANY_OP))
xtables_error(PARAMETER_PROBLEM,
"recent: you must specify one of `--set', `--rcheck' "
"`--update' or `--remove'");
- if ((flags & XT_RECENT_TTL) &&
- (flags & (XT_RECENT_SET | XT_RECENT_REMOVE)))
- xtables_error(PARAMETER_PROBLEM,
- "recent: --rttl may only be used with --rcheck or "
- "--update");
}
static void recent_print(const void *ip, const struct xt_entry_match *match,
@@ -218,11 +190,11 @@ static struct xtables_match recent_mt_reg = {
.userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
.help = recent_help,
.init = recent_init,
- .parse = recent_parse,
- .final_check = recent_check,
+ .x6_parse = recent_parse,
+ .x6_fcheck = recent_check,
.print = recent_print,
.save = recent_save,
- .extra_opts = recent_opts,
+ .x6_options = recent_opts,
};
void _init(void)
diff --git a/include/xtables.h.in b/include/xtables.h.in
index eb088b6b..00be61cf 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -46,6 +46,12 @@ struct in_addr;
#define XTOPT_TABLEEND {.name = NULL}
/**
+ * Select the format the input has to conform to, as well as the target type
+ * (area pointed to with XTOPT_POINTER). Note that the storing is not always
+ * uniform. @cb->val will be populated with as much as there is space, i.e.
+ * exactly 2 items for ranges, but the target area can receive more values
+ * (e.g. in case of ranges), or less values (e.g. %XTTYPE_HOSTMASK).
+ *
* %XTTYPE_NONE: option takes no argument
* %XTTYPE_UINT*: standard integer
* %XTTYPE_UINT*RC: colon-separated range of standard integers
@@ -54,11 +60,16 @@ struct in_addr;
* %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_HOST: one host or address (ptr: union nf_inet_addr)
+ * %XTTYPE_HOSTMASK: one host or address, with an optional prefix length
+ * (ptr: union nf_inet_addr; only host portion is stored)
+ * %XTTYPE_PROTOCOL: protocol number/name from /etc/protocols (ptr: uint8_t)
* %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
+ * %XTTYPE_PLEN: prefix length
+ * %XTTYPE_PLENMASK: prefix length (ptr: union nf_inet_addr)
*/
enum xt_option_type {
XTTYPE_NONE,
@@ -75,11 +86,15 @@ enum xt_option_type {
XTTYPE_TOSMASK,
XTTYPE_MARKMASK32,
XTTYPE_SYSLOGLEVEL,
- XTTYPE_ONEHOST,
+ XTTYPE_HOST,
+ XTTYPE_HOSTMASK,
+ XTTYPE_PROTOCOL,
XTTYPE_PORT,
XTTYPE_PORT_NE,
XTTYPE_PORTRC,
XTTYPE_PORTRC_NE,
+ XTTYPE_PLEN,
+ XTTYPE_PLENMASK,
};
/**
@@ -134,12 +149,15 @@ struct xt_option_call {
bool invert;
uint8_t nvals;
union {
- uint8_t u8, u8_range[2], syslog_level;
+ uint8_t u8, u8_range[2], syslog_level, protocol;
uint16_t u16, u16_range[2], port, port_range[2];
uint32_t u32, u32_range[2];
uint64_t u64, u64_range[2];
double dbl;
- union nf_inet_addr inetaddr;
+ struct {
+ union nf_inet_addr haddr, hmask;
+ uint8_t hlen;
+ };
struct {
uint8_t tos_value, tos_mask;
};
@@ -147,10 +165,12 @@ struct xt_option_call {
uint32_t mark, mask;
};
} val;
+ /* Wished for a world where the ones below were gone: */
union {
struct xt_entry_match **match;
struct xt_entry_target **target;
};
+ void *xt_entry;
};
/**
diff --git a/xtoptions.c b/xtoptions.c
index 86498a97..70370edb 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -419,9 +419,11 @@ static socklen_t xtables_sa_hostlen(unsigned int afproto)
}
/**
- * Accepts: a hostname (DNS), or a single inetaddr.
+ * Accepts: a hostname (DNS), or a single inetaddr - without any mask. The
+ * result is stored in @cb->val.haddr. Additionally, @cb->val.hmask and
+ * @cb->val.hlen are set for completeness to the appropriate values.
*/
-static void xtopt_parse_onehost(struct xt_option_call *cb)
+static void xtopt_parse_host(struct xt_option_call *cb)
{
struct addrinfo hints = {.ai_family = afinfo->family};
unsigned int adcount = 0;
@@ -433,16 +435,19 @@ static void xtopt_parse_onehost(struct xt_option_call *cb)
xt_params->exit_err(PARAMETER_PROBLEM,
"getaddrinfo: %s\n", gai_strerror(ret));
+ memset(&cb->val.hmask, 0xFF, sizeof(cb->val.hmask));
+ cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128;
+
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,
+ memset(&cb->val.haddr, 0, sizeof(cb->val.haddr));
+ memcpy(&cb->val.haddr,
xtables_sa_host(p->ai_addr, p->ai_family),
xtables_sa_hostlen(p->ai_family));
++adcount;
continue;
}
- if (memcmp(&cb->val.inetaddr,
+ if (memcmp(&cb->val.haddr,
xtables_sa_host(p->ai_addr, p->ai_family),
xtables_sa_hostlen(p->ai_family)) != 0)
xt_params->exit_err(PARAMETER_PROBLEM,
@@ -453,8 +458,8 @@ static void xtopt_parse_onehost(struct xt_option_call *cb)
freeaddrinfo(res);
if (cb->entry->flags & XTOPT_PUT)
/* Validation in xtables_option_metavalidate */
- memcpy(XTOPT_MKPTR(cb), &cb->val.inetaddr,
- sizeof(cb->val.inetaddr));
+ memcpy(XTOPT_MKPTR(cb), &cb->val.haddr,
+ sizeof(cb->val.haddr));
}
/**
@@ -488,7 +493,31 @@ static int xtables_getportbyname(const char *name)
}
/**
- * Validate and parse a port specification and put the result into @cb.
+ * Validate and parse a protocol specification (number or name) by use of
+ * /etc/protocols and put the result into @cb->val.protocol.
+ */
+static void xtopt_parse_protocol(struct xt_option_call *cb)
+{
+ const struct protoent *entry;
+ unsigned int value = -1;
+
+ if (xtables_strtoui(cb->arg, NULL, &value, 0, UINT8_MAX)) {
+ cb->val.protocol = value;
+ return;
+ }
+ entry = getprotobyname(cb->arg);
+ if (entry == NULL)
+ xt_params->exit_err(PARAMETER_PROBLEM,
+ "Protocol \"%s\" does not resolve to anything.\n",
+ cb->arg);
+ cb->val.protocol = entry->p_proto;
+ if (cb->entry->flags & XTOPT_PUT)
+ *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.protocol;
+}
+
+/**
+ * Validate and parse a port specification and put the result into
+ * @cb->val.port.
*/
static void xtopt_parse_port(struct xt_option_call *cb)
{
@@ -561,6 +590,88 @@ static void xtopt_parse_mport(struct xt_option_call *cb)
free(lo_arg);
}
+/**
+ * Parse an integer and ensure it is within the address family's prefix length
+ * limits. The result is stored in @cb->val.hlen.
+ */
+static void xtopt_parse_plen(struct xt_option_call *cb)
+{
+ const struct xt_option_entry *entry = cb->entry;
+ unsigned int prefix_len = 128; /* happiness is a warm gcc */
+
+ cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128;
+ if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen))
+ xt_params->exit_err(PARAMETER_PROBLEM,
+ "%s: bad value for option \"--%s\", "
+ "or out of range (%u-%u).\n",
+ cb->ext_name, entry->name, 0, cb->val.hlen);
+
+ cb->val.hlen = prefix_len;
+}
+
+/**
+ * Reuse xtopt_parse_plen for testing the integer. Afterwards convert this to
+ * a bitmask, and make it available through @cb->val.hmask (hlen remains
+ * valid). If %XTOPT_PUT is used, hmask will be copied to the target area.
+ */
+static void xtopt_parse_plenmask(struct xt_option_call *cb)
+{
+ const struct xt_option_entry *entry = cb->entry;
+ uint32_t *mask = cb->val.hmask.all;
+
+ xtopt_parse_plen(cb);
+
+ memset(mask, 0xFF, sizeof(union nf_inet_addr));
+ /* This shifting is AF-independent. */
+ if (cb->val.hlen == 0) {
+ mask[0] = mask[1] = mask[2] = mask[3] = 0;
+ } else if (cb->val.hlen <= 32) {
+ mask[0] <<= 32 - cb->val.hlen;
+ mask[1] = mask[2] = mask[3] = 0;
+ } else if (cb->val.hlen <= 64) {
+ mask[1] <<= 32 - (cb->val.hlen - 32);
+ mask[2] = mask[3] = 0;
+ } else if (cb->val.hlen <= 96) {
+ mask[2] <<= 32 - (cb->val.hlen - 64);
+ mask[3] = 0;
+ } else if (cb->val.hlen <= 128) {
+ mask[3] <<= 32 - (cb->val.hlen - 96);
+ }
+ mask[0] = htonl(mask[0]);
+ mask[1] = htonl(mask[1]);
+ mask[2] = htonl(mask[2]);
+ mask[3] = htonl(mask[3]);
+ if (entry->flags & XTOPT_PUT)
+ memcpy(XTOPT_MKPTR(cb), mask, sizeof(union nf_inet_addr));
+}
+
+static void xtopt_parse_hostmask(struct xt_option_call *cb)
+{
+ const char *orig_arg = cb->arg;
+ char *work, *p;
+
+ if (strchr(cb->arg, '/') == NULL) {
+ xtopt_parse_host(cb);
+ return;
+ }
+ work = strdup(orig_arg);
+ if (work == NULL)
+ xt_params->exit_err(PARAMETER_PROBLEM, "strdup");
+ p = strchr(work, '/'); /* by def this can't be NULL now */
+ *p++ = '\0';
+ /*
+ * Because xtopt_parse_host and xtopt_parse_plenmask would store
+ * different things in the same target area, XTTYPE_HOSTMASK must
+ * disallow XTOPT_PUT, which it does by forcing its absence,
+ * cf. not being listed in xtopt_psize.
+ */
+ cb->arg = work;
+ xtopt_parse_host(cb);
+ cb->arg = p;
+ xtopt_parse_plenmask(cb);
+ cb->arg = orig_arg;
+}
+
static void (*const xtopt_subparse[])(struct xt_option_call *) = {
[XTTYPE_UINT8] = xtopt_parse_int,
[XTTYPE_UINT16] = xtopt_parse_int,
@@ -575,14 +686,22 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = {
[XTTYPE_TOSMASK] = xtopt_parse_tosmask,
[XTTYPE_MARKMASK32] = xtopt_parse_markmask,
[XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel,
- [XTTYPE_ONEHOST] = xtopt_parse_onehost,
+ [XTTYPE_HOST] = xtopt_parse_host,
+ [XTTYPE_HOSTMASK] = xtopt_parse_hostmask,
+ [XTTYPE_PROTOCOL] = xtopt_parse_protocol,
[XTTYPE_PORT] = xtopt_parse_port,
[XTTYPE_PORT_NE] = xtopt_parse_port,
[XTTYPE_PORTRC] = xtopt_parse_mport,
[XTTYPE_PORTRC_NE] = xtopt_parse_mport,
+ [XTTYPE_PLEN] = xtopt_parse_plen,
+ [XTTYPE_PLENMASK] = xtopt_parse_plenmask,
};
static const size_t xtopt_psize[] = {
+ /*
+ * All types not listed here, and thus essentially being initialized to
+ * zero have zero on purpose.
+ */
[XTTYPE_UINT8] = sizeof(uint8_t),
[XTTYPE_UINT16] = sizeof(uint16_t),
[XTTYPE_UINT32] = sizeof(uint32_t),
@@ -594,11 +713,14 @@ static const size_t xtopt_psize[] = {
[XTTYPE_DOUBLE] = sizeof(double),
[XTTYPE_STRING] = -1,
[XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t),
- [XTTYPE_ONEHOST] = sizeof(union nf_inet_addr),
+ [XTTYPE_HOST] = sizeof(union nf_inet_addr),
+ [XTTYPE_HOSTMASK] = sizeof(union nf_inet_addr),
+ [XTTYPE_PROTOCOL] = sizeof(uint8_t),
[XTTYPE_PORT] = sizeof(uint16_t),
[XTTYPE_PORT_NE] = sizeof(uint16_t),
[XTTYPE_PORTRC] = sizeof(uint16_t[2]),
[XTTYPE_PORTRC_NE] = sizeof(uint16_t[2]),
+ [XTTYPE_PLENMASK] = sizeof(union nf_inet_addr),
};
/**
@@ -653,7 +775,8 @@ void xtables_option_metavalidate(const char *name,
name, entry->id);
if (!(entry->flags & XTOPT_PUT))
continue;
- if (entry->type >= ARRAY_SIZE(xtopt_psize))
+ if (entry->type >= ARRAY_SIZE(xtopt_psize) ||
+ xtopt_psize[entry->type] == 0)
xt_params->exit_err(OTHER_PROBLEM,
"%s: entry type of option \"--%s\" cannot be "
"combined with XTOPT_PUT\n",
@@ -710,6 +833,7 @@ void xtables_option_tpcall(unsigned int c, char **argv, bool invert,
cb.data = t->t->data;
cb.xflags = t->tflags;
cb.target = &t->t;
+ cb.xt_entry = fw;
t->x6_parse(&cb);
t->tflags = cb.xflags;
}
@@ -744,6 +868,7 @@ void xtables_option_mpcall(unsigned int c, char **argv, bool invert,
cb.data = m->m->data;
cb.xflags = m->mflags;
cb.match = &m->m;
+ cb.xt_entry = fw;
m->x6_parse(&cb);
m->mflags = cb.xflags;
}