From 18b5628da718a56fed9628763669da36b5225aa2 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=yasuyuki/emailAddress=yasuyuki@netfilter.org" Date: Fri, 20 Oct 2006 12:24:34 +0000 Subject: - Add revision support to ip6tables. - Add support port range match to libip6t_multiport (R?mi Denis-Courmont ) --- extensions/libip6t_multiport.c | 201 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 1 deletion(-) (limited to 'extensions') diff --git a/extensions/libip6t_multiport.c b/extensions/libip6t_multiport.c index ed5fffe..166abce 100644 --- a/extensions/libip6t_multiport.c +++ b/extensions/libip6t_multiport.c @@ -5,7 +5,8 @@ #include #include #include -#include +/* To ensure that iptables compiles with an old kernel */ +#include "../include/linux/netfilter_ipv6/ip6t_multiport.h" /* Function which prints out usage message. */ static void @@ -20,6 +21,23 @@ help(void) " --dports ...\n" " match destination port(s)\n" " --ports port[,port,port]\n" +" match both source and destination port(s)\n" +" NOTE: this kernel does not support port ranges in multiport.\n", +IPTABLES_VERSION); +} + +static void +help_v1(void) +{ + printf( +"multiport v%s options:\n" +" --source-ports [!] port[,port:port,port...]\n" +" --sports ...\n" +" match source port(s)\n" +" --destination-ports [!] port[,port:port,port...]\n" +" --dports ...\n" +" match destination port(s)\n" +" --ports [!] port[,port:port,port]\n" " match both source and destination port(s)\n", IPTABLES_VERSION); } @@ -70,6 +88,46 @@ parse_multi_ports(const char *portstring, u_int16_t *ports, const char *proto) return i; } +static void +parse_multi_ports_v1(const char *portstring, + struct ip6t_multiport_v1 *multiinfo, + const char *proto) +{ + char *buffer, *cp, *next, *range; + unsigned int i; + u_int16_t m; + + buffer = strdup(portstring); + if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed"); + + for (i=0; ipflags[i] = 0; + + for (cp=buffer, i=0; cp && iports[i] = parse_port(cp, proto); + if (range) { + multiinfo->pflags[i] = 1; + multiinfo->ports[++i] = parse_port(range, proto); + if (multiinfo->ports[i-1] >= multiinfo->ports[i]) + exit_error(PARAMETER_PROBLEM, + "invalid portrange specified"); + m <<= 1; + } + } + multiinfo->count = i; + if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified"); + free(buffer); +} + /* Initialize the match. */ static void init(struct ip6t_entry_match *m, unsigned int *nfcache) @@ -143,6 +201,52 @@ parse(int c, char **argv, int invert, unsigned int *flags, return 1; } +static int +parse_v1(int c, char **argv, int invert, unsigned int *flags, + const struct ip6t_entry *entry, + unsigned int *nfcache, + struct ip6t_entry_match **match) +{ + const char *proto; + struct ip6t_multiport_v1 *multiinfo + = (struct ip6t_multiport_v1 *)(*match)->data; + + switch (c) { + case '1': + check_inverse(argv[optind-1], &invert, &optind, 0); + proto = check_proto(entry); + parse_multi_ports_v1(argv[optind-1], multiinfo, proto); + multiinfo->flags = IP6T_MULTIPORT_SOURCE; + break; + + case '2': + check_inverse(argv[optind-1], &invert, &optind, 0); + proto = check_proto(entry); + parse_multi_ports_v1(argv[optind-1], multiinfo, proto); + multiinfo->flags = IP6T_MULTIPORT_DESTINATION; + break; + + case '3': + check_inverse(argv[optind-1], &invert, &optind, 0); + proto = check_proto(entry); + parse_multi_ports_v1(argv[optind-1], multiinfo, proto); + multiinfo->flags = IP6T_MULTIPORT_EITHER; + break; + + default: + return 0; + } + + if (invert) + multiinfo->invert = 1; + + if (*flags) + exit_error(PARAMETER_PROBLEM, + "multiport can only have one option"); + *flags = 1; + return 1; +} + /* Final check; must specify something. */ static void final_check(unsigned int flags) @@ -210,6 +314,49 @@ print(const struct ip6t_ip6 *ip, printf(" "); } +static void +print_v1(const struct ip6t_ip6 *ip, + const struct ip6t_entry_match *match, + int numeric) +{ + const struct ip6t_multiport_v1 *multiinfo + = (const struct ip6t_multiport_v1 *)match->data; + unsigned int i; + + printf("multiport "); + + switch (multiinfo->flags) { + case IP6T_MULTIPORT_SOURCE: + printf("sports "); + break; + + case IP6T_MULTIPORT_DESTINATION: + printf("dports "); + break; + + case IP6T_MULTIPORT_EITHER: + printf("ports "); + break; + + default: + printf("ERROR "); + break; + } + + if (multiinfo->invert) + printf("! "); + + for (i=0; i < multiinfo->count; i++) { + printf("%s", i ? "," : ""); + print_port(multiinfo->ports[i], ip->proto, numeric); + if (multiinfo->pflags[i]) { + printf(":"); + print_port(multiinfo->ports[++i], ip->proto, numeric); + } + } + printf(" "); +} + /* Saves the union ip6t_matchinfo in parsable form to stdout. */ static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match) { @@ -238,6 +385,41 @@ static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match printf(" "); } +static void save_v1(const struct ip6t_ip6 *ip, + const struct ip6t_entry_match *match) +{ + const struct ip6t_multiport_v1 *multiinfo + = (const struct ip6t_multiport_v1 *)match->data; + unsigned int i; + + switch (multiinfo->flags) { + case IP6T_MULTIPORT_SOURCE: + printf("--sports "); + break; + + case IP6T_MULTIPORT_DESTINATION: + printf("--dports "); + break; + + case IP6T_MULTIPORT_EITHER: + printf("--ports "); + break; + } + + if (multiinfo->invert) + printf("! "); + + for (i=0; i < multiinfo->count; i++) { + printf("%s", i ? "," : ""); + print_port(multiinfo->ports[i], ip->proto, 1); + if (multiinfo->pflags[i]) { + printf(":"); + print_port(multiinfo->ports[++i], ip->proto, 1); + } + } + printf(" "); +} + static struct ip6tables_match multiport = { .name = "multiport", .version = IPTABLES_VERSION, @@ -252,8 +434,25 @@ static struct ip6tables_match multiport = { .extra_opts = opts, }; +static struct ip6tables_match multiport_v1 = { + .next = NULL, + .name = "multiport", + .revision = 1, + .version = IPTABLES_VERSION, + .size = IP6T_ALIGN(sizeof(struct ip6t_multiport_v1)), + .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_multiport_v1)), + .help = &help_v1, + .init = &init, + .parse = &parse_v1, + .final_check = &final_check, + .print = &print_v1, + .save = &save_v1, + .extra_opts = opts +}; + void _init(void) { register_match6(&multiport); + register_match6(&multiport_v1); } -- cgit v1.2.3