diff options
author | Jan Engelhardt <jengelh@medozas.de> | 2009-06-01 11:46:12 +0200 |
---|---|---|
committer | Jan Engelhardt <jengelh@medozas.de> | 2009-06-01 11:46:12 +0200 |
commit | 67cf1a928952f1d1ca32f529d78036cebc1b8800 (patch) | |
tree | a4800406c1813082bb2dab8ca172acc836b0a75d /extensions | |
parent | cd30054544021bad206efb6b98df640528e1cba1 (diff) |
policy: merge ipv6 and ipv4 variant
The files duplicate most of their code, and struct ipt_policy_info
being defined to xt_policy_info makes them actually have even more in
common.
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/libip6t_policy.c | 432 | ||||
-rw-r--r-- | extensions/libxt_policy.c (renamed from extensions/libipt_policy.c) | 145 |
2 files changed, 114 insertions, 463 deletions
diff --git a/extensions/libip6t_policy.c b/extensions/libip6t_policy.c deleted file mode 100644 index daeff893..00000000 --- a/extensions/libip6t_policy.c +++ /dev/null @@ -1,432 +0,0 @@ -/* Shared library add-on to ip6tables to add policy support. */ -#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 <libiptc/libip6tc.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; - -static void policy_help(void) -{ - printf( -"policy match options:\n" -" --dir in|out match policy applied during decapsulation/\n" -" policy to be applied during encapsulation\n" -" --pol none|ipsec match policy\n" -" --strict match entire policy instead of single element\n" -" at any position\n" -"[!] --reqid reqid match reqid\n" -"[!] --spi spi match SPI\n" -"[!] --proto proto match protocol (ah/esp/ipcomp)\n" -"[!] --mode mode match mode (transport/tunnel)\n" -"[!] --tunnel-src addr/masklen match tunnel source\n" -"[!] --tunnel-dst addr/masklen match tunnel destination\n" -" --next begin next element in policy\n"); -} - -static const struct option policy_opts[] = -{ - { - .name = "dir", - .has_arg = 1, - .val = '1', - }, - { - .name = "pol", - .has_arg = 1, - .val = '2', - }, - { - .name = "strict", - .val = '3' - }, - { - .name = "reqid", - .has_arg = 1, - .val = '4', - }, - { - .name = "spi", - .has_arg = 1, - .val = '5' - }, - { - .name = "tunnel-src", - .has_arg = 1, - .val = '6' - }, - { - .name = "tunnel-dst", - .has_arg = 1, - .val = '7' - }, - { - .name = "proto", - .has_arg = 1, - .val = '8' - }, - { - .name = "mode", - .has_arg = 1, - .val = '9' - }, - { - .name = "next", - .val = 'a' - }, - { .name = NULL } -}; - -static int parse_direction(char *s) -{ - if (strcmp(s, "in") == 0) - return XT_POLICY_MATCH_IN; - if (strcmp(s, "out") == 0) - return XT_POLICY_MATCH_OUT; - xtables_error(PARAMETER_PROBLEM, "policy_match: invalid dir \"%s\"", s); -} - -static int parse_policy(char *s) -{ - if (strcmp(s, "none") == 0) - return XT_POLICY_MATCH_NONE; - if (strcmp(s, "ipsec") == 0) - return 0; - xtables_error(PARAMETER_PROBLEM, "policy match: invalid policy \"%s\"", s); -} - -static int parse_mode(char *s) -{ - if (strcmp(s, "transport") == 0) - return XT_POLICY_MODE_TRANSPORT; - if (strcmp(s, "tunnel") == 0) - return XT_POLICY_MODE_TUNNEL; - xtables_error(PARAMETER_PROBLEM, "policy match: invalid mode \"%s\"", s); -} - -static int policy_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - struct xt_policy_info *info = (void *)(*match)->data; - struct xt_policy_elem *e = &info->pol[info->len]; - struct in6_addr *addr = NULL, mask; - unsigned int naddr = 0, num; - int mode; - - xtables_check_inverse(optarg, &invert, &optind, 0); - - 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(argv[optind-1]); - break; - case '2': - if (invert) - xtables_error(PARAMETER_PROBLEM, - "policy match: can't invert --policy option"); - - info->flags |= parse_policy(argv[optind-1]); - 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"); - - info->flags |= XT_POLICY_MATCH_STRICT; - break; - case '4': - 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", "--reqid", optarg); - e->reqid = num; - break; - case '5': - 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; - break; - case '6': - if (e->match.saddr) - xtables_error(PARAMETER_PROBLEM, - "policy match: double --tunnel-src option"); - - xtables_ip6parse_any(argv[optind-1], &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; - memcpy(&e->saddr.a6, addr, sizeof(*addr)); - memcpy(&e->smask.a6, &mask, sizeof(mask)); - break; - case '7': - if (e->match.daddr) - xtables_error(PARAMETER_PROBLEM, - "policy match: double --tunnel-dst option"); - - xtables_ip6parse_any(argv[optind-1], &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; - memcpy(&e->daddr.a6, addr, sizeof(*addr)); - memcpy(&e->dmask.a6, &mask, sizeof(mask)); - break; - case '8': - if (e->match.proto) - xtables_error(PARAMETER_PROBLEM, - "policy match: double --proto option"); - - e->proto = xtables_parse_protocol(argv[optind-1]); - if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP && - e->proto != IPPROTO_COMP) - xtables_error(PARAMETER_PROBLEM, - "policy match: protocol must ah/esp/ipcomp"); - e->match.proto = 1; - e->invert.proto = invert; - break; - case '9': - if (e->match.mode) - xtables_error(PARAMETER_PROBLEM, - "policy match: double --mode option"); - - mode = parse_mode(argv[optind-1]); - e->match.mode = 1; - e->invert.mode = invert; - e->mode = mode; - break; - case 'a': - if (invert) - xtables_error(PARAMETER_PROBLEM, - "policy match: can't invert --next option"); - - if (++info->len == XT_POLICY_MAX_ELEM) - xtables_error(PARAMETER_PROBLEM, - "policy match: maximum policy depth reached"); - break; - default: - return 0; - } - - policy_info = info; - return 1; -} - -static void policy_check(unsigned int flags) -{ - struct xt_policy_info *info = policy_info; - struct xt_policy_elem *e; - int i; - - if (info == NULL) - xtables_error(PARAMETER_PROBLEM, - "policy match: no parameters given"); - - if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) - xtables_error(PARAMETER_PROBLEM, - "policy match: neither --in nor --out specified"); - - if (info->flags & XT_POLICY_MATCH_NONE) { - if (info->flags & XT_POLICY_MATCH_STRICT) - xtables_error(PARAMETER_PROBLEM, - "policy match: policy none but --strict given"); - - if (info->len != 0) - xtables_error(PARAMETER_PROBLEM, - "policy match: policy none but policy given"); - } else - info->len++; /* increase len by 1, no --next after last element */ - - if (!(info->flags & XT_POLICY_MATCH_STRICT) && info->len > 1) - xtables_error(PARAMETER_PROBLEM, - "policy match: multiple elements but no --strict"); - - for (i = 0; i < info->len; i++) { - e = &info->pol[i]; - - if (info->flags & XT_POLICY_MATCH_STRICT && - !(e->match.reqid || e->match.spi || e->match.saddr || - e->match.daddr || e->match.proto || e->match.mode)) - xtables_error(PARAMETER_PROBLEM, - "policy match: empty policy element"); - - if ((e->match.saddr || e->match.daddr) - && ((e->mode == XT_POLICY_MODE_TUNNEL && e->invert.mode) || - (e->mode == XT_POLICY_MODE_TRANSPORT && !e->invert.mode))) - xtables_error(PARAMETER_PROBLEM, - "policy match: --tunnel-src/--tunnel-dst " - "is only valid in tunnel mode"); - } -} - -static void print_mode(char *prefix, u_int8_t mode, int numeric) -{ - printf("%smode ", prefix); - - switch (mode) { - case XT_POLICY_MODE_TRANSPORT: - printf("transport "); - break; - case XT_POLICY_MODE_TUNNEL: - printf("tunnel "); - break; - default: - printf("??? "); - break; - } -} - -static void print_proto(char *prefix, u_int8_t proto, int numeric) -{ - struct protoent *p = NULL; - - printf("%sproto ", prefix); - if (!numeric) - p = getprotobynumber(proto); - if (p != NULL) - printf("%s ", p->p_name); - else - printf("%u ", proto); -} - -#define PRINT_INVERT(x) \ -do { \ - if (x) \ - printf("! "); \ -} while(0) - -static void print_entry(char *prefix, const struct xt_policy_elem *e, - int numeric) -{ - if (e->match.reqid) { - PRINT_INVERT(e->invert.reqid); - printf("%sreqid %u ", prefix, e->reqid); - } - if (e->match.spi) { - PRINT_INVERT(e->invert.spi); - printf("%sspi 0x%x ", prefix, e->spi); - } - if (e->match.proto) { - PRINT_INVERT(e->invert.proto); - print_proto(prefix, e->proto, numeric); - } - if (e->match.mode) { - PRINT_INVERT(e->invert.mode); - print_mode(prefix, e->mode, numeric); - } - if (e->match.daddr) { - PRINT_INVERT(e->invert.daddr); - printf("%stunnel-dst %s%s ", prefix, - xtables_ip6addr_to_numeric(&e->daddr.a6), - xtables_ip6mask_to_numeric(&e->dmask.a6)); - } - if (e->match.saddr) { - PRINT_INVERT(e->invert.saddr); - printf("%stunnel-src %s%s ", prefix, - xtables_ip6addr_to_numeric(&e->saddr.a6), - xtables_ip6mask_to_numeric(&e->smask.a6)); - } -} - -static void print_flags(char *prefix, const struct xt_policy_info *info) -{ - if (info->flags & XT_POLICY_MATCH_IN) - printf("%sdir in ", prefix); - else - printf("%sdir out ", prefix); - - if (info->flags & XT_POLICY_MATCH_NONE) - printf("%spol none ", prefix); - else - printf("%spol ipsec ", prefix); - - if (info->flags & XT_POLICY_MATCH_STRICT) - printf("%sstrict ", prefix); -} - -static void policy_print(const void *ip, const struct xt_entry_match *match, - int numeric) -{ - const struct xt_policy_info *info = (void *)match->data; - unsigned int i; - - printf("policy match "); - print_flags("", info); - for (i = 0; i < info->len; i++) { - if (info->len > 1) - printf("[%u] ", i); - print_entry("", &info->pol[i], numeric); - } - - printf("\n"); -} - -static void policy_save(const void *ip, const struct xt_entry_match *match) -{ - const struct xt_policy_info *info = (void *)match->data; - unsigned int i; - - print_flags("--", info); - for (i = 0; i < info->len; i++) { - print_entry("--", &info->pol[i], 0); - if (i + 1 < info->len) - printf("--next "); - } -} - -static struct xtables_match policy_mt6_reg = { - .name = "policy", - .version = XTABLES_VERSION, - .family = NFPROTO_IPV6, - .size = XT_ALIGN(sizeof(struct xt_policy_info)), - .userspacesize = XT_ALIGN(sizeof(struct xt_policy_info)), - .help = policy_help, - .parse = policy_parse, - .final_check = policy_check, - .print = policy_print, - .save = policy_save, - .extra_opts = policy_opts, -}; - -void _init(void) -{ - xtables_register_match(&policy_mt6_reg); -} diff --git a/extensions/libipt_policy.c b/extensions/libxt_policy.c index d6bad003..d17b1bbc 100644 --- a/extensions/libipt_policy.c +++ b/extensions/libxt_policy.c @@ -118,12 +118,12 @@ 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, - const void *entry, struct xt_entry_match **match) +static int policy_parse(int c, int invert, unsigned int *flags, + struct xt_policy_info *info, uint8_t family) { - struct xt_policy_info *info = (void *)(*match)->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; @@ -138,14 +138,14 @@ static int policy_parse(int c, char **argv, int invert, unsigned int *flags, xtables_error(PARAMETER_PROBLEM, "policy match: can't invert --dir option"); - info->flags |= parse_direction(argv[optind-1]); + info->flags |= parse_direction(optarg); break; case '2': if (invert) xtables_error(PARAMETER_PROBLEM, "policy match: can't invert --policy option"); - info->flags |= parse_policy(argv[optind-1]); + info->flags |= parse_policy(optarg); break; case '3': if (info->flags & XT_POLICY_MATCH_STRICT) @@ -185,37 +185,53 @@ static int policy_parse(int c, char **argv, int invert, unsigned int *flags, xtables_error(PARAMETER_PROBLEM, "policy match: double --tunnel-src option"); - xtables_ipparse_any(argv[optind-1], &addr, &mask, &naddr); + 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; - e->saddr.a4 = addr[0]; - e->smask.a4 = mask; + 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; + } break; case '7': if (e->match.daddr) xtables_error(PARAMETER_PROBLEM, "policy match: double --tunnel-dst option"); - xtables_ipparse_any(argv[optind-1], &addr, &mask, &naddr); + 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; - e->daddr.a4 = addr[0]; - e->dmask.a4 = mask; + 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; + } break; case '8': if (e->match.proto) xtables_error(PARAMETER_PROBLEM, "policy match: double --proto option"); - e->proto = xtables_parse_protocol(argv[optind-1]); + e->proto = xtables_parse_protocol(optarg); if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP && e->proto != IPPROTO_COMP) xtables_error(PARAMETER_PROBLEM, @@ -228,7 +244,7 @@ static int policy_parse(int c, char **argv, int invert, unsigned int *flags, xtables_error(PARAMETER_PROBLEM, "policy match: double --mode option"); - mode = parse_mode(argv[optind-1]); + mode = parse_mode(optarg); e->match.mode = 1; e->invert.mode = invert; e->mode = mode; @@ -250,6 +266,20 @@ static int policy_parse(int c, char **argv, int invert, unsigned int *flags, 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, 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) +{ + return policy_parse(c, invert, flags, (void *)(*match)->data, + NFPROTO_IPV6); +} + static void policy_check(unsigned int flags) { struct xt_policy_info *info = policy_info; @@ -297,7 +327,7 @@ static void policy_check(unsigned int flags) } } -static void print_mode(char *prefix, u_int8_t mode, int numeric) +static void print_mode(const char *prefix, u_int8_t mode, int numeric) { printf("%smode ", prefix); @@ -314,7 +344,7 @@ static void print_mode(char *prefix, u_int8_t mode, int numeric) } } -static void print_proto(char *prefix, u_int8_t proto, int numeric) +static void print_proto(const char *prefix, u_int8_t proto, int numeric) { struct protoent *p = NULL; @@ -333,8 +363,8 @@ do { \ printf("! "); \ } while(0) -static void print_entry(char *prefix, const struct xt_policy_elem *e, - int numeric) +static void print_entry(const char *prefix, const struct xt_policy_elem *e, + bool numeric, uint8_t family) { if (e->match.reqid) { PRINT_INVERT(e->invert.reqid); @@ -354,15 +384,25 @@ static void print_entry(char *prefix, const struct xt_policy_elem *e, } if (e->match.daddr) { PRINT_INVERT(e->invert.daddr); - printf("%stunnel-dst %s%s ", prefix, - xtables_ipaddr_to_numeric((const void *)&e->daddr), - xtables_ipmask_to_numeric((const void *)&e->dmask)); + if (family == NFPROTO_IPV6) + printf("%stunnel-dst %s%s ", prefix, + xtables_ip6addr_to_numeric(&e->daddr.a6), + xtables_ip6mask_to_numeric(&e->dmask.a6)); + else + printf("%stunnel-dst %s%s ", prefix, + xtables_ipaddr_to_numeric(&e->daddr.a4), + xtables_ipmask_to_numeric(&e->dmask.a4)); } if (e->match.saddr) { PRINT_INVERT(e->invert.saddr); - printf("%stunnel-src %s%s ", prefix, - xtables_ipaddr_to_numeric((const void *)&e->saddr), - xtables_ipmask_to_numeric((const void *)&e->smask)); + if (family == NFPROTO_IPV6) + printf("%stunnel-src %s%s ", prefix, + xtables_ip6addr_to_numeric(&e->saddr.a6), + xtables_ip6mask_to_numeric(&e->smask.a6)); + else + printf("%stunnel-src %s%s ", prefix, + xtables_ipaddr_to_numeric(&e->saddr.a4), + xtables_ipmask_to_numeric(&e->smask.a4)); } } @@ -382,8 +422,23 @@ static void print_flags(char *prefix, const struct xt_policy_info *info) printf("%sstrict ", prefix); } -static void policy_print(const void *ip, const struct xt_entry_match *match, - int numeric) +static void policy4_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + const struct xt_policy_info *info = (void *)match->data; + unsigned int i; + + printf("policy match "); + print_flags("", info); + for (i = 0; i < info->len; i++) { + if (info->len > 1) + printf("[%u] ", i); + print_entry("", &info->pol[i], numeric, NFPROTO_IPV4); + } +} + +static void policy6_print(const void *ip, const struct xt_entry_match *match, + int numeric) { const struct xt_policy_info *info = (void *)match->data; unsigned int i; @@ -393,18 +448,31 @@ static void policy_print(const void *ip, const struct xt_entry_match *match, for (i = 0; i < info->len; i++) { if (info->len > 1) printf("[%u] ", i); - print_entry("", &info->pol[i], numeric); + print_entry("", &info->pol[i], numeric, NFPROTO_IPV6); } } -static void policy_save(const void *ip, const struct xt_entry_match *match) +static void policy4_save(const void *ip, const struct xt_entry_match *match) { const struct xt_policy_info *info = (void *)match->data; unsigned int i; print_flags("--", info); for (i = 0; i < info->len; i++) { - print_entry("--", &info->pol[i], 0); + print_entry("--", &info->pol[i], false, NFPROTO_IPV4); + if (i + 1 < info->len) + printf("--next "); + } +} + +static void policy6_save(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_policy_info *info = (void *)match->data; + unsigned int i; + + print_flags("--", info); + for (i = 0; i < info->len; i++) { + print_entry("--", &info->pol[i], false, NFPROTO_IPV6); if (i + 1 < info->len) printf("--next "); } @@ -417,14 +485,29 @@ 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 = policy_parse, + .parse = policy4_parse, + .final_check = policy_check, + .print = policy4_print, + .save = policy4_save, + .extra_opts = policy_opts, +}; + +static struct xtables_match policy_mt6_reg = { + .name = "policy", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .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, - .print = policy_print, - .save = policy_save, + .print = policy6_print, + .save = policy6_save, .extra_opts = policy_opts, }; void _init(void) { xtables_register_match(&policy_mt_reg); + xtables_register_match(&policy_mt6_reg); } |