Signed-off-by: Jan Engelhardt <jengelh@xxxxxxxxxx> --- extensions/libxt_policy.c | 269 ++++++++++++--------------------------------- 1 files changed, 73 insertions(+), 196 deletions(-) diff --git a/extensions/libxt_policy.c b/extensions/libxt_policy.c index 16e8c53..a514246 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, }, }; -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html