All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] iptables: ip6table version support and libip6t_multiport.fix
@ 2006-09-11  1:06 Laurence J. Lane
  2006-10-02  1:37 ` Laurence J. Lane
  0 siblings, 1 reply; 23+ messages in thread
From: Laurence J. Lane @ 2006-09-11  1:06 UTC (permalink / raw)
  To: netfilter-devel

[-- Attachment #1: Type: text/plain, Size: 347 bytes --]

details: http://bugs.debian.org/329775

The 329775-submitter@bugs.debian.org address reaches all
interested Debian parties.

Rémi Denis-Courmont has submitted a patch to that adds version support
to ip6tables and updates libip6t_multiport to v1. (Rémi also posted to the
list but something appears to have gone wrong.)

It Works for Me.

[-- Attachment #2: ipv6-multiport-range.patch --]
[-- Type: text/x-patch, Size: 10377 bytes --]

diff -Nru iptables-1.3.5.orig/extensions/libip6t_multiport.c iptables-1.3.5/extensions/libip6t_multiport.c
--- iptables-1.3.5.orig/extensions/libip6t_multiport.c	2005-02-19 21:19:17.000000000 +0200
+++ iptables-1.3.5/extensions/libip6t_multiport.c	2006-08-27 13:03:36.000000000 +0300
@@ -20,6 +20,23 @@
 " --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);
 }
@@ -49,7 +66,7 @@
 {
 	unsigned int portnum;
 
-	if ((string_to_number(port, 0, 65535, &portnum)) != -1 ||
+	if (string_to_number(port, 0, 65535, &portnum) != -1 ||
 	    (portnum = service_to_port(port, proto)) != -1)
 		return (u_int16_t)portnum;
 
@@ -77,6 +94,46 @@
 	return i;
 }
 
+static void
+parse_multi_ports_v1(const char *portstring, 
+		     struct xt_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<XT_MULTI_PORTS; i++)
+		multiinfo->pflags[i] = 0;
+ 
+	for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next, i++) {
+		next=strchr(cp, ',');
+ 		if (next) *next++='\0';
+		range = strchr(cp, ':');
+		if (range) {
+			if (i == XT_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 ip6t_entry_match *m, unsigned int *nfcache)
@@ -150,6 +207,52 @@
 	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 xt_multiport_v1 *multiinfo
+		= (struct xt_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)
@@ -218,6 +321,49 @@
 	printf(" ");
 }
 
+static void
+print_v1(const struct ip6t_ip6 *ip,
+	 const struct ip6t_entry_match *match,
+	 int numeric)
+{
+	const struct xt_multiport_v1 *multiinfo
+		= (const struct xt_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)
 {
@@ -246,6 +392,41 @@
 	printf(" ");
 }
 
+static void save_v1(const struct ip6t_ip6 *ip, 
+		    const struct ip6t_entry_match *match)
+{
+	const struct xt_multiport_v1 *multiinfo
+		= (const struct xt_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,
@@ -260,8 +441,25 @@
 	.extra_opts	= opts,
 };
 
+static struct ip6tables_match multiport_v1 = { 
+	.next		= NULL,
+	.name		= "multiport",
+	.revision	= 1,
+	.version	= IPTABLES_VERSION,
+	.size		= IP6T_ALIGN(sizeof(struct xt_multiport_v1)),
+	.userspacesize	= IP6T_ALIGN(sizeof(struct xt_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);
 }
diff -Nru iptables-1.3.5.orig/include/ip6tables.h iptables-1.3.5/include/ip6tables.h
--- iptables-1.3.5.orig/include/ip6tables.h	2006-01-30 10:43:09.000000000 +0200
+++ iptables-1.3.5/include/ip6tables.h	2006-08-27 13:02:55.000000000 +0300
@@ -22,6 +22,9 @@
 
 	ip6t_chainlabel name;
 
+	/* Revision of match (0 by default). */
+	u_int8_t revision;
+
 	const char *version;
 
 	/* Size of match data. */
diff -Nru iptables-1.3.5.orig/ip6tables.c iptables-1.3.5/ip6tables.c
--- iptables-1.3.5.orig/ip6tables.c	2006-01-30 10:43:12.000000000 +0200
+++ iptables-1.3.5/ip6tables.c	2006-08-27 13:13:37.000000000 +0300
@@ -193,6 +193,8 @@
 const char *program_name;
 char *lib_dir;
 
+int kernel_version;
+
 /* Keeping track of external matches and targets: linked lists.  */
 struct ip6tables_match *ip6tables_matches = NULL;
 struct ip6tables_target *ip6tables_targets = NULL;
@@ -1047,10 +1049,51 @@
 	return merge;
 }
 
+static int compatible_revision(const char *name, u_int8_t revision, int opt)
+{
+	struct ip6t_get_revision rev;
+	socklen_t s = sizeof(rev);
+	int max_rev, sockfd;
+
+	sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
+	if (sockfd < 0) {
+		fprintf(stderr, "Could not open socket to kernel: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+
+	strcpy(rev.name, name);
+	rev.revision = revision;
+
+	max_rev = getsockopt(sockfd, IPPROTO_IPV6, opt, &rev, &s);
+	if (max_rev < 0) {
+		/* Definitely don't support this? */
+		if (errno == EPROTONOSUPPORT) {
+			close(sockfd);
+			return 0;
+		} else if (errno == ENOPROTOOPT) {
+			close(sockfd);
+			/* Assume only revision 0 support (old kernel) */
+			return (revision == 0);
+		} else {
+			fprintf(stderr, "getsockopt failed strangely: %s\n",
+				strerror(errno));
+			exit(1);
+		}
+	}
+	close(sockfd);
+	return 1;
+}
+
+static int compatible_match_revision(const char *name, u_int8_t revision)
+{
+	return compatible_revision(name, revision, IP6T_SO_GET_REVISION_MATCH);
+}
+
 void
 register_match6(struct ip6tables_match *me)
 {
-	struct ip6tables_match **i;
+	struct ip6tables_match **i, *old;
 
 	if (strcmp(me->version, program_version) != 0) {
 		fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
@@ -1058,12 +1101,36 @@
 		exit(1);
 	}
 
-	if (find_match(me->name, DURING_LOAD, NULL)) {
-		fprintf(stderr, "%s: match `%s' already registered.\n",
+	/* Revision field stole a char from name. */
+	if (strlen(me->name) >= IP6T_FUNCTION_MAXNAMELEN-1) {
+		fprintf(stderr, "%s: target `%s' has invalid name\n",
 			program_name, me->name);
 		exit(1);
 	}
 
+	old = find_match(me->name, DURING_LOAD, NULL);
+	if (old) {
+		if (old->revision == me->revision) {
+			fprintf(stderr,
+				"%s: match `%s' already registered.\n",
+				program_name, me->name);
+			exit(1);
+		}
+
+		/* Now we have two (or more) options, check compatibility. */
+		if (compatible_match_revision(old->name, old->revision)
+		    && old->revision > me->revision)
+			return;
+
+		/* Replace if compatible. */
+		if (!compatible_match_revision(me->name, me->revision))
+			return;
+
+		/* Delete old one. */
+		for (i = &ip6tables_matches; *i!=old; i = &(*i)->next);
+		*i = old->next;
+	}
+	
 	if (me->size != IP6T_ALIGN(me->size)) {
 		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
 			program_name, me->name, (unsigned int)me->size);
@@ -1700,6 +1767,14 @@
 	*matches = NULL;
 }
 
+static void set_revision(char *name, u_int8_t revision)
+{
+	/* Old kernel sources don't have ".revision" field,
+	   but we stole a byte from name. */
+	name[IP6T_FUNCTION_MAXNAMELEN - 2] = '\0';
+	name[IP6T_FUNCTION_MAXNAMELEN - 1] = revision;
+}
+
 int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
 {
 	struct ip6t_entry fw, *e = NULL;
@@ -1978,6 +2053,7 @@
 			m->m = fw_calloc(1, size);
 			m->m->u.match_size = size;
 			strcpy(m->m->u.user.name, m->name);
+			set_revision(m->m->u.user.name, m->revision);
 			if (m->init != NULL)
 				m->init(m->m, &fw.nfcache);
 			opts = merge_options(opts, m->extra_opts, &m->option_offset);
@@ -2120,6 +2196,8 @@
 					m->m = fw_calloc(1, size);
 					m->m->u.match_size = size;
 					strcpy(m->m->u.user.name, m->name);
+					set_revision(m->m->u.user.name,
+						     m->revision);
 					if (m->init != NULL)
 						m->init(m->m, &fw.nfcache);
 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
  2006-09-11  1:06 [PATCH] iptables: ip6table version support and libip6t_multiport.fix Laurence J. Lane
@ 2006-10-02  1:37 ` Laurence J. Lane
  2006-10-02  4:46   ` Yasuyuki KOZAKAI
  0 siblings, 1 reply; 23+ messages in thread
From: Laurence J. Lane @ 2006-10-02  1:37 UTC (permalink / raw)
  To: netfilter-devel

On 9/10/06, Laurence J. Lane <ljlane@debian.org> wrote:

> details: http://bugs.debian.org/329775
>
> The 329775-submitter@bugs.debian.org address reaches all
> interested Debian parties.
>
> Rémi Denis-Courmont has submitted a patch to that adds version support
> to ip6tables and updates libip6t_multiport to v1. (Rémi also posted to the
> list but something appears to have gone wrong.)
>
> It Works for Me.

I guess the list software ate the attachment.

diff -Nru iptables-1.3.5.orig/extensions/libip6t_multiport.c
iptables-1.3.5/extensions/libip6t_multiport.c
--- iptables-1.3.5.orig/extensions/libip6t_multiport.c	2005-02-19
21:19:17.000000000 +0200
+++ iptables-1.3.5/extensions/libip6t_multiport.c	2006-08-27
13:03:36.000000000 +0300
@@ -20,6 +20,23 @@
 " --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);
 }
