summaryrefslogtreecommitdiffstats
path: root/extensions/libipt_multiport.c
diff options
context:
space:
mode:
authorPablo Neira <pablo@eurodev.net>2005-01-03 09:37:07 +0000
committerRusty Russell <rusty@rustcorp.com.au>2005-01-03 09:37:07 +0000
commit5df9547e093c4fef0bb926adb268dbd020e543a6 (patch)
tree5d2267d64c9429681071a2c7233ba1e009f2e0a5 /extensions/libipt_multiport.c
parentee9c820500c17ebd25f4f90d77e54962d295fa1c (diff)
Pablo Neira:
Multiport revision 1 userspace support.
Diffstat (limited to 'extensions/libipt_multiport.c')
-rw-r--r--extensions/libipt_multiport.c200
1 files changed, 199 insertions, 1 deletions
diff --git a/extensions/libipt_multiport.c b/extensions/libipt_multiport.c
index 9420d5c0..7442f94b 100644
--- a/extensions/libipt_multiport.c
+++ b/extensions/libipt_multiport.c
@@ -5,7 +5,8 @@
#include <stdlib.h>
#include <getopt.h>
#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_multiport.h>
+/* 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; i<IPT_MULTI_PORTS; i++)
+ multiinfo->pflags[i] = 0;
+
+ for (cp=buffer, i=0; cp && i<IPT_MULTI_PORTS; cp=next, i++) {
+ next=strchr(cp, ',');
+ if (next) *next++='\0';
+ range = strchr(cp, ':');
+ if (range) {
+ if (i == IPT_MULTI_PORTS-1)
+ exit_error(PARAMETER_PROBLEM,
+ "too many ports specified");
+ *range++ = '\0';
+ }
+ multiinfo->ports[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);
}