From 55283c74d4ca3284f61803581cf98c950f64dd70 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=rusty/emailAddress=rusty@netfilter.org" Date: Mon, 3 Jan 2005 09:37:07 +0000 Subject: Pablo Neira: Multiport revision 1 userspace support. --- extensions/libipt_multiport.c | 200 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 199 insertions(+), 1 deletion(-) (limited to 'extensions') diff --git a/extensions/libipt_multiport.c b/extensions/libipt_multiport.c index 9420d5c..7442f94 100644 --- a/extensions/libipt_multiport.c +++ b/extensions/libipt_multiport.c @@ -5,7 +5,8 @@ #include #include #include -#include +/* To ensure that iptables compiles with an old kernel */ +#include "../include/linux/netfilter_ipv4/ipt_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); } @@ -77,6 +95,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 ipt_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 ipt_entry_match *m, unsigned int *nfcache) @@ -153,6 +211,56 @@ 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 ipt_entry *entry, + unsigned int *nfcache, + struct ipt_entry_match **match) +{ + const char *proto; + struct ipt_multiport_v1 *multiinfo + = (struct ipt_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 = IPT_MULTIPORT_SOURCE; + *nfcache |= NFC_IP_SRC_PT; + 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 = IPT_MULTIPORT_DESTINATION; + *nfcache |= NFC_IP_DST_PT; + 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 = IPT_MULTIPORT_EITHER; + *nfcache |= NFC_IP_SRC_PT | NFC_IP_DST_PT; + break; + + default: + return 0; + } + + if (invert) + exit_error(PARAMETER_PROBLEM, + "multiport does not support invert"); + + 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) @@ -221,6 +329,46 @@ print(const struct ipt_ip *ip, printf(" "); } +static void +print_v1(const struct ipt_ip *ip, + const struct ipt_entry_match *match, + int numeric) +{ + const struct ipt_multiport_v1 *multiinfo + = (const struct ipt_multiport_v1 *)match->data; + unsigned int i; + + printf("multiport "); + + switch (multiinfo->flags) { + case IPT_MULTIPORT_SOURCE: + printf("sports "); + break; + + case IPT_MULTIPORT_DESTINATION: + printf("dports "); + break; + + case IPT_MULTIPORT_EITHER: + printf("ports "); + break; + + default: + printf("ERROR "); + break; + } + + 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 ipt_matchinfo in parsable form to stdout. */ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match) { @@ -249,9 +397,42 @@ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match) printf(" "); } +static void save_v1(const struct ipt_ip *ip, + const struct ipt_entry_match *match) +{ + const struct ipt_multiport_v1 *multiinfo + = (const struct ipt_multiport_v1 *)match->data; + unsigned int i; + + switch (multiinfo->flags) { + case IPT_MULTIPORT_SOURCE: + printf("--sports "); + break; + + case IPT_MULTIPORT_DESTINATION: + printf("--dports "); + break; + + case IPT_MULTIPORT_EITHER: + printf("--ports "); + break; + } + + 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 iptables_match multiport = { .next = NULL, .name = "multiport", + .revision = 0, .version = IPTABLES_VERSION, .size = IPT_ALIGN(sizeof(struct ipt_multiport)), .userspacesize = IPT_ALIGN(sizeof(struct ipt_multiport)), @@ -264,8 +445,25 @@ static struct iptables_match multiport = { .extra_opts = opts }; +static struct iptables_match multiport_v1 = { + .next = NULL, + .name = "multiport", + .version = IPTABLES_VERSION, + .revision = 1, + .size = IPT_ALIGN(sizeof(struct ipt_multiport_v1)), + .userspacesize = IPT_ALIGN(sizeof(struct ipt_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_match(&multiport); + register_match(&multiport_v1); } -- cgit v1.2.3