@@ -49,7 +66,7 @@
 {
 	unsigned int portnum;

-	if ((string_to_number(port, 0, 65535, &portnum)) != -1 ||
+	if (string_to_number(port, 0, 65535, &portnum) != -1 ||
 	    (portnum = service_to_port(port, proto)) != -1)
 		return (u_int16_t)portnum;

@@ -77,6 +94,46 @@
 	return i;
 }

+static void
+parse_multi_ports_v1(const char *portstring,
+		     struct xt_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<XT_MULTI_PORTS; i++)
+		multiinfo->pflags[i] = 0;
+
+	for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next, i++) {
+		next=strchr(cp, ',');
+ 		if (next) *next++='\0';
+		range = strchr(cp, ':');
+		if (range) {
+			if (i == XT_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 ip6t_entry_match *m, unsigned int *nfcache)
@@ -150,6 +207,52 @@
 	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 xt_multiport_v1 *multiinfo
+		= (struct xt_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)
@@ -218,6 +321,49 @@
 	printf(" ");
 }

+static void
+print_v1(const struct ip6t_ip6 *ip,
+	 const struct ip6t_entry_match *match,
+	 int numeric)
+{
+	const struct xt_multiport_v1 *multiinfo
+		= (const struct xt_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)
 {
@@ -246,6 +392,41 @@
 	printf(" ");
 }

+static void save_v1(const struct ip6t_ip6 *ip,
+		    const struct ip6t_entry_match *match)
+{
+	const struct xt_multiport_v1 *multiinfo
+		= (const struct xt_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,
@@ -260,8 +441,25 @@
 	.extra_opts	= opts,
 };

+static struct ip6tables_match multiport_v1 = {
+	.next		= NULL,
+	.name		= "multiport",
+	.revision	= 1,
+	.version	= IPTABLES_VERSION,
+	.size		= IP6T_ALIGN(sizeof(struct xt_multiport_v1)),
+	.userspacesize	= IP6T_ALIGN(sizeof(struct xt_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);
 }
diff -Nru iptables-1.3.5.orig/include/ip6tables.h
iptables-1.3.5/include/ip6tables.h
--- iptables-1.3.5.orig/include/ip6tables.h	2006-01-30 10:43:09.000000000 +0200
+++ iptables-1.3.5/include/ip6tables.h	2006-08-27 13:02:55.000000000 +0300
@@ -22,6 +22,9 @@

 	ip6t_chainlabel name;

+	/* Revision of match (0 by default). */
+	u_int8_t revision;
+
 	const char *version;

 	/* Size of match data. */
diff -Nru iptables-1.3.5.orig/ip6tables.c iptables-1.3.5/ip6tables.c
--- iptables-1.3.5.orig/ip6tables.c	2006-01-30 10:43:12.000000000 +0200
+++ iptables-1.3.5/ip6tables.c	2006-08-27 13:13:37.000000000 +0300
@@ -193,6 +193,8 @@
 const char *program_name;
 char *lib_dir;

+int kernel_version;
+
 /* Keeping track of external matches and targets: linked lists.  */
 struct ip6tables_match *ip6tables_matches = NULL;
 struct ip6tables_target *ip6tables_targets = NULL;
@@ -1047,10 +1049,51 @@
 	return merge;
 }

+static int compatible_revision(const char *name, u_int8_t revision, int opt)
+{
+	struct ip6t_get_revision rev;
+	socklen_t s = sizeof(rev);
+	int max_rev, sockfd;
+
+	sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
+	if (sockfd < 0) {
+		fprintf(stderr, "Could not open socket to kernel: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+
+	strcpy(rev.name, name);
+	rev.revision = revision;
+
+	max_rev = getsockopt(sockfd, IPPROTO_IPV6, opt, &rev, &s);
+	if (max_rev < 0) {
+		/* Definitely don't support this? */
+		if (errno == EPROTONOSUPPORT) {
+			close(sockfd);
+			return 0;
+		} else if (errno == ENOPROTOOPT) {
+			close(sockfd);
+			/* Assume only revision 0 support (old kernel) */
+			return (revision == 0);
+		} else {
+			fprintf(stderr, "getsockopt failed strangely: %s\n",
+				strerror(errno));
+			exit(1);
+		}
+	}
+	close(sockfd);
+	return 1;
+}
+
+static int compatible_match_revision(const char *name, u_int8_t revision)
+{
+	return compatible_revision(name, revision, IP6T_SO_GET_REVISION_MATCH);
+}
+
 void
 register_match6(struct ip6tables_match *me)
 {
-	struct ip6tables_match **i;
+	struct ip6tables_match **i, *old;

 	if (strcmp(me->version, program_version) != 0) {
 		fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
@@ -1058,12 +1101,36 @@
 		exit(1);
 	}

-	if (find_match(me->name, DURING_LOAD, NULL)) {
-		fprintf(stderr, "%s: match `%s' already registered.\n",
+	/* Revision field stole a char from name. */
+	if (strlen(me->name) >= IP6T_FUNCTION_MAXNAMELEN-1) {
+		fprintf(stderr, "%s: target `%s' has invalid name\n",
 			program_name, me->name);
 		exit(1);
 	}

+	old = find_match(me->name, DURING_LOAD, NULL);
+	if (old) {
+		if (old->revision == me->revision) {
+			fprintf(stderr,
+				"%s: match `%s' already registered.\n",
+				program_name, me->name);
+			exit(1);
+		}
+
+		/* Now we have two (or more) options, check compatibility. */
+		if (compatible_match_revision(old->name, old->revision)
+		    && old->revision > me->revision)
+			return;
+
+		/* Replace if compatible. */
+		if (!compatible_match_revision(me->name, me->revision))
+			return;
+
+		/* Delete old one. */
+		for (i = &ip6tables_matches; *i!=old; i = &(*i)->next);
+		*i = old->next;
+	}
+	
 	if (me->size != IP6T_ALIGN(me->size)) {
 		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
 			program_name, me->name, (unsigned int)me->size);
@@ -1700,6 +1767,14 @@
 	*matches = NULL;
 }

+static void set_revision(char *name, u_int8_t revision)
+{
+	/* Old kernel sources don't have ".revision" field,
+	   but we stole a byte from name. */
+	name[IP6T_FUNCTION_MAXNAMELEN - 2] = '\0';
+	name[IP6T_FUNCTION_MAXNAMELEN - 1] = revision;
+}
+
 int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
 {
 	struct ip6t_entry fw, *e = NULL;
@@ -1978,6 +2053,7 @@
 			m->m = fw_calloc(1, size);
 			m->m->u.match_size = size;
 			strcpy(m->m->u.user.name, m->name);
+			set_revision(m->m->u.user.name, m->revision);
 			if (m->init != NULL)
 				m->init(m->m, &fw.nfcache);
 			opts = merge_options(opts, m->extra_opts, &m->option_offset);
@@ -2120,6 +2196,8 @@
 					m->m = fw_calloc(1, size);
 					m->m->u.match_size = size;
 					strcpy(m->m->u.user.name, m->name);
+					set_revision(m->m->u.user.name,
+						     m->revision);
 					if (m->init != NULL)
 						m->init(m->m, &fw.nfcache);

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
  2006-10-02  1:37 ` Laurence J. Lane
@ 2006-10-02  4:46   ` Yasuyuki KOZAKAI
  2006-10-02 14:47     ` Rémi Denis-Courmont
  0 siblings, 1 reply; 23+ messages in thread
From: Yasuyuki KOZAKAI @ 2006-10-02  4:46 UTC (permalink / raw)
  To: ljlane; +Cc: netfilter-devel


Hello,

From: "Laurence J. Lane" <ljlane@debian.org>
Date: Sun, 1 Oct 2006 21:37:54 -0400

> On 9/10/06, Laurence J. Lane <ljlane@debian.org> wrote:
> 
> > details: http://bugs.debian.org/329775
> >
> > The 329775-submitter@bugs.debian.org address reaches all
> > interested Debian parties.
> >
> > Rémi Denis-Courmont has submitted a patch to that adds version support
> > to ip6tables and updates libip6t_multiport to v1. (Rémi also posted to the
> > list but something appears to have gone wrong.)
> >
> > It Works for Me.
> 
> I guess the list software ate the attachment.

Great! I'll read deeply that.

> +static void
> +parse_multi_ports_v1(const char *portstring,
> +		     struct xt_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<XT_MULTI_PORTS; i++)
> +		multiinfo->pflags[i] = 0;
> +
> +	for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next, i++) {

Please use IP6T_MULTI_PORTS so that we can compile with linux 2.4.

Regards,

-- Yasuyuki Kozakai

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
  2006-10-02  4:46   ` Yasuyuki KOZAKAI
@ 2006-10-02 14:47     ` Rémi Denis-Courmont
  2006-10-03 14:30       ` Yasuyuki KOZAKAI
       [not found]       ` <200610031430.k93EUJgA008197@toshiba.co.jp>
  0 siblings, 2 replies; 23+ messages in thread
From: Rémi Denis-Courmont @ 2006-10-02 14:47 UTC (permalink / raw)
  To: Yasuyuki KOZAKAI; +Cc: ljlane, netfilter-devel

Le lundi 2 octobre 2006 07:46, Yasuyuki KOZAKAI a écrit :
(...)
> Please use IP6T_MULTI_PORTS so that we can compile with linux 2.4.

There you go (also resynched with latest SVN), but won't it fail with 
xt_multiport_v1 anyway (there is no ip6t_multiport_v1 in *any* kernel 
version to date, AFAIK)?

Index: include/ip6tables.h
===================================================================
--- include/ip6tables.h	(révision 6678)
+++ include/ip6tables.h	(copie de travail)
@@ -33,6 +33,9 @@
 
 	ip6t_chainlabel name;
 
+	/* Revision of match (0 by default). */
+	u_int8_t revision;
+
 	const char *version;
 
 	/* Size of match data. */
Index: extensions/libip6t_multiport.c
===================================================================
--- extensions/libip6t_multiport.c	(révision 6678)
+++ extensions/libip6t_multiport.c	(copie de travail)
@@ -20,6 +20,23 @@
 " --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 +87,46 @@
 	return i;
 }
 
+static void
+parse_multi_ports_v1(const char *portstring, 
+		     struct xt_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<IP6T_MULTI_PORTS; i++)
+		multiinfo->pflags[i] = 0;
+ 
+	for (cp=buffer, i=0; cp && i<IP6T_MULTI_PORTS; cp=next, i++) {
+		next=strchr(cp, ',');
+ 		if (next) *next++='\0';
+		range = strchr(cp, ':');
+		if (range) {
+			if (i == IP6T_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 ip6t_entry_match *m, unsigned int *nfcache)
@@ -143,6 +200,52 @@
 	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 xt_multiport_v1 *multiinfo
+		= (struct xt_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 +313,49 @@
 	printf(" ");
 }
 
+static void
+print_v1(const struct ip6t_ip6 *ip,
+	 const struct ip6t_entry_match *match,
+	 int numeric)
+{
+	const struct xt_multiport_v1 *multiinfo
+		= (const struct xt_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 +384,41 @@
 	printf(" ");
 }
 
+static void save_v1(const struct ip6t_ip6 *ip, 
+		    const struct ip6t_entry_match *match)
+{
+	const struct xt_multiport_v1 *multiinfo
+		= (const struct xt_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 +433,25 @@
 	.extra_opts	= opts,
 };
 
+static struct ip6tables_match multiport_v1 = { 
+	.next		= NULL,
+	.name		= "multiport",
+	.revision	= 1,
+	.version	= IPTABLES_VERSION,
+	.size		= IP6T_ALIGN(sizeof(struct xt_multiport_v1)),
+	.userspacesize	= IP6T_ALIGN(sizeof(struct xt_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);
 }
Index: ip6tables.c
===================================================================
--- ip6tables.c	(révision 6678)
+++ ip6tables.c	(copie de travail)
@@ -193,6 +193,8 @@
 const char *program_name;
 char *lib_dir;
 
+int kernel_version;
+
 /* Keeping track of external matches and targets: linked lists.  */
 struct ip6tables_match *ip6tables_matches = NULL;
 struct ip6tables_target *ip6tables_targets = NULL;
@@ -1102,10 +1104,51 @@
 	return merge;
 }
 
+static int compatible_revision(const char *name, u_int8_t revision, int 
opt)
+{
+	struct ip6t_get_revision rev;
+	socklen_t s = sizeof(rev);
+	int max_rev, sockfd;
+
+	sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
+	if (sockfd < 0) {
+		fprintf(stderr, "Could not open socket to kernel: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+
+	strcpy(rev.name, name);
+	rev.revision = revision;
+
+	max_rev = getsockopt(sockfd, IPPROTO_IPV6, opt, &rev, &s);
+	if (max_rev < 0) {
+		/* Definitely don't support this? */
+		if (errno == EPROTONOSUPPORT) {
+			close(sockfd);
+			return 0;
+		} else if (errno == ENOPROTOOPT) {
+			close(sockfd);
+			/* Assume only revision 0 support (old kernel) */
+			return (revision == 0);
+		} else {
+			fprintf(stderr, "getsockopt failed strangely: %s\n",
+				strerror(errno));
+			exit(1);
+		}
+	}
+	close(sockfd);
+	return 1;
+}
+
+static int compatible_match_revision(const char *name, u_int8_t 
revision)
+{
+	return compatible_revision(name, revision, 
IP6T_SO_GET_REVISION_MATCH);
+}
+
 void
 register_match6(struct ip6tables_match *me)
 {
-	struct ip6tables_match **i;
+	struct ip6tables_match **i, *old;
 
 	if (strcmp(me->version, program_version) != 0) {
 		fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
@@ -1113,12 +1156,36 @@
 		exit(1);
 	}
 
-	if (find_match(me->name, DURING_LOAD, NULL)) {
-		fprintf(stderr, "%s: match `%s' already registered.\n",
+	/* Revision field stole a char from name. */
+	if (strlen(me->name) >= IP6T_FUNCTION_MAXNAMELEN-1) {
+		fprintf(stderr, "%s: target `%s' has invalid name\n",
 			program_name, me->name);
 		exit(1);
 	}
 
+	old = find_match(me->name, DURING_LOAD, NULL);
+	if (old) {
+		if (old->revision == me->revision) {
+			fprintf(stderr,
+				"%s: match `%s' already registered.\n",
+				program_name, me->name);
+			exit(1);
+		}
+
+		/* Now we have two (or more) options, check compatibility. */
+		if (compatible_match_revision(old->name, old->revision)
+		    && old->revision > me->revision)
+			return;
+
+		/* Replace if compatible. */
+		if (!compatible_match_revision(me->name, me->revision))
+			return;
+
+		/* Delete old one. */
+		for (i = &ip6tables_matches; *i!=old; i = &(*i)->next);
+		*i = old->next;
+	}
+	
 	if (me->size != IP6T_ALIGN(me->size)) {
 		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
 			program_name, me->name, (unsigned int)me->size);
@@ -1761,6 +1828,14 @@
 	*matches = NULL;
 }
 
+static void set_revision(char *name, u_int8_t revision)
+{
+	/* Old kernel sources don't have ".revision" field,
+	   but we stole a byte from name. */
+	name[IP6T_FUNCTION_MAXNAMELEN - 2] = '\0';
+	name[IP6T_FUNCTION_MAXNAMELEN - 1] = revision;
+}
+
 int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t 
*handle)
 {
 	struct ip6t_entry fw, *e = NULL;
@@ -2041,6 +2116,7 @@
 			m->m = fw_calloc(1, size);
 			m->m->u.match_size = size;
 			strcpy(m->m->u.user.name, m->name);
+			set_revision(m->m->u.user.name, m->revision);
 			if (m->init != NULL)
 				m->init(m->m, &fw.nfcache);
 			if (m != m->next)
@@ -2185,6 +2261,8 @@
 					m->m = fw_calloc(1, size);
 					m->m->u.match_size = size;
 					strcpy(m->m->u.user.name, m->name);
+					set_revision(m->m->u.user.name,
+						     m->revision);
 					if (m->init != NULL)
 						m->init(m->m, &fw.nfcache);
 

-- 
Rémi Denis-Courmont
http://www.remlab.net/

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
  2006-10-02 14:47     ` Rémi Denis-Courmont
@ 2006-10-03 14:30       ` Yasuyuki KOZAKAI
       [not found]       ` <200610031430.k93EUJgA008197@toshiba.co.jp>
  1 sibling, 0 replies; 23+ messages in thread
From: Yasuyuki KOZAKAI @ 2006-10-03 14:30 UTC (permalink / raw)
  To: rdenis; +Cc: ljlane, netfilter-devel, yasuyuki.kozakai

From: Rémi Denis-Courmont <rdenis@simphalempin.com>
Date: Mon, 2 Oct 2006 17:47:42 +0300

> Le lundi 2 octobre 2006 07:46, Yasuyuki KOZAKAI a écrit :
> (...)
> > Please use IP6T_MULTI_PORTS so that we can compile with linux 2.4.
> 
> There you go (also resynched with latest SVN), but won't it fail with 
> xt_multiport_v1 anyway (there is no ip6t_multiport_v1 in *any* kernel 
> version to date, AFAIK)?

But they have multiport v0 features. The revision was introduced to keep
compatibility with such features in old kernel and make possible to add new
features to new kernel.

IPv4 multiport match (and policy match, too) would help you. It has
the line

	#include ../../include/netfilter_ipv4/ipt_multiport.h

and definitions for old kernel are included in the header.

-- Yasuyuki Kozakai

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
       [not found]       ` <200610031430.k93EUJgA008197@toshiba.co.jp>
@ 2006-10-03 19:58         ` Rémi Denis-Courmont
  2006-10-12  8:11           ` Yasuyuki KOZAKAI
       [not found]           ` <200610120811.k9C8B4Pg002384@toshiba.co.jp>
  0 siblings, 2 replies; 23+ messages in thread
From: Rémi Denis-Courmont @ 2006-10-03 19:58 UTC (permalink / raw)
  To: Yasuyuki KOZAKAI; +Cc: ljlane, netfilter-devel

Le mardi 3 octobre 2006 17:30, vous avez écrit :
> IPv4 multiport match (and policy match, too) would help you. It has
> the line
>
> 	#include ../../include/netfilter_ipv4/ipt_multiport.h
>
> and definitions for old kernel are included in the header.

Ok. This time there is no trace of (xt|XT)_ at all:

diff -Nru iptables-1.3.5.orig/extensions/libip6t_multiport.c 
iptables-1.3.5/extensions/libip6t_multiport.c
--- iptables-1.3.5.orig/extensions/libip6t_multiport.c	2005-02-19 
21:19:17.000000000 +0200
+++ iptables-1.3.5/extensions/libip6t_multiport.c	2006-08-27 
13:03:36.000000000 +0300
@@ -20,6 +20,23 @@
 " --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);
 }
@@ -49,7 +66,7 @@
 {
 	unsigned int portnum;
 
-	if ((string_to_number(port, 0, 65535, &portnum)) != -1 ||
+	if (string_to_number(port, 0, 65535, &portnum) != -1 ||
 	    (portnum = service_to_port(port, proto)) != -1)
 		return (u_int16_t)portnum;
 
@@ -77,6 +94,46 @@
 	return i;
 }
 
+static void
+parse_multi_ports_v1(const char *portstring, 
+		     struct xt_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<XT_MULTI_PORTS; i++)
+		multiinfo->pflags[i] = 0;
+ 
+	for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next, i++) {
+		next=strchr(cp, ',');
+ 		if (next) *next++='\0';
+		range = strchr(cp, ':');
+		if (range) {
+			if (i == XT_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 ip6t_entry_match *m, unsigned int *nfcache)
@@ -150,6 +207,52 @@
 	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 xt_multiport_v1 *multiinfo
+		= (struct xt_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)
@@ -218,6 +321,49 @@
 	printf(" ");
 }
 
+static void
+print_v1(const struct ip6t_ip6 *ip,
+	 const struct ip6t_entry_match *match,
+	 int numeric)
+{
+	const struct xt_multiport_v1 *multiinfo
+		= (const struct xt_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)
 {
@@ -246,6 +392,41 @@
 	printf(" ");
 }
 
+static void save_v1(const struct ip6t_ip6 *ip, 
+		    const struct ip6t_entry_match *match)
+{
+	const struct xt_multiport_v1 *multiinfo
+		= (const struct xt_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,
@@ -260,8 +441,25 @@
 	.extra_opts	= opts,
 };
 
+static struct ip6tables_match multiport_v1 = { 
+	.next		= NULL,
+	.name		= "multiport",
+	.revision	= 1,
+	.version	= IPTABLES_VERSION,
+	.size		= IP6T_ALIGN(sizeof(struct xt_multiport_v1)),
+	.userspacesize	= IP6T_ALIGN(sizeof(struct xt_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);
 }
diff -Nru iptables-1.3.5.orig/include/ip6tables.h 
iptables-1.3.5/include/ip6tables.h
--- iptables-1.3.5.orig/include/ip6tables.h	2006-01-30 
10:43:09.000000000 +0200
+++ iptables-1.3.5/include/ip6tables.h	2006-08-27 13:02:55.000000000 
+0300
@@ -22,6 +22,9 @@
 
 	ip6t_chainlabel name;
 
+	/* Revision of match (0 by default). */
+	u_int8_t revision;
+
 	const char *version;
 
 	/* Size of match data. */
diff -Nru iptables-1.3.5.orig/ip6tables.c iptables-1.3.5/ip6tables.c
--- iptables-1.3.5.orig/ip6tables.c	2006-01-30 10:43:12.000000000 +0200
+++ iptables-1.3.5/ip6tables.c	2006-08-27 13:13:37.000000000 +0300
@@ -193,6 +193,8 @@
 const char *program_name;
 char *lib_dir;
 
+int kernel_version;
+
 /* Keeping track of external matches and targets: linked lists.  */
 struct ip6tables_match *ip6tables_matches = NULL;
 struct ip6tables_target *ip6tables_targets = NULL;
@@ -1047,10 +1049,51 @@
 	return merge;
 }
 
+static int compatible_revision(const char *name, u_int8_t revision, int 
opt)
+{
+	struct ip6t_get_revision rev;
+	socklen_t s = sizeof(rev);
+	int max_rev, sockfd;
+
+	sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
+	if (sockfd < 0) {
+		fprintf(stderr, "Could not open socket to kernel: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+
+	strcpy(rev.name, name);
+	rev.revision = revision;
+
+	max_rev = getsockopt(sockfd, IPPROTO_IPV6, opt, &rev, &s);
+	if (max_rev < 0) {
+		/* Definitely don't support this? */
+		if (errno == EPROTONOSUPPORT) {
+			close(sockfd);
+			return 0;
+		} else if (errno == ENOPROTOOPT) {
+			close(sockfd);
+			/* Assume only revision 0 support (old kernel) */
+			return (revision == 0);
+		} else {
+			fprintf(stderr, "getsockopt failed strangely: %s\n",
+				strerror(errno));
+			exit(1);
+		}
+	}
+	close(sockfd);
+	return 1;
+}
+
+static int compatible_match_revision(const char *name, u_int8_t 
revision)
+{
+	return compatible_revision(name, revision, 
IP6T_SO_GET_REVISION_MATCH);
+}
+
 void
 register_match6(struct ip6tables_match *me)
 {
-	struct ip6tables_match **i;
+	struct ip6tables_match **i, *old;
 
 	if (strcmp(me->version, program_version) != 0) {
 		fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
@@ -1058,12 +1101,36 @@
 		exit(1);
 	}
 
-	if (find_match(me->name, DURING_LOAD, NULL)) {
-		fprintf(stderr, "%s: match `%s' already registered.\n",
+	/* Revision field stole a char from name. */
+	if (strlen(me->name) >= IP6T_FUNCTION_MAXNAMELEN-1) {
+		fprintf(stderr, "%s: target `%s' has invalid name\n",
 			program_name, me->name);
 		exit(1);
 	}
 
+	old = find_match(me->name, DURING_LOAD, NULL);
+	if (old) {
+		if (old->revision == me->revision) {
+			fprintf(stderr,
+				"%s: match `%s' already registered.\n",
+				program_name, me->name);
+			exit(1);
+		}
+
+		/* Now we have two (or more) options, check compatibility. */
+		if (compatible_match_revision(old->name, old->revision)
+		    && old->revision > me->revision)
+			return;
+
+		/* Replace if compatible. */
+		if (!compatible_match_revision(me->name, me->revision))
+			return;
+
+		/* Delete old one. */
+		for (i = &ip6tables_matches; *i!=old; i = &(*i)->next);
+		*i = old->next;
+	}
+	
 	if (me->size != IP6T_ALIGN(me->size)) {
 		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
 			program_name, me->name, (unsigned int)me->size);
@@ -1700,6 +1767,14 @@
 	*matches = NULL;
 }
 
+static void set_revision(char *name, u_int8_t revision)
+{
+	/* Old kernel sources don't have ".revision" field,
+	   but we stole a byte from name. */
+	name[IP6T_FUNCTION_MAXNAMELEN - 2] = '\0';
+	name[IP6T_FUNCTION_MAXNAMELEN - 1] = revision;
+}
+
 int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t 
*handle)
 {
 	struct ip6t_entry fw, *e = NULL;
@@ -1978,6 +2053,7 @@
 			m->m = fw_calloc(1, size);
 			m->m->u.match_size = size;
 			strcpy(m->m->u.user.name, m->name);
+			set_revision(m->m->u.user.name, m->revision);
 			if (m->init != NULL)
 				m->init(m->m, &fw.nfcache);
 			opts = merge_options(opts, m->extra_opts, &m->option_offset);
@@ -2120,6 +2196,8 @@
 					m->m = fw_calloc(1, size);
 					m->m->u.match_size = size;
 					strcpy(m->m->u.user.name, m->name);
+					set_revision(m->m->u.user.name,
+						     m->revision);
 					if (m->init != NULL)
 						m->init(m->m, &fw.nfcache);
 

-- 
Rémi Denis-Courmont
http://www.remlab.net/

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Compiling 1.3.6
@ 2006-10-06 18:41 Jorge Bastos
  2006-10-08 22:21 ` Pablo Neira Ayuso
  0 siblings, 1 reply; 23+ messages in thread
From: Jorge Bastos @ 2006-10-06 18:41 UTC (permalink / raw)
  To: netfilter

I was compiling the 1.3.6 version of iptables, agains my 2.6.19-rc1 kernel 
version and i get this (it also happens with the final 2.6.18).
Is there some livrary that needs an upgrade or am i missing something?
I already tryed the svn last version and the same happens.

Thanks,
Jorge


Extensions found: IPv4:CLUSTERIP IPv4:connbytes IPv4:dccp IPv4:quota 
IPv4:recent IPv4:statistic IPv4:string IPv6:REJECT IPv6:ah IPv6:esp 
IPv6:frag IPv6:ipv6header IPv6:rt
cc -O2 -Wall -Wunused -I/usr/src/linux-2.6.18/include -Iinclude/ -DIPTABLES_VERSION=\"1.3.6\" 
  -fPIC -o extensions/libipt_iprange_sh.o -c extensions/libipt_iprange.c
In file included from extensions/libipt_iprange.c:9:
/usr/src/linux-2.6.18/include/linux/netfilter_ipv4/ipt_iprange.h:11: error: 
expected specifier-qualifier-list before '__be32'
extensions/libipt_iprange.c: In function 'parse_iprange':
extensions/libipt_iprange.c:43: error: 'struct ipt_iprange' has no member 
named 'min_ip'
extensions/libipt_iprange.c:50: error: 'struct ipt_iprange' has no member 
named 'max_ip'
extensions/libipt_iprange.c:52: error: 'struct ipt_iprange' has no member 
named 'max_ip'
extensions/libipt_iprange.c:52: error: 'struct ipt_iprange' has no member 
named 'min_ip'
extensions/libipt_iprange.c: In function 'print_iprange':
extensions/libipt_iprange.c:116: error: 'const struct ipt_iprange' has no 
member named 'min_ip'
extensions/libipt_iprange.c:117: error: 'const struct ipt_iprange' has no 
member named 'max_ip'
make: *** [extensions/libipt_iprange_sh.o] Error 1 



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Compiling 1.3.6
  2006-10-06 18:41 Compiling 1.3.6 Jorge Bastos
@ 2006-10-08 22:21 ` Pablo Neira Ayuso
  2006-10-09 15:23   ` Patrick McHardy
  0 siblings, 1 reply; 23+ messages in thread
From: Pablo Neira Ayuso @ 2006-10-08 22:21 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter, Netfilter Development Mailinglist

[-- Attachment #1: Type: text/plain, Size: 711 bytes --]

Hi Patrick,

Jorge Bastos wrote:
> I was compiling the 1.3.6 version of iptables, agains my 2.6.19-rc1
> kernel version and i get this (it also happens with the final 2.6.18).
> Is there some livrary that needs an upgrade or am i missing something?
> I already tryed the svn last version and the same happens.

min_ip and max_ip type has been changed from u_int32_t to __be32 that is
not defined in userspace, this breaks iptables compilation. Attached a
patch that recovers the use of u_int32_t. I'm not sure if this is the
best fix so let me know what you think.

-- 
The dawn of the fourth age of Linux firewalling is coming; a time of
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris

[-- Attachment #2: x --]
[-- Type: text/plain, Size: 721 bytes --]

[PATCH] Fix iptables compilation with support for iprange

iptables requires ipt_iprange.h that defines max_ip and min_ip as __be32
that is not defined in userspace.

Reported by Jorge Bastos.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Index: net-2.6/include/linux/netfilter_ipv4/ipt_iprange.h
===================================================================
--- net-2.6.orig/include/linux/netfilter_ipv4/ipt_iprange.h	2006-10-09 00:15:42.000000000 +0200
+++ net-2.6/include/linux/netfilter_ipv4/ipt_iprange.h	2006-10-09 00:15:55.000000000 +0200
@@ -8,7 +8,7 @@
 
 struct ipt_iprange {
 	/* Inclusive: network order. */
-	__be32 min_ip, max_ip;
+	u_int32_t min_ip, max_ip;
 };
 
 struct ipt_iprange_info

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Compiling 1.3.6
  2006-10-08 22:21 ` Pablo Neira Ayuso
@ 2006-10-09 15:23   ` Patrick McHardy
  2006-10-09 15:36     ` Pablo Neira Ayuso
  0 siblings, 1 reply; 23+ messages in thread
From: Patrick McHardy @ 2006-10-09 15:23 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter, Netfilter Development Mailinglist

[-- Attachment #1: Type: text/plain, Size: 394 bytes --]

Pablo Neira Ayuso wrote:
> min_ip and max_ip type has been changed from u_int32_t to __be32 that is
> not defined in userspace, this breaks iptables compilation. Attached a
> patch that recovers the use of u_int32_t. I'm not sure if this is the
> best fix so let me know what you think.

I think we should just define the endian-annotation types in userspace.
Does this patch fix compilation?


[-- Attachment #2: x --]
[-- Type: text/plain, Size: 395 bytes --]

Index: include/iptables_common.h
===================================================================
--- include/iptables_common.h	(Revision 6660)
+++ include/iptables_common.h	(Arbeitskopie)
@@ -42,4 +42,9 @@
   extern void init_extensions(void);
 #endif
 
+#define __be32	u_int32_t
+#define __le32	u_int32_t
+#define __be16	u_int16_t
+#define __le16	u_int16_t
+
 #endif /*_IPTABLES_COMMON_H*/

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Compiling 1.3.6
  2006-10-09 15:23   ` Patrick McHardy
@ 2006-10-09 15:36     ` Pablo Neira Ayuso
  2006-10-09 15:44       ` Pablo Neira Ayuso
  2006-10-09 16:02       ` Patrick McHardy
  0 siblings, 2 replies; 23+ messages in thread
From: Pablo Neira Ayuso @ 2006-10-09 15:36 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: netfilter, Netfilter Development Mailinglist, Jorge Bastos

Patrick McHardy wrote:
> Pablo Neira Ayuso wrote:
> 
>>min_ip and max_ip type has been changed from u_int32_t to __be32 that is
>>not defined in userspace, this breaks iptables compilation. Attached a
>>patch that recovers the use of u_int32_t. I'm not sure if this is the
>>best fix so let me know what you think.
> 
> 
> I think we should just define the endian-annotation types in userspace.
> Does this patch fix compilation?

But this breaks previous iptables version with new kernels :(. An 
alternative can be exporting ipt_iprange.h to iptables/include although 
this is also a hack.

-- 
The dawn of the fourth age of Linux firewalling is coming; a time of 
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Compiling 1.3.6
  2006-10-09 15:36     ` Pablo Neira Ayuso
@ 2006-10-09 15:44       ` Pablo Neira Ayuso
  2006-10-09 15:58         ` Marco Berizzi
  2006-10-09 16:02       ` Patrick McHardy
  1 sibling, 1 reply; 23+ messages in thread
From: Pablo Neira Ayuso @ 2006-10-09 15:44 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter, Netfilter Development Mailinglist

Pablo Neira Ayuso wrote:
> Patrick McHardy wrote:
> 
>> Pablo Neira Ayuso wrote:
>>
>>> min_ip and max_ip type has been changed from u_int32_t to __be32 that is
>>> not defined in userspace, this breaks iptables compilation. Attached a
>>> patch that recovers the use of u_int32_t. I'm not sure if this is the
>>> best fix so let me know what you think.
>>
>>
>>
>> I think we should just define the endian-annotation types in userspace.
>> Does this patch fix compilation?
> 
> 
> But this breaks previous iptables version with new kernels :(.  An
> alternative can be exporting ipt_iprange.h to iptables/include although 
> this is also a hack.

Forget the alternative, it won't work either

-- 
The dawn of the fourth age of Linux firewalling is coming; a time of 
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Compiling 1.3.6
  2006-10-09 15:44       ` Pablo Neira Ayuso
@ 2006-10-09 15:58         ` Marco Berizzi
  2006-10-09 16:02           ` Patrick McHardy
  0 siblings, 1 reply; 23+ messages in thread
From: Marco Berizzi @ 2006-10-09 15:58 UTC (permalink / raw)
  To: pablo, kaber; +Cc: netfilter-devel, netfilter

Pablo Neira Ayuso wrote:

>Pablo Neira Ayuso wrote:
>>Patrick McHardy wrote:
>>
>>>Pablo Neira Ayuso wrote:
>>>
>>>>min_ip and max_ip type has been changed from u_int32_t to __be32 that is
>>>>not defined in userspace, this breaks iptables compilation.

I'm able to compile iptables 1.3.6 with 2.6.18 kernel
headers without any errors.
However iptables 1.3.6 + linux 2.6.19-rc1 kernel
headers give me this error:

cc -O2 -Wall -Wunused -I/usr/src/linux/include -Iinclude/ 
-DIPTABLES_VERSION=\"1.3.6\"  -fPIC -o extensions/libipt_iprange_sh.o -c 
exte
nsions/libipt_iprange.c
In file included from extensions/libipt_iprange.c:9:
/usr/src/linux/include/linux/netfilter_ipv4/ipt_iprange.h:11: error: syntax 
error before "__be32"
/usr/src/linux/include/linux/netfilter_ipv4/ipt_iprange.h:11: warning: no 
semicolon at end of struct or union
/usr/src/linux/include/linux/netfilter_ipv4/ipt_iprange.h:16: error: field 
`src' has incomplete type
/usr/src/linux/include/linux/netfilter_ipv4/ipt_iprange.h:17: error: field 
`dst' has incomplete type
extensions/libipt_iprange.c: In function `parse_iprange':
extensions/libipt_iprange.c:43: error: dereferencing pointer to incomplete 
type
extensions/libipt_iprange.c:50: error: dereferencing pointer to incomplete 
type
extensions/libipt_iprange.c:52: error: dereferencing pointer to incomplete 
type
extensions/libipt_iprange.c:52: error: dereferencing pointer to incomplete 
type
extensions/libipt_iprange.c: In function `print_iprange':
extensions/libipt_iprange.c:116: error: dereferencing pointer to incomplete 
type
extensions/libipt_iprange.c:117: error: dereferencing pointer to incomplete 
type
make: *** [extensions/libipt_iprange_sh.o] Error 1

My env: Slackware Linux 11.0

Linux Calimero 2.6.19-rc1 #1 PREEMPT Thu Oct 5 15:26:06 CEST 2006 i686 
pentium3 i386 GNU/Linux

Gnu C                  3.4.6
Gnu make               3.81
binutils               2.15.92.0.2
util-linux             2.12r
mount                  2.12r
module-init-tools      3.2.2
e2fsprogs              1.38
Linux C Library        2.3.6
Dynamic linker (ldd)   2.3.6
Linux C++ Library      6.0.3
Procps                 3.2.7
Net-tools              1.60
Kbd                    1.12
Sh-utils               5.97




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Compiling 1.3.6
  2006-10-09 15:36     ` Pablo Neira Ayuso
  2006-10-09 15:44       ` Pablo Neira Ayuso
@ 2006-10-09 16:02       ` Patrick McHardy
  2006-10-19  6:06         ` [PATCH] iptables: ip6table version support and libip6t_multiport.fix Yasuyuki KOZAKAI
  1 sibling, 1 reply; 23+ messages in thread
From: Patrick McHardy @ 2006-10-09 16:02 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: netfilter, Netfilter Development Mailinglist, Jorge Bastos

Pablo Neira Ayuso wrote:
> Patrick McHardy wrote:
> 
>> Pablo Neira Ayuso wrote:
>>
>>> min_ip and max_ip type has been changed from u_int32_t to __be32 that is
>>> not defined in userspace, this breaks iptables compilation. Attached a
>>> patch that recovers the use of u_int32_t. I'm not sure if this is the
>>> best fix so let me know what you think.
>>
>>
>>
>> I think we should just define the endian-annotation types in userspace.
>> Does this patch fix compilation?
> 
> 
> But this breaks previous iptables version with new kernels :(. An
> alternative can be exporting ipt_iprange.h to iptables/include although
> this is also a hack.

We should consider moving away from using the kernel headers directly.
Breaking compilation of old iptables versions is not too bad IMO,
old binaries will still work and someone compiling old iptables with
a new kernel can just as well just compile a new version.

Unfortunately 1.3.6 won't compile with 2.6.19, so we might have to put
out a new version soon.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Compiling 1.3.6
  2006-10-09 15:58         ` Marco Berizzi
@ 2006-10-09 16:02           ` Patrick McHardy
  2006-10-09 16:10             ` Marco Berizzi
  0 siblings, 1 reply; 23+ messages in thread
From: Patrick McHardy @ 2006-10-09 16:02 UTC (permalink / raw)
  To: Marco Berizzi; +Cc: netfilter, netfilter-devel, mysql.jorge, pablo

Marco Berizzi wrote:
> Pablo Neira Ayuso wrote:
> 
>> Pablo Neira Ayuso wrote:
>>
>>> Patrick McHardy wrote:
>>>
>>>> Pablo Neira Ayuso wrote:
>>>>
>>>>> min_ip and max_ip type has been changed from u_int32_t to __be32
>>>>> that is
>>>>> not defined in userspace, this breaks iptables compilation.
> 
> 
> I'm able to compile iptables 1.3.6 with 2.6.18 kernel
> headers without any errors.
> However iptables 1.3.6 + linux 2.6.19-rc1 kernel
> headers give me this error:

Does the patch I just sent fix it?


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Compiling 1.3.6
  2006-10-09 16:02           ` Patrick McHardy
@ 2006-10-09 16:10             ` Marco Berizzi
  2006-10-09 17:23               ` Patrick McHardy
  0 siblings, 1 reply; 23+ messages in thread
From: Marco Berizzi @ 2006-10-09 16:10 UTC (permalink / raw)
  To: kaber; +Cc: netfilter, netfilter-devel, mysql.jorge, pablo

Patrick McHardy wrote:

>Marco Berizzi wrote:
> > Pablo Neira Ayuso wrote:
> >
> >> Pablo Neira Ayuso wrote:
> >>
> >>> Patrick McHardy wrote:
> >>>
> >>>> Pablo Neira Ayuso wrote:
> >>>>
> >>>>> min_ip and max_ip type has been changed from u_int32_t to __be32
> >>>>> that is
> >>>>> not defined in userspace, this breaks iptables compilation.
> >
> >
> > I'm able to compile iptables 1.3.6 with 2.6.18 kernel
> > headers without any errors.
> > However iptables 1.3.6 + linux 2.6.19-rc1 kernel
> > headers give me this error:
>
>Does the patch I just sent fix it?

Yes, now I'm able to compile iptables 1.3.6 with 2.6.19-rc1
kernel headers with your patch:

Index: include/iptables_common.h
===================================================================
--- include/iptables_common.h   (Revision 6660)
+++ include/iptables_common.h   (Arbeitskopie)
@@ -42,4 +42,9 @@
   extern void init_extensions(void);
#endif

+#define __be32 u_int32_t
+#define __le32 u_int32_t
+#define __be16 u_int16_t
+#define __le16 u_int16_t
+
#endif /*_IPTABLES_COMMON_H*/




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Compiling 1.3.6
  2006-10-09 16:10             ` Marco Berizzi
@ 2006-10-09 17:23               ` Patrick McHardy
  2006-10-09 17:57                 ` Jorge Bastos
  0 siblings, 1 reply; 23+ messages in thread
From: Patrick McHardy @ 2006-10-09 17:23 UTC (permalink / raw)
  To: Marco Berizzi; +Cc: netfilter, netfilter-devel

Marco Berizzi wrote:
> Patrick McHardy wrote:
> 
>> Does the patch I just sent fix it?
> 
> 
> Yes, now I'm able to compile iptables 1.3.6 with 2.6.19-rc1
> kernel headers with your patch:

Thanks, I've committed it to SVN.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Compiling 1.3.6
  2006-10-09 17:23               ` Patrick McHardy
@ 2006-10-09 17:57                 ` Jorge Bastos
  0 siblings, 0 replies; 23+ messages in thread
From: Jorge Bastos @ 2006-10-09 17:57 UTC (permalink / raw)
  To: netfilter

Great!
I'm going to try it.

Jorge

----- Original Message ----- 
From: "Patrick McHardy" <kaber@trash.net>
To: "Marco Berizzi" <pupilla@hotmail.com>
Cc: <pablo@netfilter.org>; <mysql.jorge@decimal.pt>; 
<netfilter-devel@lists.netfilter.org>; <netfilter@lists.netfilter.org>
Sent: Monday, October 09, 2006 6:23 PM
Subject: Re: Compiling 1.3.6


> Marco Berizzi wrote:
>> Patrick McHardy wrote:
>>
>>> Does the patch I just sent fix it?
>>
>>
>> Yes, now I'm able to compile iptables 1.3.6 with 2.6.19-rc1
>> kernel headers with your patch:
>
> Thanks, I've committed it to SVN.
> 



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
  2006-10-03 19:58         ` Rémi Denis-Courmont
@ 2006-10-12  8:11           ` Yasuyuki KOZAKAI
       [not found]           ` <200610120811.k9C8B4Pg002384@toshiba.co.jp>
  1 sibling, 0 replies; 23+ messages in thread
From: Yasuyuki KOZAKAI @ 2006-10-12  8:11 UTC (permalink / raw)
  To: rdenis; +Cc: ljlane, netfilter-devel, yasuyuki.kozakai


Hello, sorry for late replying.

From: Rémi Denis-Courmont <rdenis@simphalempin.com>
Date: Tue, 3 Oct 2006 22:58:28 +0300

> Le mardi 3 octobre 2006 17:30, vous avez écrit :
> > IPv4 multiport match (and policy match, too) would help you. It has
> > the line
> >
> > 	#include ../../include/netfilter_ipv4/ipt_multiport.h
> >
> > and definitions for old kernel are included in the header.
> 
> Ok. This time there is no trace of (xt|XT)_ at all:

??? Did you send intended patch ? It includes XT_MULTI_PORTS as folows.

> diff -Nru iptables-1.3.5.orig/extensions/libip6t_multiport.c 
> iptables-1.3.5/extensions/libip6t_multiport.c
> --- iptables-1.3.5.orig/extensions/libip6t_multiport.c	2005-02-19 
> 21:19:17.000000000 +0200
> +++ iptables-1.3.5/extensions/libip6t_multiport.c	2006-08-27 
> 13:03:36.000000000 +0300
> @@ -20,6 +20,23 @@
>  " --dports ...\n"
>  "				match destination port(s)\n"
>  " --ports port[,port,port]\n"

snip

> +	for (i=0; i<XT_MULTI_PORTS; i++)
> +		multiinfo->pflags[i] = 0;
> + 

And I noticed that your mailer breaks the patch. For example, 

> +	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)
>  {
> @@ -246,6 +392,41 @@
>  	printf(" ");
>  }

ip6t_entry_match *match) is moved to next line. That should be after
"const struct ".

Regards,

-- Yasuyuki Kozakai

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
       [not found]           ` <200610120811.k9C8B4Pg002384@toshiba.co.jp>
@ 2006-10-12 14:29             ` Rémi Denis-Courmont
  2006-10-13  0:50               ` Yasuyuki KOZAKAI
  0 siblings, 1 reply; 23+ messages in thread
From: Rémi Denis-Courmont @ 2006-10-12 14:29 UTC (permalink / raw)
  To: Yasuyuki KOZAKAI; +Cc: ljlane, netfilter-devel

[-- Attachment #1: Type: text/plain, Size: 316 bytes --]

Le jeudi 12 octobre 2006 11:11, Yasuyuki KOZAKAI a écrit :
> ??? Did you send intended patch ? It includes XT_MULTI_PORTS as
> folows.

Hmm, probably resent the old one accidentally then.

Sending the correct patch as attachment to avoid further breakages.

-- 
Rémi Denis-Courmont
http://www.remlab.net/

[-- Attachment #2: iptables-ip6t-multiport-v1.patch --]
[-- Type: text/x-diff, Size: 11967 bytes --]

Index: iptables/include/linux/netfilter_ipv6/ip6t_multiport.h
===================================================================
--- iptables/include/linux/netfilter_ipv6/ip6t_multiport.h	(révision 0)
+++ iptables/include/linux/netfilter_ipv6/ip6t_multiport.h	(révision 0)
@@ -0,0 +1,30 @@
+#ifndef _IP6T_MULTIPORT_H
+#define _IP6T_MULTIPORT_H
+
+enum ip6t_multiport_flags
+{
+	IP6T_MULTIPORT_SOURCE,
+	IP6T_MULTIPORT_DESTINATION,
+	IP6T_MULTIPORT_EITHER
+};
+
+#define IP6T_MULTI_PORTS	15
+
+/* Must fit inside union xt_matchinfo: 16 bytes */
+struct ip6t_multiport
+{
+	u_int8_t flags;				/* Type of comparison */
+	u_int8_t count;				/* Number of ports */
+	u_int16_t ports[IP6T_MULTI_PORTS];	/* Ports */
+};
+
+struct ip6t_multiport_v1
+{
+	u_int8_t flags;				/* Type of comparison */
+	u_int8_t count;				/* Number of ports */
+	u_int16_t ports[IP6T_MULTI_PORTS];	/* Ports */
+	u_int8_t pflags[IP6T_MULTI_PORTS];	/* Port flags */
+	u_int8_t invert;			/* Invert flag */
+};
+
+#endif /*_IP6T_MULTIPORT_H*/

Modification de propriétés sur iptables/include/linux/netfilter_ipv6/ip6t_multiport.h
___________________________________________________________________
Nom : svn:eol-style
   + native

Index: iptables/include/ip6tables.h
===================================================================
--- iptables/include/ip6tables.h	(révision 6687)
+++ iptables/include/ip6tables.h	(copie de travail)
@@ -33,6 +33,9 @@
 
 	ip6t_chainlabel name;
 
+	/* Revision of match (0 by default). */
+	u_int8_t revision;
+
 	const char *version;
 
 	/* Size of match data. */
Index: iptables/extensions/libip6t_multiport.c
===================================================================
--- iptables/extensions/libip6t_multiport.c	(révision 6687)
+++ iptables/extensions/libip6t_multiport.c	(copie de travail)
@@ -5,7 +5,8 @@
 #include <stdlib.h>
 #include <getopt.h>
 #include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6t_multiport.h>
+/* 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 @@
 " --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 @@
 	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; i<IP6T_MULTI_PORTS; i++)
+		multiinfo->pflags[i] = 0;
+ 
+	for (cp=buffer, i=0; cp && i<IP6T_MULTI_PORTS; cp=next, i++) {
+		next=strchr(cp, ',');
+ 		if (next) *next++='\0';
+		range = strchr(cp, ':');
+		if (range) {
+			if (i == IP6T_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 ip6t_entry_match *m, unsigned int *nfcache)
@@ -143,6 +201,52 @@
 	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 @@
 	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 @@
 	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 @@
 	.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);
 }
Index: iptables/ip6tables.c
===================================================================
--- iptables/ip6tables.c	(révision 6687)
+++ iptables/ip6tables.c	(copie de travail)
@@ -193,6 +193,8 @@
 const char *program_name;
 char *lib_dir;
 
+int kernel_version;
+
 /* Keeping track of external matches and targets: linked lists.  */
 struct ip6tables_match *ip6tables_matches = NULL;
 struct ip6tables_target *ip6tables_targets = NULL;
@@ -1102,10 +1104,51 @@
 	return merge;
 }
 
+static int compatible_revision(const char *name, u_int8_t revision, int opt)
+{
+	struct ip6t_get_revision rev;
+	socklen_t s = sizeof(rev);
+	int max_rev, sockfd;
+
+	sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
+	if (sockfd < 0) {
+		fprintf(stderr, "Could not open socket to kernel: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+
+	strcpy(rev.name, name);
+	rev.revision = revision;
+
+	max_rev = getsockopt(sockfd, IPPROTO_IPV6, opt, &rev, &s);
+	if (max_rev < 0) {
+		/* Definitely don't support this? */
+		if (errno == EPROTONOSUPPORT) {
+			close(sockfd);
+			return 0;
+		} else if (errno == ENOPROTOOPT) {
+			close(sockfd);
+			/* Assume only revision 0 support (old kernel) */
+			return (revision == 0);
+		} else {
+			fprintf(stderr, "getsockopt failed strangely: %s\n",
+				strerror(errno));
+			exit(1);
+		}
+	}
+	close(sockfd);
+	return 1;
+}
+
+static int compatible_match_revision(const char *name, u_int8_t revision)
+{
+	return compatible_revision(name, revision, IP6T_SO_GET_REVISION_MATCH);
+}
+
 void
 register_match6(struct ip6tables_match *me)
 {
-	struct ip6tables_match **i;
+	struct ip6tables_match **i, *old;
 
 	if (strcmp(me->version, program_version) != 0) {
 		fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
@@ -1113,12 +1156,36 @@
 		exit(1);
 	}
 
-	if (find_match(me->name, DURING_LOAD, NULL)) {
-		fprintf(stderr, "%s: match `%s' already registered.\n",
+	/* Revision field stole a char from name. */
+	if (strlen(me->name) >= IP6T_FUNCTION_MAXNAMELEN-1) {
+		fprintf(stderr, "%s: target `%s' has invalid name\n",
 			program_name, me->name);
 		exit(1);
 	}
 
+	old = find_match(me->name, DURING_LOAD, NULL);
+	if (old) {
+		if (old->revision == me->revision) {
+			fprintf(stderr,
+				"%s: match `%s' already registered.\n",
+				program_name, me->name);
+			exit(1);
+		}
+
+		/* Now we have two (or more) options, check compatibility. */
+		if (compatible_match_revision(old->name, old->revision)
+		    && old->revision > me->revision)
+			return;
+
+		/* Replace if compatible. */
+		if (!compatible_match_revision(me->name, me->revision))
+			return;
+
+		/* Delete old one. */
+		for (i = &ip6tables_matches; *i!=old; i = &(*i)->next);
+		*i = old->next;
+	}
+	
 	if (me->size != IP6T_ALIGN(me->size)) {
 		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
 			program_name, me->name, (unsigned int)me->size);
@@ -1761,6 +1828,14 @@
 	*matches = NULL;
 }
 
+static void set_revision(char *name, u_int8_t revision)
+{
+	/* Old kernel sources don't have ".revision" field,
+	   but we stole a byte from name. */
+	name[IP6T_FUNCTION_MAXNAMELEN - 2] = '\0';
+	name[IP6T_FUNCTION_MAXNAMELEN - 1] = revision;
+}
+
 int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
 {
 	struct ip6t_entry fw, *e = NULL;
@@ -2041,6 +2116,7 @@
 			m->m = fw_calloc(1, size);
 			m->m->u.match_size = size;
 			strcpy(m->m->u.user.name, m->name);
+			set_revision(m->m->u.user.name, m->revision);
 			if (m->init != NULL)
 				m->init(m->m, &fw.nfcache);
 			if (m != m->next)
@@ -2185,6 +2261,8 @@
 					m->m = fw_calloc(1, size);
 					m->m->u.match_size = size;
 					strcpy(m->m->u.user.name, m->name);
+					set_revision(m->m->u.user.name,
+						     m->revision);
 					if (m->init != NULL)
 						m->init(m->m, &fw.nfcache);
 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
  2006-10-12 14:29             ` Rémi Denis-Courmont
@ 2006-10-13  0:50               ` Yasuyuki KOZAKAI
       [not found]                 ` <200610190606.k9J66kRd002796@toshiba.co.jp>
  0 siblings, 1 reply; 23+ messages in thread
From: Yasuyuki KOZAKAI @ 2006-10-13  0:50 UTC (permalink / raw)
  To: rdenis; +Cc: ljlane, netfilter-devel, yasuyuki.kozakai

[-- Attachment #1: Type: Text/Plain, Size: 1530 bytes --]


Hello,

> Le jeudi 12 octobre 2006 11:11, Yasuyuki KOZAKAI a écrit :
> > ??? Did you send intended patch ? It includes XT_MULTI_PORTS as
> > folows.
> 
> Hmm, probably resent the old one accidentally then.
> 
> Sending the correct patch as attachment to avoid further breakages.

Thanks,

OK, I've update your patch (please see below comments in detail), and also
tested with kernel 2.4.33.3 and 2.6 linus tree and ip6tables build with
headers in each of them.

If no objection, I'll commit the attached patch next week.

I appreciate if you tries to build with 2.4 kernel for such changes
from next time.


From: Rémi Denis-Courmont <rdenis@simphalempin.com>
Date: Thu, 12 Oct 2006 17:29:35 +0300

> Index: iptables/include/ip6tables.h
> ===================================================================
> --- iptables/include/ip6tables.h	(révision 6687)
> +++ iptables/include/ip6tables.h	(copie de travail)
> @@ -33,6 +33,9 @@
>  
>  	ip6t_chainlabel name;
>  
> +	/* Revision of match (0 by default). */
> +	u_int8_t revision;
> +
>  	const char *version;

The declaration for ip6t_get_revision is missing. That doesn't exist
in 2.4 kernel.

> Index: iptables/ip6tables.c
> ===================================================================
> --- iptables/ip6tables.c	(révision 6687)
> +++ iptables/ip6tables.c	(copie de travail)
> @@ -193,6 +193,8 @@
>  const char *program_name;
>  char *lib_dir;
>  
> +int kernel_version;

This isn't used anywhere.

Regards,


[-- Attachment #2: multiport6.patch --]
[-- Type: Text/Plain, Size: 11701 bytes --]

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 <stdlib.h>
 #include <getopt.h>
 #include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6t_multiport.h>
+/* 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
 	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; i<IP6T_MULTI_PORTS; i++)
+		multiinfo->pflags[i] = 0;
+ 
+	for (cp=buffer, i=0; cp && i<IP6T_MULTI_PORTS; cp=next, i++) {
+		next=strchr(cp, ',');
+ 		if (next) *next++='\0';
+		range = strchr(cp, ':');
+		if (range) {
+			if (i == IP6T_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 ip6t_entry_match *m, unsigned int *nfcache)
@@ -143,6 +201,52 @@ parse(int c, char **argv, int invert, un
 	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 *
 	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);
 }
diff --git a/include/ip6tables.h b/include/ip6tables.h
index b1140b3..406f255 100644
--- a/include/ip6tables.h
+++ b/include/ip6tables.h
@@ -15,6 +15,18 @@
 #define IPPROTO_DCCP 33
 #endif
 
+#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */
+#define IP6T_SO_GET_REVISION_MATCH	(IP6T_BASE_CTL + 2)
+#define IP6T_SO_GET_REVISION_TARGET	(IP6T_BASE_CTL + 3)
+
+struct ip6t_get_revision
+{
+	char name[IP6T_FUNCTION_MAXNAMELEN-1];
+
+	u_int8_t revision;
+};
+#endif /* IP6T_SO_GET_REVISION_MATCH   Old kernel source */
+
 struct ip6tables_rule_match
 {
 	struct ip6tables_rule_match *next;
@@ -33,6 +45,9 @@ struct ip6tables_match
 
 	ip6t_chainlabel name;
 
+	/* Revision of match (0 by default). */
+	u_int8_t revision;
+
 	const char *version;
 
 	/* Size of match data. */
diff --git a/include/linux/netfilter_ipv6/ip6t_multiport.h b/include/linux/netfilter_ipv6/ip6t_multiport.h
new file mode 100644
index 0000000..8c2cc9d
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_multiport.h
@@ -0,0 +1,30 @@
+#ifndef _IP6T_MULTIPORT_H
+#define _IP6T_MULTIPORT_H
+
+enum ip6t_multiport_flags
+{
+	IP6T_MULTIPORT_SOURCE,
+	IP6T_MULTIPORT_DESTINATION,
+	IP6T_MULTIPORT_EITHER
+};
+
+#define IP6T_MULTI_PORTS	15
+
+/* Must fit inside union xt_matchinfo: 16 bytes */
+struct ip6t_multiport
+{
+	u_int8_t flags;				/* Type of comparison */
+	u_int8_t count;				/* Number of ports */
+	u_int16_t ports[IP6T_MULTI_PORTS];	/* Ports */
+};
+
+struct ip6t_multiport_v1
+{
+	u_int8_t flags;				/* Type of comparison */
+	u_int8_t count;				/* Number of ports */
+	u_int16_t ports[IP6T_MULTI_PORTS];	/* Ports */
+	u_int8_t pflags[IP6T_MULTI_PORTS];	/* Port flags */
+	u_int8_t invert;			/* Invert flag */
+};
+
+#endif /*_IP6T_MULTIPORT_H*/
diff --git a/ip6tables.c b/ip6tables.c
index 659041f..92e434c 100644
--- a/ip6tables.c
+++ b/ip6tables.c
@@ -1102,10 +1102,51 @@ merge_options(struct option *oldopts, co
 	return merge;
 }
 
+static int compatible_revision(const char *name, u_int8_t revision, int opt)
+{
+	struct ip6t_get_revision rev;
+	socklen_t s = sizeof(rev);
+	int max_rev, sockfd;
+
+	sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
+	if (sockfd < 0) {
+		fprintf(stderr, "Could not open socket to kernel: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+
+	strcpy(rev.name, name);
+	rev.revision = revision;
+
+	max_rev = getsockopt(sockfd, IPPROTO_IPV6, opt, &rev, &s);
+	if (max_rev < 0) {
+		/* Definitely don't support this? */
+		if (errno == EPROTONOSUPPORT) {
+			close(sockfd);
+			return 0;
+		} else if (errno == ENOPROTOOPT) {
+			close(sockfd);
+			/* Assume only revision 0 support (old kernel) */
+			return (revision == 0);
+		} else {
+			fprintf(stderr, "getsockopt failed strangely: %s\n",
+				strerror(errno));
+			exit(1);
+		}
+	}
+	close(sockfd);
+	return 1;
+}
+
+static int compatible_match_revision(const char *name, u_int8_t revision)
+{
+	return compatible_revision(name, revision, IP6T_SO_GET_REVISION_MATCH);
+}
+
 void
 register_match6(struct ip6tables_match *me)
 {
-	struct ip6tables_match **i;
+	struct ip6tables_match **i, *old;
 
 	if (strcmp(me->version, program_version) != 0) {
 		fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
@@ -1113,12 +1154,36 @@ register_match6(struct ip6tables_match *
 		exit(1);
 	}
 
-	if (find_match(me->name, DURING_LOAD, NULL)) {
-		fprintf(stderr, "%s: match `%s' already registered.\n",
+	/* Revision field stole a char from name. */
+	if (strlen(me->name) >= IP6T_FUNCTION_MAXNAMELEN-1) {
+		fprintf(stderr, "%s: target `%s' has invalid name\n",
 			program_name, me->name);
 		exit(1);
 	}
 
+	old = find_match(me->name, DURING_LOAD, NULL);
+	if (old) {
+		if (old->revision == me->revision) {
+			fprintf(stderr,
+				"%s: match `%s' already registered.\n",
+				program_name, me->name);
+			exit(1);
+		}
+
+		/* Now we have two (or more) options, check compatibility. */
+		if (compatible_match_revision(old->name, old->revision)
+		    && old->revision > me->revision)
+			return;
+
+		/* Replace if compatible. */
+		if (!compatible_match_revision(me->name, me->revision))
+			return;
+
+		/* Delete old one. */
+		for (i = &ip6tables_matches; *i!=old; i = &(*i)->next);
+		*i = old->next;
+	}
+	
 	if (me->size != IP6T_ALIGN(me->size)) {
 		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
 			program_name, me->name, (unsigned int)me->size);
@@ -1761,6 +1826,14 @@ void clear_rule_matches(struct ip6tables
 	*matches = NULL;
 }
 
+static void set_revision(char *name, u_int8_t revision)
+{
+	/* Old kernel sources don't have ".revision" field,
+	   but we stole a byte from name. */
+	name[IP6T_FUNCTION_MAXNAMELEN - 2] = '\0';
+	name[IP6T_FUNCTION_MAXNAMELEN - 1] = revision;
+}
+
 int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
 {
 	struct ip6t_entry fw, *e = NULL;
@@ -2041,6 +2114,7 @@ int do_command6(int argc, char *argv[], 
 			m->m = fw_calloc(1, size);
 			m->m->u.match_size = size;
 			strcpy(m->m->u.user.name, m->name);
+			set_revision(m->m->u.user.name, m->revision);
 			if (m->init != NULL)
 				m->init(m->m, &fw.nfcache);
 			if (m != m->next)
@@ -2185,6 +2259,8 @@ int do_command6(int argc, char *argv[], 
 					m->m = fw_calloc(1, size);
 					m->m->u.match_size = size;
 					strcpy(m->m->u.user.name, m->name);
+					set_revision(m->m->u.user.name,
+						     m->revision);
 					if (m->init != NULL)
 						m->init(m->m, &fw.nfcache);
 

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
  2006-10-09 16:02       ` Patrick McHardy
@ 2006-10-19  6:06         ` Yasuyuki KOZAKAI
  0 siblings, 0 replies; 23+ messages in thread
From: Yasuyuki KOZAKAI @ 2006-10-19  6:06 UTC (permalink / raw)
  To: kaber; +Cc: rdenis, netfilter-devel, ljlane


Hi, Patrick,

I've found the following your mail and would I be better to commit this
until next version of iptables ?

From: Patrick McHardy <kaber@trash.net>
Date: Mon, 09 Oct 2006 18:02:14 +0200

> We should consider moving away from using the kernel headers directly.
> Breaking compilation of old iptables versions is not too bad IMO,
> old binaries will still work and someone compiling old iptables with
> a new kernel can just as well just compile a new version.
> 
> Unfortunately 1.3.6 won't compile with 2.6.19, so we might have to put
> out a new version soon.


From: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
Date: Fri, 13 Oct 2006 09:50:44 +0900 (JST)

> 
> Hello,
> 
> > Le jeudi 12 octobre 2006 11:11, Yasuyuki KOZAKAI a écrit :
> > > ??? Did you send intended patch ? It includes XT_MULTI_PORTS as
> > > folows.
> > 
> > Hmm, probably resent the old one accidentally then.
> > 
> > Sending the correct patch as attachment to avoid further breakages.
> 
> Thanks,
> 
> OK, I've update your patch (please see below comments in detail), and also
> tested with kernel 2.4.33.3 and 2.6 linus tree and ip6tables build with
> headers in each of them.
> 
> If no objection, I'll commit the attached patch next week.
> 
> I appreciate if you tries to build with 2.4 kernel for such changes
> from next time.
> 
> 
> From: Rémi Denis-Courmont <rdenis@simphalempin.com>
> Date: Thu, 12 Oct 2006 17:29:35 +0300
> 
> > Index: iptables/include/ip6tables.h
> > ===================================================================
> > --- iptables/include/ip6tables.h	(révision 6687)
> > +++ iptables/include/ip6tables.h	(copie de travail)
> > @@ -33,6 +33,9 @@
> >  
> >  	ip6t_chainlabel name;
> >  
> > +	/* Revision of match (0 by default). */
> > +	u_int8_t revision;
> > +
> >  	const char *version;
> 
> The declaration for ip6t_get_revision is missing. That doesn't exist
> in 2.4 kernel.
> 
> > Index: iptables/ip6tables.c
> > ===================================================================
> > --- iptables/ip6tables.c	(révision 6687)
> > +++ iptables/ip6tables.c	(copie de travail)
> > @@ -193,6 +193,8 @@
> >  const char *program_name;
> >  char *lib_dir;
> >  
> > +int kernel_version;
> 
> This isn't used anywhere.
> 
> Regards,
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
       [not found]                 ` <200610190606.k9J66kRd002796@toshiba.co.jp>
@ 2006-10-20 10:06                   ` Patrick McHardy
  2006-10-20 11:48                     ` Yasuyuki KOZAKAI
  0 siblings, 1 reply; 23+ messages in thread
From: Patrick McHardy @ 2006-10-20 10:06 UTC (permalink / raw)
  To: Yasuyuki KOZAKAI; +Cc: rdenis, netfilter-devel, ljlane

Yasuyuki KOZAKAI wrote:
> Hi, Patrick,
> 
> I've found the following your mail and would I be better to commit this
> until next version of iptables ?

The patch looks fine, I guess we can add it since we still have a few
weeks until we should release a new version.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
  2006-10-20 10:06                   ` Patrick McHardy
@ 2006-10-20 11:48                     ` Yasuyuki KOZAKAI
  0 siblings, 0 replies; 23+ messages in thread
From: Yasuyuki KOZAKAI @ 2006-10-20 11:48 UTC (permalink / raw)
  To: kaber; +Cc: rdenis, netfilter-devel, ljlane, yasuyuki.kozakai

From: Patrick McHardy <kaber@trash.net>
Date: Fri, 20 Oct 2006 12:06:49 +0200

> Yasuyuki KOZAKAI wrote:
> > Hi, Patrick,
> > 
> > I've found the following your mail and would I be better to commit this
> > until next version of iptables ?
> 
> The patch looks fine, I guess we can add it since we still have a few
> weeks until we should release a new version.

OK, I've commited it. Thanks.

-- Yasuyuki Kozakai

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2006-10-20 11:48 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-11  1:06 [PATCH] iptables: ip6table version support and libip6t_multiport.fix Laurence J. Lane
2006-10-02  1:37 ` Laurence J. Lane
2006-10-02  4:46   ` Yasuyuki KOZAKAI
2006-10-02 14:47     ` Rémi Denis-Courmont
2006-10-03 14:30       ` Yasuyuki KOZAKAI
     [not found]       ` <200610031430.k93EUJgA008197@toshiba.co.jp>
2006-10-03 19:58         ` Rémi Denis-Courmont
2006-10-12  8:11           ` Yasuyuki KOZAKAI
     [not found]           ` <200610120811.k9C8B4Pg002384@toshiba.co.jp>
2006-10-12 14:29             ` Rémi Denis-Courmont
2006-10-13  0:50               ` Yasuyuki KOZAKAI
     [not found]                 ` <200610190606.k9J66kRd002796@toshiba.co.jp>
2006-10-20 10:06                   ` Patrick McHardy
2006-10-20 11:48                     ` Yasuyuki KOZAKAI
  -- strict thread matches above, loose matches on Subject: below --
2006-10-06 18:41 Compiling 1.3.6 Jorge Bastos
2006-10-08 22:21 ` Pablo Neira Ayuso
2006-10-09 15:23   ` Patrick McHardy
2006-10-09 15:36     ` Pablo Neira Ayuso
2006-10-09 15:44       ` Pablo Neira Ayuso
2006-10-09 15:58         ` Marco Berizzi
2006-10-09 16:02           ` Patrick McHardy
2006-10-09 16:10             ` Marco Berizzi
2006-10-09 17:23               ` Patrick McHardy
2006-10-09 17:57                 ` Jorge Bastos
2006-10-09 16:02       ` Patrick McHardy
2006-10-19  6:06         ` [PATCH] iptables: ip6table version support and libip6t_multiport.fix Yasuyuki KOZAKAI

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.