From e62f426c7ead7c0025d15860df97426db6509942 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:08 +0200 Subject: Convert the NAT targets to use the kernel supplied nf_nat.h header Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libipt_DNAT.c | 36 ++++++++++++++++++------------------ extensions/libipt_MASQUERADE.c | 32 ++++++++++++++++---------------- extensions/libipt_NETMAP.c | 18 +++++++++--------- extensions/libipt_REDIRECT.c | 34 +++++++++++++++++----------------- extensions/libipt_SAME.c | 21 +++++++++++++-------- extensions/libipt_SNAT.c | 36 ++++++++++++++++++------------------ 6 files changed, 91 insertions(+), 86 deletions(-) (limited to 'extensions') diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c index 466c9def..ff187999 100644 --- a/extensions/libipt_DNAT.c +++ b/extensions/libipt_DNAT.c @@ -6,7 +6,7 @@ #include /* get_kernel_version */ #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_DEST = 0, @@ -23,7 +23,7 @@ enum { struct ipt_natinfo { struct xt_entry_target t; - struct nf_nat_multi_range mr; + struct nf_nat_ipv4_multi_range_compat mr; }; static void DNAT_help(void) @@ -44,7 +44,7 @@ static const struct xt_option_entry DNAT_opts[] = { }; static struct ipt_natinfo * -append_range(struct ipt_natinfo *info, const struct nf_nat_range *range) +append_range(struct ipt_natinfo *info, const struct nf_nat_ipv4_range *range) { unsigned int size; @@ -66,7 +66,7 @@ append_range(struct ipt_natinfo *info, const struct nf_nat_range *range) static struct xt_entry_target * parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) { - struct nf_nat_range range; + struct nf_nat_ipv4_range range; char *arg, *colon, *dash, *error; const struct in_addr *ip; @@ -83,7 +83,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) xtables_error(PARAMETER_PROBLEM, "Need TCP, UDP, SCTP or DCCP with port specification"); - range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; port = atoi(colon+1); if (port <= 0 || port > 65535) @@ -122,7 +122,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) *colon = '\0'; } - range.flags |= IP_NAT_RANGE_MAP_IPS; + range.flags |= NF_NAT_RANGE_MAP_IPS; dash = strchr(arg, '-'); if (colon && dash && dash > colon) dash = NULL; @@ -177,7 +177,7 @@ static void DNAT_parse(struct xt_option_call *cb) cb->xflags |= F_X_TO_DEST; break; case O_PERSISTENT: - info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT; + info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT; break; } } @@ -185,15 +185,15 @@ static void DNAT_parse(struct xt_option_call *cb) static void DNAT_fcheck(struct xt_fcheck_call *cb) { static const unsigned int f = F_TO_DEST | F_RANDOM; - struct nf_nat_multi_range *mr = cb->data; + struct nf_nat_ipv4_multi_range_compat *mr = cb->data; if ((cb->xflags & f) == f) - mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; } -static void print_range(const struct nf_nat_range *r) +static void print_range(const struct nf_nat_ipv4_range *r) { - if (r->flags & IP_NAT_RANGE_MAP_IPS) { + if (r->flags & NF_NAT_RANGE_MAP_IPS) { struct in_addr a; a.s_addr = r->min_ip; @@ -203,7 +203,7 @@ static void print_range(const struct nf_nat_range *r) printf("-%s", xtables_ipaddr_to_numeric(&a)); } } - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(":"); printf("%hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) @@ -220,9 +220,9 @@ static void DNAT_print(const void *ip, const struct xt_entry_target *target, printf(" to:"); for (i = 0; i < info->mr.rangesize; i++) { print_range(&info->mr.range[i]); - if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); - if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT) + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" persistent"); } } @@ -235,9 +235,9 @@ static void DNAT_save(const void *ip, const struct xt_entry_target *target) for (i = 0; i < info->mr.rangesize; i++) { printf(" --to-destination "); print_range(&info->mr.range[i]); - if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); - if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT) + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" --persistent"); } } @@ -246,8 +246,8 @@ static struct xtables_target dnat_tg_reg = { .name = "DNAT", .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)), - .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), + .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), .help = DNAT_help, .x6_parse = DNAT_parse, .x6_fcheck = DNAT_fcheck, diff --git a/extensions/libipt_MASQUERADE.c b/extensions/libipt_MASQUERADE.c index 7ba42dfd..ea074454 100644 --- a/extensions/libipt_MASQUERADE.c +++ b/extensions/libipt_MASQUERADE.c @@ -6,7 +6,7 @@ #include #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_PORTS = 0, @@ -31,7 +31,7 @@ static const struct xt_option_entry MASQUERADE_opts[] = { static void MASQUERADE_init(struct xt_entry_target *t) { - struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data; + struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data; /* Actually, it's 0, but it's ignored at the moment. */ mr->rangesize = 1; @@ -39,12 +39,12 @@ static void MASQUERADE_init(struct xt_entry_target *t) /* Parses ports */ static void -parse_ports(const char *arg, struct nf_nat_multi_range *mr) +parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr) { char *end; unsigned int port, maxport; - mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX)) xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg); @@ -75,7 +75,7 @@ static void MASQUERADE_parse(struct xt_option_call *cb) { const struct ipt_entry *entry = cb->xt_entry; int portok; - struct nf_nat_multi_range *mr = cb->data; + struct nf_nat_ipv4_multi_range_compat *mr = cb->data; if (entry->ip.proto == IPPROTO_TCP || entry->ip.proto == IPPROTO_UDP @@ -95,7 +95,7 @@ static void MASQUERADE_parse(struct xt_option_call *cb) parse_ports(cb->arg, mr); break; case O_RANDOM: - mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; break; } } @@ -104,33 +104,33 @@ static void MASQUERADE_print(const void *ip, const struct xt_entry_target *target, int numeric) { - const struct nf_nat_multi_range *mr = (const void *)target->data; - const struct nf_nat_range *r = &mr->range[0]; + const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data; + const struct nf_nat_ipv4_range *r = &mr->range[0]; - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(" masq ports: "); printf("%hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) printf("-%hu", ntohs(r->max.tcp.port)); } - if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); } static void MASQUERADE_save(const void *ip, const struct xt_entry_target *target) { - const struct nf_nat_multi_range *mr = (const void *)target->data; - const struct nf_nat_range *r = &mr->range[0]; + const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data; + const struct nf_nat_ipv4_range *r = &mr->range[0]; - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(" --to-ports %hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) printf("-%hu", ntohs(r->max.tcp.port)); } - if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); } @@ -138,8 +138,8 @@ static struct xtables_target masquerade_tg_reg = { .name = "MASQUERADE", .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)), - .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), + .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), .help = MASQUERADE_help, .init = MASQUERADE_init, .x6_parse = MASQUERADE_parse, diff --git a/extensions/libipt_NETMAP.c b/extensions/libipt_NETMAP.c index 5c4471a9..dee7b01b 100644 --- a/extensions/libipt_NETMAP.c +++ b/extensions/libipt_NETMAP.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #define MODULENAME "NETMAP" @@ -45,7 +45,7 @@ netmask2bits(uint32_t netmask) static void NETMAP_init(struct xt_entry_target *t) { - struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data; + struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data; /* Actually, it's 0, but it's ignored at the moment. */ mr->rangesize = 1; @@ -53,11 +53,11 @@ static void NETMAP_init(struct xt_entry_target *t) static void NETMAP_parse(struct xt_option_call *cb) { - struct nf_nat_multi_range *mr = cb->data; - struct nf_nat_range *range = &mr->range[0]; + struct nf_nat_ipv4_multi_range_compat *mr = cb->data; + struct nf_nat_ipv4_range *range = &mr->range[0]; xtables_option_parse(cb); - range->flags |= IP_NAT_RANGE_MAP_IPS; + range->flags |= NF_NAT_RANGE_MAP_IPS; range->min_ip = cb->val.haddr.ip & cb->val.hmask.ip; range->max_ip = range->min_ip | ~cb->val.hmask.ip; } @@ -65,8 +65,8 @@ static void NETMAP_parse(struct xt_option_call *cb) static void NETMAP_print(const void *ip, const struct xt_entry_target *target, int numeric) { - const struct nf_nat_multi_range *mr = (const void *)target->data; - const struct nf_nat_range *r = &mr->range[0]; + const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data; + const struct nf_nat_ipv4_range *r = &mr->range[0]; struct in_addr a; int bits; @@ -90,8 +90,8 @@ static struct xtables_target netmap_tg_reg = { .name = MODULENAME, .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)), - .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), + .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), .help = NETMAP_help, .init = NETMAP_init, .x6_parse = NETMAP_parse, diff --git a/extensions/libipt_REDIRECT.c b/extensions/libipt_REDIRECT.c index e67360a0..610a9499 100644 --- a/extensions/libipt_REDIRECT.c +++ b/extensions/libipt_REDIRECT.c @@ -4,7 +4,7 @@ #include #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_PORTS = 0, @@ -30,7 +30,7 @@ static const struct xt_option_entry REDIRECT_opts[] = { static void REDIRECT_init(struct xt_entry_target *t) { - struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data; + struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data; /* Actually, it's 0, but it's ignored at the moment. */ mr->rangesize = 1; @@ -38,12 +38,12 @@ static void REDIRECT_init(struct xt_entry_target *t) /* Parses ports */ static void -parse_ports(const char *arg, struct nf_nat_multi_range *mr) +parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr) { char *end = ""; unsigned int port, maxport; - mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX) && (port = xtables_service_to_port(arg, NULL)) == (unsigned)-1) @@ -75,7 +75,7 @@ parse_ports(const char *arg, struct nf_nat_multi_range *mr) static void REDIRECT_parse(struct xt_option_call *cb) { const struct ipt_entry *entry = cb->xt_entry; - struct nf_nat_multi_range *mr = (void *)(*cb->target)->data; + struct nf_nat_ipv4_multi_range_compat *mr = (void *)(*cb->target)->data; int portok; if (entry->ip.proto == IPPROTO_TCP @@ -95,11 +95,11 @@ static void REDIRECT_parse(struct xt_option_call *cb) "Need TCP, UDP, SCTP or DCCP with port specification"); parse_ports(cb->arg, mr); if (cb->xflags & F_RANDOM) - mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; break; case O_RANDOM: if (cb->xflags & F_TO_PORTS) - mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; break; } } @@ -107,30 +107,30 @@ static void REDIRECT_parse(struct xt_option_call *cb) static void REDIRECT_print(const void *ip, const struct xt_entry_target *target, int numeric) { - const struct nf_nat_multi_range *mr = (const void *)target->data; - const struct nf_nat_range *r = &mr->range[0]; + const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data; + const struct nf_nat_ipv4_range *r = &mr->range[0]; - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(" redir ports "); printf("%hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) printf("-%hu", ntohs(r->max.tcp.port)); - if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (mr->range[0].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); } } static void REDIRECT_save(const void *ip, const struct xt_entry_target *target) { - const struct nf_nat_multi_range *mr = (const void *)target->data; - const struct nf_nat_range *r = &mr->range[0]; + const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data; + const struct nf_nat_ipv4_range *r = &mr->range[0]; - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(" --to-ports "); printf("%hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) printf("-%hu", ntohs(r->max.tcp.port)); - if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (mr->range[0].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); } } @@ -139,8 +139,8 @@ static struct xtables_target redirect_tg_reg = { .name = "REDIRECT", .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)), - .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), + .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), .help = REDIRECT_help, .init = REDIRECT_init, .x6_parse = REDIRECT_parse, diff --git a/extensions/libipt_SAME.c b/extensions/libipt_SAME.c index e603ef64..5d5bf630 100644 --- a/extensions/libipt_SAME.c +++ b/extensions/libipt_SAME.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include enum { @@ -37,7 +37,7 @@ static const struct xt_option_entry SAME_opts[] = { }; /* Parses range of IPs */ -static void parse_to(const char *orig_arg, struct nf_nat_range *range) +static void parse_to(const char *orig_arg, struct nf_nat_ipv4_range *range) { char *dash, *arg; const struct in_addr *ip; @@ -45,7 +45,7 @@ static void parse_to(const char *orig_arg, struct nf_nat_range *range) arg = strdup(orig_arg); if (arg == NULL) xtables_error(RESOURCE_PROBLEM, "strdup"); - range->flags |= IP_NAT_RANGE_MAP_IPS; + range->flags |= NF_NAT_RANGE_MAP_IPS; dash = strchr(arg, '-'); if (dash) @@ -74,6 +74,7 @@ static void parse_to(const char *orig_arg, struct nf_nat_range *range) static void SAME_parse(struct xt_option_call *cb) { struct ipt_same_info *mr = cb->data; + unsigned int count; xtables_option_parse(cb); switch (cb->entry->id) { @@ -89,6 +90,10 @@ static void SAME_parse(struct xt_option_call *cb) case O_NODST: mr->info |= IPT_SAME_NODST; break; + case O_RANDOM: + for (count=0; count < mr->rangesize; count++) + mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM; + break; } } @@ -100,7 +105,7 @@ static void SAME_fcheck(struct xt_fcheck_call *cb) if ((cb->xflags & f) == f) for (count = 0; count < mr->rangesize; ++count) - mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM; } static void SAME_print(const void *ip, const struct xt_entry_target *target, @@ -113,7 +118,7 @@ static void SAME_print(const void *ip, const struct xt_entry_target *target, printf(" same:"); for (count = 0; count < mr->rangesize; count++) { - const struct nf_nat_range *r = &mr->range[count]; + const struct nf_nat_ipv4_range *r = &mr->range[count]; struct in_addr a; a.s_addr = r->min_ip; @@ -123,7 +128,7 @@ static void SAME_print(const void *ip, const struct xt_entry_target *target, if (r->min_ip != r->max_ip) printf("-%s", xtables_ipaddr_to_numeric(&a)); - if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) random_selection = 1; } @@ -141,7 +146,7 @@ static void SAME_save(const void *ip, const struct xt_entry_target *target) int random_selection = 0; for (count = 0; count < mr->rangesize; count++) { - const struct nf_nat_range *r = &mr->range[count]; + const struct nf_nat_ipv4_range *r = &mr->range[count]; struct in_addr a; a.s_addr = r->min_ip; @@ -150,7 +155,7 @@ static void SAME_save(const void *ip, const struct xt_entry_target *target) if (r->min_ip != r->max_ip) printf("-%s", xtables_ipaddr_to_numeric(&a)); - if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) random_selection = 1; } diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c index c8cb26df..1a24f3d8 100644 --- a/extensions/libipt_SNAT.c +++ b/extensions/libipt_SNAT.c @@ -6,7 +6,7 @@ #include #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_SRC = 0, @@ -23,7 +23,7 @@ enum { struct ipt_natinfo { struct xt_entry_target t; - struct nf_nat_multi_range mr; + struct nf_nat_ipv4_multi_range_compat mr; }; static void SNAT_help(void) @@ -44,7 +44,7 @@ static const struct xt_option_entry SNAT_opts[] = { }; static struct ipt_natinfo * -append_range(struct ipt_natinfo *info, const struct nf_nat_range *range) +append_range(struct ipt_natinfo *info, const struct nf_nat_ipv4_range *range) { unsigned int size; @@ -66,7 +66,7 @@ append_range(struct ipt_natinfo *info, const struct nf_nat_range *range) static struct xt_entry_target * parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) { - struct nf_nat_range range; + struct nf_nat_ipv4_range range; char *arg, *colon, *dash, *error; const struct in_addr *ip; @@ -83,7 +83,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) xtables_error(PARAMETER_PROBLEM, "Need TCP, UDP, SCTP or DCCP with port specification"); - range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; port = atoi(colon+1); if (port <= 0 || port > 65535) @@ -122,7 +122,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) *colon = '\0'; } - range.flags |= IP_NAT_RANGE_MAP_IPS; + range.flags |= NF_NAT_RANGE_MAP_IPS; dash = strchr(arg, '-'); if (colon && dash && dash > colon) dash = NULL; @@ -177,7 +177,7 @@ static void SNAT_parse(struct xt_option_call *cb) cb->xflags |= F_X_TO_SRC; break; case O_PERSISTENT: - info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT; + info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT; break; } } @@ -185,15 +185,15 @@ static void SNAT_parse(struct xt_option_call *cb) static void SNAT_fcheck(struct xt_fcheck_call *cb) { static const unsigned int f = F_TO_SRC | F_RANDOM; - struct nf_nat_multi_range *mr = cb->data; + struct nf_nat_ipv4_multi_range_compat *mr = cb->data; if ((cb->xflags & f) == f) - mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; } -static void print_range(const struct nf_nat_range *r) +static void print_range(const struct nf_nat_ipv4_range *r) { - if (r->flags & IP_NAT_RANGE_MAP_IPS) { + if (r->flags & NF_NAT_RANGE_MAP_IPS) { struct in_addr a; a.s_addr = r->min_ip; @@ -203,7 +203,7 @@ static void print_range(const struct nf_nat_range *r) printf("-%s", xtables_ipaddr_to_numeric(&a)); } } - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(":"); printf("%hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) @@ -220,9 +220,9 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target, printf(" to:"); for (i = 0; i < info->mr.rangesize; i++) { print_range(&info->mr.range[i]); - if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); - if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT) + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" persistent"); } } @@ -235,9 +235,9 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target) for (i = 0; i < info->mr.rangesize; i++) { printf(" --to-source "); print_range(&info->mr.range[i]); - if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); - if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT) + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" --persistent"); } } @@ -246,8 +246,8 @@ static struct xtables_target snat_tg_reg = { .name = "SNAT", .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)), - .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), + .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), .help = SNAT_help, .x6_parse = SNAT_parse, .x6_fcheck = SNAT_fcheck, -- cgit v1.2.3 From 0e37f00980eb6b4fc2c5f979cc5fa83c0fff9d30 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:10 +0200 Subject: extensions: add IPv6 MASQUERADE extension Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_MASQUERADE.c | 150 ++++++++++++++++++++++++++++++++++++++ extensions/libip6t_MASQUERADE.man | 30 ++++++++ 2 files changed, 180 insertions(+) create mode 100644 extensions/libip6t_MASQUERADE.c create mode 100644 extensions/libip6t_MASQUERADE.man (limited to 'extensions') diff --git a/extensions/libip6t_MASQUERADE.c b/extensions/libip6t_MASQUERADE.c new file mode 100644 index 00000000..eb9213ef --- /dev/null +++ b/extensions/libip6t_MASQUERADE.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 MASQUERADE target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +enum { + O_TO_PORTS = 0, + O_RANDOM, +}; + +static void MASQUERADE_help(void) +{ + printf( +"MASQUERADE target options:\n" +" --to-ports [-]\n" +" Port (range) to map to.\n" +" --random\n" +" Randomize source port.\n"); +} + +static const struct xt_option_entry MASQUERADE_opts[] = { + {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING}, + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, +}; + +/* Parses ports */ +static void +parse_ports(const char *arg, struct nf_nat_range *r) +{ + char *end; + unsigned int port, maxport; + + r->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; + + if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX)) + xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg); + + switch (*end) { + case '\0': + r->min_proto.tcp.port + = r->max_proto.tcp.port + = htons(port); + return; + case '-': + if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX)) + break; + + if (maxport < port) + break; + + r->min_proto.tcp.port = htons(port); + r->max_proto.tcp.port = htons(maxport); + return; + default: + break; + } + xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg); +} + +static void MASQUERADE_parse(struct xt_option_call *cb) +{ + const struct ip6t_entry *entry = cb->xt_entry; + struct nf_nat_range *r = cb->data; + int portok; + + if (entry->ipv6.proto == IPPROTO_TCP || + entry->ipv6.proto == IPPROTO_UDP || + entry->ipv6.proto == IPPROTO_SCTP || + entry->ipv6.proto == IPPROTO_DCCP || + entry->ipv6.proto == IPPROTO_ICMP) + portok = 1; + else + portok = 0; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_TO_PORTS: + if (!portok) + xtables_error(PARAMETER_PROBLEM, + "Need TCP, UDP, SCTP or DCCP with port specification"); + parse_ports(cb->arg, r); + break; + case O_RANDOM: + r->flags |= NF_NAT_RANGE_PROTO_RANDOM; + break; + } +} + +static void +MASQUERADE_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct nf_nat_range *r = (const void *)target->data; + + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(" masq ports: "); + printf("%hu", ntohs(r->min_proto.tcp.port)); + if (r->max_proto.tcp.port != r->min_proto.tcp.port) + printf("-%hu", ntohs(r->max_proto.tcp.port)); + } + + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" random"); +} + +static void +MASQUERADE_save(const void *ip, const struct xt_entry_target *target) +{ + const struct nf_nat_range *r = (const void *)target->data; + + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(" --to-ports %hu", ntohs(r->min_proto.tcp.port)); + if (r->max_proto.tcp.port != r->min_proto.tcp.port) + printf("-%hu", ntohs(r->max_proto.tcp.port)); + } + + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" --random"); +} + +static struct xtables_target masquerade_tg_reg = { + .name = "MASQUERADE", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct nf_nat_range)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)), + .help = MASQUERADE_help, + .x6_parse = MASQUERADE_parse, + .print = MASQUERADE_print, + .save = MASQUERADE_save, + .x6_options = MASQUERADE_opts, +}; + +void _init(void) +{ + xtables_register_target(&masquerade_tg_reg); +} diff --git a/extensions/libip6t_MASQUERADE.man b/extensions/libip6t_MASQUERADE.man new file mode 100644 index 00000000..c63d826b --- /dev/null +++ b/extensions/libip6t_MASQUERADE.man @@ -0,0 +1,30 @@ +This target is only valid in the +.B nat +table, in the +.B POSTROUTING +chain. It should only be used with dynamically assigned IPv6 (dialup) +connections: if you have a static IP address, you should use the SNAT +target. Masquerading is equivalent to specifying a mapping to the IP +address of the interface the packet is going out, but also has the +effect that connections are +.I forgotten +when the interface goes down. This is the correct behavior when the +next dialup is unlikely to have the same interface address (and hence +any established connections are lost anyway). +.TP +\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP] +This specifies a range of source ports to use, overriding the default +.B SNAT +source port-selection heuristics (see above). This is only valid +if the rule also specifies +\fB\-p tcp\fP +or +\fB\-p udp\fP. +.TP +\fB\-\-random\fP +Randomize source port mapping +If option +\fB\-\-random\fP +is used then port mapping will be randomized. +.RS +.PP -- cgit v1.2.3 From 3672111649732be657cb7566178b7d2618ba6ec5 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:11 +0200 Subject: extensions: add IPv6 SNAT extension Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_SNAT.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 extensions/libip6t_SNAT.c (limited to 'extensions') diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c new file mode 100644 index 00000000..307be70e --- /dev/null +++ b/extensions/libip6t_SNAT.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 SNAT target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +enum { + O_TO_SRC = 0, + O_RANDOM, + O_PERSISTENT, + O_X_TO_SRC, + F_TO_SRC = 1 << O_TO_SRC, + F_RANDOM = 1 << O_RANDOM, + F_X_TO_SRC = 1 << O_X_TO_SRC, +}; + +static void SNAT_help(void) +{ + printf( +"SNAT target options:\n" +" --to-source [[-]][:port[-port]]\n" +" Address to map source to.\n" +"[--random] [--persistent]\n"); +} + +static const struct xt_option_entry SNAT_opts[] = { + {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_MULTI}, + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, +}; + +/* Ranges expected in network order. */ +static void +parse_to(const char *orig_arg, int portok, struct nf_nat_range *range) +{ + char *arg, *start, *end = NULL, *colon = NULL, *dash, *error; + const struct in6_addr *ip; + + arg = strdup(orig_arg); + if (arg == NULL) + xtables_error(RESOURCE_PROBLEM, "strdup"); + + start = strchr(arg, '['); + if (start == NULL) + start = arg; + else { + start++; + end = strchr(start, ']'); + if (end == NULL) + xtables_error(PARAMETER_PROBLEM, + "Invalid address format"); + + *end = '\0'; + colon = strchr(end + 1, ':'); + } + + if (colon) { + int port; + + if (!portok) + xtables_error(PARAMETER_PROBLEM, + "Need TCP, UDP, SCTP or DCCP with port specification"); + + range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; + + port = atoi(colon+1); + if (port <= 0 || port > 65535) + xtables_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", colon+1); + + error = strchr(colon+1, ':'); + if (error) + xtables_error(PARAMETER_PROBLEM, + "Invalid port:port syntax - use dash\n"); + + dash = strchr(colon, '-'); + if (!dash) { + range->min_proto.tcp.port + = range->max_proto.tcp.port + = htons(port); + } else { + int maxport; + + maxport = atoi(dash + 1); + if (maxport <= 0 || maxport > 65535) + xtables_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", dash+1); + if (maxport < port) + /* People are stupid. */ + xtables_error(PARAMETER_PROBLEM, + "Port range `%s' funky\n", colon+1); + range->min_proto.tcp.port = htons(port); + range->max_proto.tcp.port = htons(maxport); + } + /* Starts with a colon? No IP info...*/ + if (colon == arg) { + free(arg); + return; + } + *colon = '\0'; + } + + range->flags |= NF_NAT_RANGE_MAP_IPS; + dash = strchr(start, '-'); + if (colon && dash && dash > colon) + dash = NULL; + + if (dash) + *dash = '\0'; + + ip = xtables_numeric_to_ip6addr(start); + if (!ip) + xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", + start); + range->min_addr.in6 = *ip; + if (dash) { + ip = xtables_numeric_to_ip6addr(dash + 1); + if (!ip) + xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", + dash+1); + range->max_addr.in6 = *ip; + } else + range->max_addr = range->min_addr; + + free(arg); + return; +} + +static void SNAT_parse(struct xt_option_call *cb) +{ + const struct ip6t_entry *entry = cb->xt_entry; + struct nf_nat_range *range = cb->data; + int portok; + + if (entry->ipv6.proto == IPPROTO_TCP || + entry->ipv6.proto == IPPROTO_UDP || + entry->ipv6.proto == IPPROTO_SCTP || + entry->ipv6.proto == IPPROTO_DCCP || + entry->ipv6.proto == IPPROTO_ICMP) + portok = 1; + else + portok = 0; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_TO_SRC: + if (cb->xflags & F_X_TO_SRC) { + if (!kernel_version) + get_kernel_version(); + if (kernel_version > LINUX_VERSION(2, 6, 10)) + xtables_error(PARAMETER_PROBLEM, + "SNAT: Multiple --to-source not supported"); + } + parse_to(cb->arg, portok, range); + break; + case O_PERSISTENT: + range->flags |= NF_NAT_RANGE_PERSISTENT; + break; + } +} + +static void SNAT_fcheck(struct xt_fcheck_call *cb) +{ + static const unsigned int f = F_TO_SRC | F_RANDOM; + struct nf_nat_range *range = cb->data; + + if ((cb->xflags & f) == f) + range->flags |= NF_NAT_RANGE_PROTO_RANDOM; +} + +static void print_range(const struct nf_nat_range *range) +{ + if (range->flags & NF_NAT_RANGE_MAP_IPS) { + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) + printf("["); + printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6)); + if (memcmp(&range->min_addr, &range->max_addr, + sizeof(range->min_addr))) + printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6)); + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) + printf("]"); + } + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(":"); + printf("%hu", ntohs(range->min_proto.tcp.port)); + if (range->max_proto.tcp.port != range->min_proto.tcp.port) + printf("-%hu", ntohs(range->max_proto.tcp.port)); + } +} + +static void SNAT_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct nf_nat_range *range = (const void *)target->data; + + printf(" to:"); + print_range(range); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" random"); + if (range->flags & NF_NAT_RANGE_PERSISTENT) + printf(" persistent"); +} + +static void SNAT_save(const void *ip, const struct xt_entry_target *target) +{ + const struct nf_nat_range *range = (const void *)target->data; + + printf(" --to-source "); + print_range(range); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" --random"); + if (range->flags & NF_NAT_RANGE_PERSISTENT) + printf(" --persistent"); +} + +static struct xtables_target snat_tg_reg = { + .name = "SNAT", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .revision = 1, + .size = XT_ALIGN(sizeof(struct nf_nat_range)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)), + .help = SNAT_help, + .x6_parse = SNAT_parse, + .x6_fcheck = SNAT_fcheck, + .print = SNAT_print, + .save = SNAT_save, + .x6_options = SNAT_opts, +}; + +void _init(void) +{ + xtables_register_target(&snat_tg_reg); +} -- cgit v1.2.3 From 9caf63581907860a1a0acee970b9f50d41b6a8ba Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:12 +0200 Subject: extensions: add IPv6 DNAT target Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_DNAT.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 extensions/libip6t_DNAT.c (limited to 'extensions') diff --git a/extensions/libip6t_DNAT.c b/extensions/libip6t_DNAT.c new file mode 100644 index 00000000..a5969c36 --- /dev/null +++ b/extensions/libip6t_DNAT.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 DNAT target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +enum { + O_TO_DEST = 0, + O_RANDOM, + O_PERSISTENT, + O_X_TO_DEST, + F_TO_DEST = 1 << O_TO_DEST, + F_RANDOM = 1 << O_RANDOM, + F_X_TO_DEST = 1 << O_X_TO_DEST, +}; + +static void DNAT_help(void) +{ + printf( +"DNAT target options:\n" +" --to-dest [[-]][:port[-port]]\n" +" Address to map source to.\n" +"[--random] [--persistent]\n"); +} + +static const struct xt_option_entry DNAT_opts[] = { + {.name = "to-dest", .id = O_TO_DEST, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_MULTI}, + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, +}; + +/* Ranges expected in network order. */ +static void +parse_to(const char *orig_arg, int portok, struct nf_nat_range *range) +{ + char *arg, *start, *end = NULL, *colon = NULL, *dash, *error; + const struct in6_addr *ip; + + arg = strdup(orig_arg); + if (arg == NULL) + xtables_error(RESOURCE_PROBLEM, "strdup"); + + start = strchr(arg, '['); + if (start == NULL) + start = arg; + else { + start++; + end = strchr(start, ']'); + if (end == NULL) + xtables_error(PARAMETER_PROBLEM, + "Invalid address format"); + + *end = '\0'; + colon = strchr(end + 1, ':'); + } + + if (colon) { + int port; + + if (!portok) + xtables_error(PARAMETER_PROBLEM, + "Need TCP, UDP, SCTP or DCCP with port specification"); + + range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; + + port = atoi(colon+1); + if (port <= 0 || port > 65535) + xtables_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", colon+1); + + error = strchr(colon+1, ':'); + if (error) + xtables_error(PARAMETER_PROBLEM, + "Invalid port:port syntax - use dash\n"); + + dash = strchr(colon, '-'); + if (!dash) { + range->min_proto.tcp.port + = range->max_proto.tcp.port + = htons(port); + } else { + int maxport; + + maxport = atoi(dash + 1); + if (maxport <= 0 || maxport > 65535) + xtables_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", dash+1); + if (maxport < port) + /* People are stupid. */ + xtables_error(PARAMETER_PROBLEM, + "Port range `%s' funky\n", colon+1); + range->min_proto.tcp.port = htons(port); + range->max_proto.tcp.port = htons(maxport); + } + /* Starts with a colon? No IP info...*/ + if (colon == arg) { + free(arg); + return; + } + *colon = '\0'; + } + + range->flags |= NF_NAT_RANGE_MAP_IPS; + dash = strchr(start, '-'); + if (colon && dash && dash > colon) + dash = NULL; + + if (dash) + *dash = '\0'; + + ip = xtables_numeric_to_ip6addr(start); + if (!ip) + xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", + start); + range->min_addr.in6 = *ip; + if (dash) { + ip = xtables_numeric_to_ip6addr(dash + 1); + if (!ip) + xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", + dash+1); + range->max_addr.in6 = *ip; + } else + range->max_addr = range->min_addr; + + free(arg); + return; +} + +static void DNAT_parse(struct xt_option_call *cb) +{ + const struct ip6t_entry *entry = cb->xt_entry; + struct nf_nat_range *range = cb->data; + int portok; + + if (entry->ipv6.proto == IPPROTO_TCP || + entry->ipv6.proto == IPPROTO_UDP || + entry->ipv6.proto == IPPROTO_SCTP || + entry->ipv6.proto == IPPROTO_DCCP || + entry->ipv6.proto == IPPROTO_ICMP) + portok = 1; + else + portok = 0; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_TO_DEST: + if (cb->xflags & F_X_TO_DEST) { + if (!kernel_version) + get_kernel_version(); + if (kernel_version > LINUX_VERSION(2, 6, 10)) + xtables_error(PARAMETER_PROBLEM, + "DNAT: Multiple --to-source not supported"); + } + parse_to(cb->arg, portok, range); + break; + case O_PERSISTENT: + range->flags |= NF_NAT_RANGE_PERSISTENT; + break; + } +} + +static void DNAT_fcheck(struct xt_fcheck_call *cb) +{ + static const unsigned int f = F_TO_DEST | F_RANDOM; + struct nf_nat_range *mr = cb->data; + + if ((cb->xflags & f) == f) + mr->flags |= NF_NAT_RANGE_PROTO_RANDOM; +} + +static void print_range(const struct nf_nat_range *range) +{ + if (range->flags & NF_NAT_RANGE_MAP_IPS) { + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) + printf("["); + printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6)); + if (memcmp(&range->min_addr, &range->max_addr, + sizeof(range->min_addr))) + printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6)); + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) + printf("]"); + } + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(":"); + printf("%hu", ntohs(range->min_proto.tcp.port)); + if (range->max_proto.tcp.port != range->min_proto.tcp.port) + printf("-%hu", ntohs(range->max_proto.tcp.port)); + } +} + +static void DNAT_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct nf_nat_range *range = (const void *)target->data; + + printf(" to:"); + print_range(range); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" random"); + if (range->flags & NF_NAT_RANGE_PERSISTENT) + printf(" persistent"); +} + +static void DNAT_save(const void *ip, const struct xt_entry_target *target) +{ + const struct nf_nat_range *range = (const void *)target->data; + + printf(" --to-source "); + print_range(range); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" --random"); + if (range->flags & NF_NAT_RANGE_PERSISTENT) + printf(" --persistent"); +} + +static struct xtables_target snat_tg_reg = { + .name = "DNAT", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .revision = 1, + .size = XT_ALIGN(sizeof(struct nf_nat_range)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)), + .help = DNAT_help, + .x6_parse = DNAT_parse, + .x6_fcheck = DNAT_fcheck, + .print = DNAT_print, + .save = DNAT_save, + .x6_options = DNAT_opts, +}; + +void _init(void) +{ + xtables_register_target(&snat_tg_reg); +} -- cgit v1.2.3 From 5eca41982d29bc25b241692d03b09b953e7a908a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:14 +0200 Subject: extensions: add IPv6 REDIRECT extension Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_REDIRECT.c | 151 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 extensions/libip6t_REDIRECT.c (limited to 'extensions') diff --git a/extensions/libip6t_REDIRECT.c b/extensions/libip6t_REDIRECT.c new file mode 100644 index 00000000..1724aa67 --- /dev/null +++ b/extensions/libip6t_REDIRECT.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +enum { + O_TO_PORTS = 0, + O_RANDOM, + F_TO_PORTS = 1 << O_TO_PORTS, + F_RANDOM = 1 << O_RANDOM, +}; + +static void REDIRECT_help(void) +{ + printf( +"REDIRECT target options:\n" +" --to-ports [-]\n" +" Port (range) to map to.\n" +" [--random]\n"); +} + +static const struct xt_option_entry REDIRECT_opts[] = { + {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING}, + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, +}; + +/* Parses ports */ +static void +parse_ports(const char *arg, struct nf_nat_range *range) +{ + char *end = ""; + unsigned int port, maxport; + + range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; + + if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX) && + (port = xtables_service_to_port(arg, NULL)) == (unsigned)-1) + xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg); + + switch (*end) { + case '\0': + range->min_proto.tcp.port + = range->max_proto.tcp.port + = htons(port); + return; + case '-': + if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX) && + (maxport = xtables_service_to_port(end + 1, NULL)) == (unsigned)-1) + break; + + if (maxport < port) + break; + + range->min_proto.tcp.port = htons(port); + range->max_proto.tcp.port = htons(maxport); + return; + default: + break; + } + xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg); +} + +static void REDIRECT_parse(struct xt_option_call *cb) +{ + const struct ip6t_entry *entry = cb->xt_entry; + struct nf_nat_range *range = (void *)(*cb->target)->data; + int portok; + + if (entry->ipv6.proto == IPPROTO_TCP + || entry->ipv6.proto == IPPROTO_UDP + || entry->ipv6.proto == IPPROTO_SCTP + || entry->ipv6.proto == IPPROTO_DCCP + || entry->ipv6.proto == IPPROTO_ICMP) + portok = 1; + else + portok = 0; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_TO_PORTS: + if (!portok) + xtables_error(PARAMETER_PROBLEM, + "Need TCP, UDP, SCTP or DCCP with port specification"); + parse_ports(cb->arg, range); + if (cb->xflags & F_RANDOM) + range->flags |= NF_NAT_RANGE_PROTO_RANDOM; + break; + case O_RANDOM: + if (cb->xflags & F_TO_PORTS) + range->flags |= NF_NAT_RANGE_PROTO_RANDOM; + break; + } +} + +static void REDIRECT_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct nf_nat_range *range = (const void *)target->data; + + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(" redir ports "); + printf("%hu", ntohs(range->min_proto.tcp.port)); + if (range->max_proto.tcp.port != range->min_proto.tcp.port) + printf("-%hu", ntohs(range->max_proto.tcp.port)); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" random"); + } +} + +static void REDIRECT_save(const void *ip, const struct xt_entry_target *target) +{ + const struct nf_nat_range *range = (const void *)target->data; + + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(" --to-ports "); + printf("%hu", ntohs(range->min_proto.tcp.port)); + if (range->max_proto.tcp.port != range->min_proto.tcp.port) + printf("-%hu", ntohs(range->max_proto.tcp.port)); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" --random"); + } +} + +static struct xtables_target redirect_tg_reg = { + .name = "REDIRECT", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct nf_nat_range)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)), + .help = REDIRECT_help, + .x6_parse = REDIRECT_parse, + .print = REDIRECT_print, + .save = REDIRECT_save, + .x6_options = REDIRECT_opts, +}; + +void _init(void) +{ + xtables_register_target(&redirect_tg_reg); +} -- cgit v1.2.3 From 5f896fd9432d2c16d17550b943f4b9a782bffe04 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:16 +0200 Subject: extensions: add IPv6 NETMAP extension Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/GNUmakefile.in | 2 +- extensions/libip6t_NETMAP.c | 93 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 extensions/libip6t_NETMAP.c (limited to 'extensions') diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 218dc3ad..2492d184 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -97,10 +97,10 @@ lib%.oo: ${srcdir}/lib%.c ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD +ip6t_NETMAP_LIBADD = -lip6tc xt_RATEEST_LIBADD = -lm xt_statistic_LIBADD = -lm - # # Static bits # diff --git a/extensions/libip6t_NETMAP.c b/extensions/libip6t_NETMAP.c new file mode 100644 index 00000000..d14dece3 --- /dev/null +++ b/extensions/libip6t_NETMAP.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULENAME "NETMAP" + +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) +{ + printf(MODULENAME" target options:\n" + " --%s address[/mask]\n" + " Network address to map to.\n\n", + NETMAP_opts[0].name); +} + +static void NETMAP_parse(struct xt_option_call *cb) +{ + struct nf_nat_range *range = cb->data; + unsigned int i; + + xtables_option_parse(cb); + range->flags |= NF_NAT_RANGE_MAP_IPS; + for (i = 0; i < 4; i++) { + range->min_addr.ip6[i] = cb->val.haddr.ip6[i] & + cb->val.hmask.ip6[i]; + range->max_addr.ip6[i] = range->min_addr.ip6[i] | + ~cb->val.hmask.ip6[i]; + } +} + +static void NETMAP_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct nf_nat_range *r = (const void *)target->data; + struct in6_addr a; + unsigned int i; + int bits; + + a = r->min_addr.in6; + printf("%s", xtables_ip6addr_to_numeric(&a)); + for (i = 0; i < 4; i++) + a.s6_addr32[i] = ~(r->min_addr.ip6[i] ^ r->max_addr.ip6[i]); + bits = ipv6_prefix_length(&a); + if (bits < 0) + printf("/%s", xtables_ip6addr_to_numeric(&a)); + else + printf("/%d", bits); +} + +static void NETMAP_save(const void *ip, const struct xt_entry_target *target) +{ + printf(" --%s ", NETMAP_opts[0].name); + NETMAP_print(ip, target, 0); +} + +static struct xtables_target netmap_tg_reg = { + .name = MODULENAME, + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct nf_nat_range)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)), + .help = NETMAP_help, + .x6_parse = NETMAP_parse, + .print = NETMAP_print, + .save = NETMAP_save, + .x6_options = NETMAP_opts, +}; + +void _init(void) +{ + xtables_register_target(&netmap_tg_reg); +} -- cgit v1.2.3 From 1871796877956ee68a39092c6fc3678e5a9d1d88 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:17 +0200 Subject: extensions: add NPT extension Add extensions for the SNPT and DNPT stateless IPv6-to-IPv6 Network Prefix Translation targets. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_DNPT.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ extensions/libip6t_SNPT.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 extensions/libip6t_DNPT.c create mode 100644 extensions/libip6t_SNPT.c (limited to 'extensions') diff --git a/extensions/libip6t_DNPT.c b/extensions/libip6t_DNPT.c new file mode 100644 index 00000000..9e4dc5cf --- /dev/null +++ b/extensions/libip6t_DNPT.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +enum { + O_SRC_PFX = 1 << 0, + O_DST_PFX = 1 << 1, +}; + +static const struct xt_option_entry SNPT_options[] = { + { .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_MAND }, + { .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_MAND }, + { } +}; + +static void SNPT_help(void) +{ + printf("SNPT target options:" + "\n" + " --src-pfx prefix/length\n" + " --dst-pfx prefix/length\n" + "\n"); +} + +static void SNPT_parse(struct xt_option_call *cb) +{ + struct ip6t_npt_tginfo *npt = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SRC_PFX: + npt->src_pfx = cb->val.haddr; + npt->src_pfx_len = cb->val.hlen; + break; + case O_DST_PFX: + npt->dst_pfx = cb->val.haddr; + npt->dst_pfx_len = cb->val.hlen; + break; + } +} + +static void SNPT_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct ip6t_npt_tginfo *npt = (const void *)target->data; + + printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6), + npt->src_pfx_len); + printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6), + npt->dst_pfx_len); +} + +static struct xtables_target snpt_tg_reg = { + .name = "DNPT", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)), + .userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment), + .help = SNPT_help, + .x6_parse = SNPT_parse, + .print = SNPT_print, + .x6_options = SNPT_options, +}; + +void _init(void) +{ + xtables_register_target(&snpt_tg_reg); +} diff --git a/extensions/libip6t_SNPT.c b/extensions/libip6t_SNPT.c new file mode 100644 index 00000000..26a86c56 --- /dev/null +++ b/extensions/libip6t_SNPT.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +enum { + O_SRC_PFX = 1 << 0, + O_DST_PFX = 1 << 1, +}; + +static const struct xt_option_entry SNPT_options[] = { + { .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_MAND }, + { .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_MAND }, + { } +}; + +static void SNPT_help(void) +{ + printf("SNPT target options:" + "\n" + " --src-pfx prefix/length\n" + " --dst-pfx prefix/length\n" + "\n"); +} + +static void SNPT_parse(struct xt_option_call *cb) +{ + struct ip6t_npt_tginfo *npt = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SRC_PFX: + npt->src_pfx = cb->val.haddr; + npt->src_pfx_len = cb->val.hlen; + break; + case O_DST_PFX: + npt->dst_pfx = cb->val.haddr; + npt->dst_pfx_len = cb->val.hlen; + break; + } +} + +static void SNPT_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct ip6t_npt_tginfo *npt = (const void *)target->data; + + printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6), + npt->src_pfx_len); + printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6), + npt->dst_pfx_len); +} + +static struct xtables_target snpt_tg_reg = { + .name = "SNPT", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)), + .userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment), + .help = SNPT_help, + .x6_parse = SNPT_parse, + .print = SNPT_print, + .x6_options = SNPT_options, +}; + +void _init(void) +{ + xtables_register_target(&snpt_tg_reg); +} -- cgit v1.2.3 From 8d8896a3833292d091ee5a028f3461083bb956bd Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 17 Sep 2012 00:23:08 +0000 Subject: libxt_time: add support to ignore day transition Currently, if you want to do something like: "match Monday, starting 23:00, for two hours" You need two rules, one for Mon 23:00 to 0:00 and one for Tue 0:00-1:00. The rule --weekdays Mo --timestart 23:00 --timestop 01:00 looks correct, but it will first match on monday from midnight to 1 a.m. and then again for another hour from 23:00 onwards. This permits userspace to explicitly ignore the day transition and match for a single, continuous time period instead. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_time.c | 20 ++++++++++++++++++++ extensions/libxt_time.man | 12 ++++++++++++ 2 files changed, 32 insertions(+) (limited to 'extensions') diff --git a/extensions/libxt_time.c b/extensions/libxt_time.c index 44c05b8f..9c5bda88 100644 --- a/extensions/libxt_time.c +++ b/extensions/libxt_time.c @@ -22,6 +22,7 @@ enum { O_DATE_STOP, O_TIME_START, O_TIME_STOP, + O_TIME_CONTIGUOUS, O_MONTHDAYS, O_WEEKDAYS, O_LOCAL_TZ, @@ -30,6 +31,7 @@ enum { F_LOCAL_TZ = 1 << O_LOCAL_TZ, F_UTC = 1 << O_UTC, F_KERNEL_TZ = 1 << O_KERNEL_TZ, + F_TIME_CONTIGUOUS = 1 << O_TIME_CONTIGUOUS, }; static const char *const week_days[] = { @@ -41,6 +43,7 @@ static const struct xt_option_entry time_opts[] = { {.name = "datestop", .id = O_DATE_STOP, .type = XTTYPE_STRING}, {.name = "timestart", .id = O_TIME_START, .type = XTTYPE_STRING}, {.name = "timestop", .id = O_TIME_STOP, .type = XTTYPE_STRING}, + {.name = "contiguous", .id = O_TIME_CONTIGUOUS, .type = XTTYPE_NONE}, {.name = "weekdays", .id = O_WEEKDAYS, .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, {.name = "monthdays", .id = O_MONTHDAYS, .type = XTTYPE_STRING, @@ -273,6 +276,9 @@ static void time_parse(struct xt_option_call *cb) case O_TIME_STOP: info->daytime_stop = time_parse_minutes(cb->arg); break; + case O_TIME_CONTIGUOUS: + info->flags |= XT_TIME_CONTIGUOUS; + break; case O_LOCAL_TZ: fprintf(stderr, "WARNING: --localtz is being replaced by " "--kerneltz, since \"local\" is ambiguous. Note the " @@ -403,6 +409,8 @@ static void time_print(const void *ip, const struct xt_entry_match *match, } if (!(info->flags & XT_TIME_LOCAL_TZ)) printf(" UTC"); + if (info->flags & XT_TIME_CONTIGUOUS) + printf(" contiguous"); } static void time_save(const void *ip, const struct xt_entry_match *match) @@ -429,6 +437,17 @@ static void time_save(const void *ip, const struct xt_entry_match *match) time_print_date(info->date_stop, "--datestop"); if (info->flags & XT_TIME_LOCAL_TZ) printf(" --kerneltz"); + if (info->flags & XT_TIME_CONTIGUOUS) + printf(" --contiguous"); +} + +static void time_check(struct xt_fcheck_call *cb) +{ + const struct xt_time_info *info = (const void *) cb->data; + if ((cb->xflags & F_TIME_CONTIGUOUS) && + info->daytime_start < info->daytime_stop) + xtables_error(PARAMETER_PROBLEM, + "time: --contiguous only makes sense when stoptime is smaller than starttime"); } static struct xtables_match time_match = { @@ -442,6 +461,7 @@ static struct xtables_match time_match = { .print = time_print, .save = time_save, .x6_parse = time_parse, + .x6_fcheck = time_check, .x6_options = time_opts, }; diff --git a/extensions/libxt_time.man b/extensions/libxt_time.man index 1d677b94..4c0cae06 100644 --- a/extensions/libxt_time.man +++ b/extensions/libxt_time.man @@ -30,6 +30,10 @@ Only match on the given weekdays. Possible values are \fBMon\fP, \fBTue\fP, to \fB7\fP, respectively. You may also use two-character variants (\fBMo\fP, \fBTu\fP, etc.). .TP +\fB\-\-contiguous\fP +When \fB\-\-timestop\fP is smaller than \fB\-\-timestart\fP value, match +this as a single time period instead distinct intervals. See EXAMPLES. +.TP \fB\-\-kerneltz\fP Use the kernel timezone instead of UTC to determine whether a packet meets the time regulations. @@ -84,3 +88,11 @@ The fourth Friday in the month: (Note that this exploits a certain mathematical property. It is not possible to say "fourth Thursday OR fourth Friday" in one rule. It is possible with multiple rules, though.) +.PP +Matching across days might not do what is expected. For instance, +.IP +\-m time \-\-weekdays Mo \-\-timestart 23:00 \-\-timestop 01:00 +Will match Monday, for one hour from midnight to 1 a.m., and then +again for another hour from 23:00 onwards. If this is unwanted, e.g. if you +would like 'match for two hours from Montay 23:00 onwards' you need to also specify +the \-\-contiguous option in the example above. -- cgit v1.2.3