summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'extensions')
-rw-r--r--extensions/libxt_policy.c269
1 files changed, 73 insertions, 196 deletions
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,
},
};