diff options
-rw-r--r-- | extensions/libipt_addrtype.c | 188 | ||||
-rw-r--r-- | extensions/libipt_addrtype.man | 34 | ||||
-rw-r--r-- | include/linux/netfilter_ipv4/ipt_addrtype.h | 14 |
3 files changed, 220 insertions, 16 deletions
diff --git a/extensions/libipt_addrtype.c b/extensions/libipt_addrtype.c index 9611c39a..97ad8044 100644 --- a/extensions/libipt_addrtype.c +++ b/extensions/libipt_addrtype.c @@ -36,7 +36,7 @@ static void addrtype_help_types(void) printf(" %s\n", rtn_names[i]); } -static void addrtype_help(void) +static void addrtype_help_v0(void) { printf( "Address type match options:\n" @@ -47,6 +47,19 @@ static void addrtype_help(void) addrtype_help_types(); } +static void addrtype_help_v1(void) +{ + printf( +"Address type match options:\n" +" [!] --src-type type[,...] Match source address type\n" +" [!] --dst-type type[,...] Match destination address type\n" +" --limit-iface-in Match only on the packet's incoming device\n" +" --limit-iface-out Match only on the packet's incoming device\n" +"\n" +"Valid types: \n"); + addrtype_help_types(); +} + static int parse_type(const char *name, size_t len, u_int16_t *mask) { @@ -79,10 +92,12 @@ static void parse_types(const char *arg, u_int16_t *mask) #define IPT_ADDRTYPE_OPT_SRCTYPE 0x1 #define IPT_ADDRTYPE_OPT_DSTTYPE 0x2 +#define IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN 0x4 +#define IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT 0x8 static int -addrtype_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +addrtype_parse_v0(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) { struct ipt_addrtype_info *info = (struct ipt_addrtype_info *) (*match)->data; @@ -115,11 +130,72 @@ addrtype_parse(int c, char **argv, int invert, unsigned int *flags, return 1; } -static void addrtype_check(unsigned int flags) +static int +addrtype_parse_v1(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + struct ipt_addrtype_info_v1 *info = + (struct ipt_addrtype_info_v1 *) (*match)->data; + + switch (c) { + case '1': + if (*flags & IPT_ADDRTYPE_OPT_SRCTYPE) + exit_error(PARAMETER_PROBLEM, + "addrtype: can't specify src-type twice"); + check_inverse(optarg, &invert, &optind, 0); + parse_types(argv[optind-1], &info->source); + if (invert) + info->flags |= IPT_ADDRTYPE_INVERT_SOURCE; + *flags |= IPT_ADDRTYPE_OPT_SRCTYPE; + break; + case '2': + if (*flags & IPT_ADDRTYPE_OPT_DSTTYPE) + exit_error(PARAMETER_PROBLEM, + "addrtype: can't specify dst-type twice"); + check_inverse(optarg, &invert, &optind, 0); + parse_types(argv[optind-1], &info->dest); + if (invert) + info->flags |= IPT_ADDRTYPE_INVERT_DEST; + *flags |= IPT_ADDRTYPE_OPT_DSTTYPE; + break; + case '3': + if (*flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN) + exit_error(PARAMETER_PROBLEM, + "addrtype: can't specify limit-iface-in twice"); + info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_IN; + *flags |= IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN; + break; + case '4': + if (*flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT) + exit_error(PARAMETER_PROBLEM, + "addrtype: can't specify limit-iface-out twice"); + info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_OUT; + *flags |= IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT; + break; + default: + return 0; + } + + return 1; +} + +static void addrtype_check_v0(unsigned int flags) +{ + if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE))) + exit_error(PARAMETER_PROBLEM, + "addrtype: you must specify --src-type or --dst-type"); +} + +static void addrtype_check_v1(unsigned int flags) { if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE))) exit_error(PARAMETER_PROBLEM, "addrtype: you must specify --src-type or --dst-type"); + if (flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN && + flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT) + exit_error(PARAMETER_PROBLEM, + "addrtype: you can't specify both --limit-iface-in " + "and --limit-iface-out"); } static void print_types(u_int16_t mask) @@ -136,8 +212,8 @@ static void print_types(u_int16_t mask) printf(" "); } -static void addrtype_print(const void *ip, const struct xt_entry_match *match, - int numeric) +static void addrtype_print_v0(const void *ip, const struct xt_entry_match *match, + int numeric) { const struct ipt_addrtype_info *info = (struct ipt_addrtype_info *) match->data; @@ -157,7 +233,34 @@ static void addrtype_print(const void *ip, const struct xt_entry_match *match, } } -static void addrtype_save(const void *ip, const struct xt_entry_match *match) +static void addrtype_print_v1(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + const struct ipt_addrtype_info_v1 *info = + (struct ipt_addrtype_info_v1 *) match->data; + + printf("ADDRTYPE match "); + if (info->source) { + printf("src-type "); + if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE) + printf("!"); + print_types(info->source); + } + if (info->dest) { + printf("dst-type "); + if (info->flags & IPT_ADDRTYPE_INVERT_DEST) + printf("!"); + print_types(info->dest); + } + if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { + printf("limit-in "); + } + if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { + printf("limit-out "); + } +} + +static void addrtype_save_v0(const void *ip, const struct xt_entry_match *match) { const struct ipt_addrtype_info *info = (struct ipt_addrtype_info *) match->data; @@ -176,28 +279,83 @@ static void addrtype_save(const void *ip, const struct xt_entry_match *match) } } +static void addrtype_save_v1(const void *ip, const struct xt_entry_match *match) +{ + const struct ipt_addrtype_info_v1 *info = + (struct ipt_addrtype_info_v1 *) match->data; + + if (info->source) { + printf("--src-type "); + if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE) + printf("! "); + print_types(info->source); + } + if (info->dest) { + printf("--dst-type "); + if (info->flags & IPT_ADDRTYPE_INVERT_DEST) + printf("! "); + print_types(info->dest); + } + if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { + printf("--limit-iface-in "); + } + if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { + printf("--limit-iface-out "); + } +} + static const struct option addrtype_opts[] = { { "src-type", 1, NULL, '1' }, { "dst-type", 1, NULL, '2' }, { .name = NULL } }; -static struct xtables_match addrtype_mt_reg = { +static const struct option addrtype_opts_v0[] = { + { "src-type", 1, NULL, '1' }, + { "dst-type", 1, NULL, '2' }, + { .name = NULL } +}; + +static const struct option addrtype_opts_v1[] = { + { "src-type", 1, NULL, '1' }, + { "dst-type", 1, NULL, '2' }, + { "limit-iface-in", 0, NULL, '3' }, + { "limit-iface-out", 0, NULL, '4' }, + { .name = NULL } +}; + +static struct xtables_match addrtype_mt_reg_v0 = { .name = "addrtype", .version = XTABLES_VERSION, .family = PF_INET, .size = XT_ALIGN(sizeof(struct ipt_addrtype_info)), .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info)), - .help = addrtype_help, - .parse = addrtype_parse, - .final_check = addrtype_check, - .print = addrtype_print, - .save = addrtype_save, - .extra_opts = addrtype_opts, + .help = addrtype_help_v0, + .parse = addrtype_parse_v0, + .final_check = addrtype_check_v0, + .print = addrtype_print_v0, + .save = addrtype_save_v0, + .extra_opts = addrtype_opts_v0, +}; + +static struct xtables_match addrtype_mt_reg_v1 = { + .name = "addrtype", + .version = XTABLES_VERSION, + .family = PF_INET, + .size = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)), + .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)), + .help = addrtype_help_v1, + .parse = addrtype_parse_v1, + .final_check = addrtype_check_v1, + .print = addrtype_print_v1, + .save = addrtype_save_v1, + .extra_opts = addrtype_opts_v1, + .revision = 1, }; void _init(void) { - xtables_register_match(&addrtype_mt_reg); + xtables_register_match(&addrtype_mt_reg_v0); + xtables_register_match(&addrtype_mt_reg_v1); } diff --git a/extensions/libipt_addrtype.man b/extensions/libipt_addrtype.man index 2c3bbab0..af5e6484 100644 --- a/extensions/libipt_addrtype.man +++ b/extensions/libipt_addrtype.man @@ -7,31 +7,63 @@ The following address types are possible: .TP .BI "UNSPEC" an unspecified address (i.e. 0.0.0.0) +.TP .BI "UNICAST" an unicast address +.TP .BI "LOCAL" a local address +.TP .BI "BROADCAST" a broadcast address +.TP .BI "ANYCAST" an anycast packet +.TP .BI "MULTICAST" a multicast address +.TP .BI "BLACKHOLE" a blackhole address +.TP .BI "UNREACHABLE" an unreachable address +.TP .BI "PROHIBIT" a prohibited address +.TP .BI "THROW" FIXME +.TP .BI "NAT" FIXME +.TP .BI "XRESOLVE" -FIXME .TP .BI "--src-type " "type" Matches if the source address is of given type .TP .BI "--dst-type " "type" Matches if the destination address is of given type +.TP +.BI "--limit-iface-in" +The address type checking can be limited to the interface the packet is coming +in. This option is only valid in the +.BR PREROUTING , +.B INPUT +and +.B FORWARD +chains. It cannot be specified with the +.B "--limit-iface-out" +option. +.TP +.BI "--limit-iface-out" +The address type checiking can be limited to the interface the packet is going +out. This option is only valid in the +.BR POSTROUTING , +.B OUTPUT +and +.B FORWARD +chains. It cannot be specified with the +.B --limit-iface-in +option. diff --git a/include/linux/netfilter_ipv4/ipt_addrtype.h b/include/linux/netfilter_ipv4/ipt_addrtype.h index 166ed01a..446de6ae 100644 --- a/include/linux/netfilter_ipv4/ipt_addrtype.h +++ b/include/linux/netfilter_ipv4/ipt_addrtype.h @@ -1,6 +1,20 @@ #ifndef _IPT_ADDRTYPE_H #define _IPT_ADDRTYPE_H +enum { + IPT_ADDRTYPE_INVERT_SOURCE = 0x0001, + IPT_ADDRTYPE_INVERT_DEST = 0x0002, + IPT_ADDRTYPE_LIMIT_IFACE_IN = 0x0004, + IPT_ADDRTYPE_LIMIT_IFACE_OUT = 0x0008, +}; + +struct ipt_addrtype_info_v1 { + u_int16_t source; /* source-type mask */ + u_int16_t dest; /* dest-type mask */ + u_int32_t flags; +}; + +/* revision 0 */ struct ipt_addrtype_info { u_int16_t source; /* source-type mask */ u_int16_t dest; /* dest-type mask */ |