All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Multiple matches of the same type
@ 2006-02-27  8:54 Jozsef Kadlecsik
  2006-02-28 16:28 ` Krzysztof Oledzki
  2006-03-04  9:37 ` Patrick McHardy
  0 siblings, 2 replies; 4+ messages in thread
From: Jozsef Kadlecsik @ 2006-02-27  8:54 UTC (permalink / raw)
  To: netfilter-devel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 803 bytes --]

Hi,

The attached patch adds the ability to specify multiple matches of the
same type by ip[6]tables. Besides removing a limitation, a few matches
(recent, u32, set :-) can benefit from the feature.

If two or more matches of the same type are detected then the options are
assumed to be grouped in order to tell which option belongs to which
match:

... -m foo ... <options0> ... -m foo ... <options1> ...

Otherwise the commandline parsing is unmodified.

If there are no objections I'm going to commit the patch in svn before the
end of the week.

Best regards,
Jozsef
-
E-mail  : kadlec@blackhole.kfki.hu, kadlec@sunserv.kfki.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
          H-1525 Budapest 114, POB. 49, Hungary

[-- Attachment #2: iptables-mm.patch --]
[-- Type: TEXT/PLAIN, Size: 8153 bytes --]

diff -urN --exclude-from=/usr/src/diff.exclude iptables/include/ip6tables.h iptables-mm/include/ip6tables.h
--- iptables/include/ip6tables.h	2006-02-22 10:41:25.000000000 +0100
+++ iptables-mm/include/ip6tables.h	2006-02-27 06:24:03.000000000 +0100
@@ -13,6 +13,10 @@
 	struct ip6tables_rule_match *next;
 
 	struct ip6tables_match *match;
+
+	/* Multiple matches of the same type: the ones before
+	   the current one are completed from parsing point of view */	
+	unsigned int completed;
 };
 
 /* Include file for additions: new matches and targets. */
diff -urN --exclude-from=/usr/src/diff.exclude iptables/include/iptables.h iptables-mm/include/iptables.h
--- iptables/include/iptables.h	2006-02-22 10:41:25.000000000 +0100
+++ iptables-mm/include/iptables.h	2006-02-26 20:12:23.000000000 +0100
@@ -29,6 +29,10 @@
 	struct iptables_rule_match *next;
 
 	struct iptables_match *match;
+
+	/* Multiple matches of the same type: the ones before
+	   the current one are completed from parsing point of view */	
+	unsigned int completed;
 };
 
 /* Include file for additions: new matches and targets. */
diff -urN --exclude-from=/usr/src/diff.exclude iptables/ip6tables.c iptables-mm/ip6tables.c
--- iptables/ip6tables.c	2006-02-22 10:41:27.000000000 +0100
+++ iptables-mm/ip6tables.c	2006-02-27 06:43:26.000000000 +0100
@@ -709,37 +709,46 @@
 }
 
 struct ip6tables_match *
-find_match(const char *name, enum ip6t_tryload tryload, struct ip6tables_rule_match **matches)
+find_match(const char *match_name, enum ip6t_tryload tryload, struct ip6tables_rule_match **matches)
 {
 	struct ip6tables_match *ptr;
- 	int icmphack = 0;
+ 	const char *icmp6 = "icmp6";
+ 	const char *name;
   
 	/* This is ugly as hell. Nonetheless, there is no way of changing
 	 * this without hurting backwards compatibility */
- 	if ( (strcmp(name,"icmpv6") == 0) ||
- 	     (strcmp(name,"ipv6-icmp") == 0) ||
- 	     (strcmp(name,"icmp6") == 0) ) icmphack = 1;
+ 	if ( (strcmp(match_name,"icmpv6") == 0) ||
+ 	     (strcmp(match_name,"ipv6-icmp") == 0) ||
+ 	     (strcmp(match_name,"icmp6") == 0) )
+ 	     	name = icmp6;
+ 	else
+ 		name = match_name;
  
- 	if (!icmphack) {
- 		for (ptr = ip6tables_matches; ptr; ptr = ptr->next) {
- 			if (strcmp(name, ptr->name) == 0)
- 				break;
- 		}
- 	} else {
- 		for (ptr = ip6tables_matches; ptr; ptr = ptr->next) {
- 			if (strcmp("icmp6", ptr->name) == 0)
- 				break;
- 		}
-  	}
+	for (ptr = ip6tables_matches; ptr; ptr = ptr->next) {
+ 		if (strcmp(name, ptr->name) == 0) {
+			struct ip6tables_match *clone;
+			
+			/* First match of this type: */
+			if (ptr->m == NULL)
+				break;
+
+			/* Second and subsequent clones */
+			clone = fw_malloc(sizeof(struct ip6tables_match));
+			memcpy(clone, ptr, sizeof(struct ip6tables_match));
+			clone->mflags = 0;
+			/* This is a clone: */
+			clone->next = clone;
+
+			ptr = clone;
+			break;
+		}
+	}
 
 #ifndef NO_SHARED_LIBS
 	if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) {
 		char path[strlen(lib_dir) + sizeof("/libip6t_.so")
 			 + strlen(name)];
-		if (!icmphack)
-			sprintf(path, "%s/libip6t_%s.so", lib_dir, name);
-		else
-			sprintf(path, "%s/libip6t_%s.so", lib_dir, "icmpv6");
+		sprintf(path, "%s/libip6t_%s.so", lib_dir, name);
 		if (dlopen(path, RTLD_NOW)) {
 			/* Found library.  If it didn't register itself,
 			   maybe they specified target as match. */
@@ -773,8 +782,12 @@
 
 		newentry = fw_malloc(sizeof(struct ip6tables_rule_match));
 
-		for (i = matches; *i; i = &(*i)->next);
+		for (i = matches; *i; i = &(*i)->next) {
+			if (strcmp(name, (*i)->match->name) == 0)
+				(*i)->completed = 1;
+		}
 		newentry->match = ptr;
+		newentry->completed = 0;
 		newentry->next = NULL;
 		*i = newentry;
 	}
@@ -1701,6 +1714,10 @@
 			free(matchp->match->m);
 			matchp->match->m = NULL;
 		}
+		if (matchp->match == matchp->match->next) {
+			free(matchp->match);
+			matchp->match = NULL;
+		}
 		free(matchp);
 		matchp = tmp;
 	}
@@ -1988,7 +2005,9 @@
 			strcpy(m->m->u.user.name, m->name);
 			if (m->init != NULL)
 				m->init(m->m, &fw.nfcache);
-			opts = merge_options(opts, m->extra_opts, &m->option_offset);
+			if (m != m->next)
+				/* Merge options for non-cloned matches */
+				opts = merge_options(opts, m->extra_opts, &m->option_offset);
 		}
 		break;
 
@@ -2066,14 +2085,14 @@
 			exit_tryhelp(2);
 
 		default:
-			/* FIXME: This scheme doesn't allow two of the same
-			   matches --RR */
 			if (!target
 			    || !(target->parse(c - target->option_offset,
 					       argv, invert,
 					       &target->tflags,
 					       &fw, &target->t))) {
 				for (matchp = matches; matchp; matchp = matchp->next) {
+					if (matchp->completed) 
+						continue;
 					if (matchp->match->parse(c - matchp->match->option_offset,
 						     argv, invert,
 						     &matchp->match->mflags,
@@ -2088,7 +2107,7 @@
 				   actually hear this code suck. */
 
 				/* some explanations (after four different bugs
-				 * in 3 different releases): If we encountere a
+				 * in 3 different releases): If we encounter a
 				 * parameter, that has not been parsed yet,
 				 * it's not an option of an explicitly loaded
 				 * match or a target.  However, we support
diff -urN --exclude-from=/usr/src/diff.exclude iptables/iptables.c iptables-mm/iptables.c
--- iptables/iptables.c	2006-02-22 10:41:27.000000000 +0100
+++ iptables-mm/iptables.c	2006-02-27 06:22:45.000000000 +0100
@@ -679,9 +679,24 @@
 	struct iptables_match *ptr;
 
 	for (ptr = iptables_matches; ptr; ptr = ptr->next) {
-		if (strcmp(name, ptr->name) == 0)
+		if (strcmp(name, ptr->name) == 0) {
+			struct iptables_match *clone;
+			
+			/* First match of this type: */
+			if (ptr->m == NULL)
+				break;
+
+			/* Second and subsequent clones */
+			clone = fw_malloc(sizeof(struct iptables_match));
+			memcpy(clone, ptr, sizeof(struct iptables_match));
+			clone->mflags = 0;
+			/* This is a clone: */
+			clone->next = clone;
+
+			ptr = clone;
 			break;
-	}
+		}
+	}		
 
 #ifndef NO_SHARED_LIBS
 	if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) {
@@ -721,8 +736,12 @@
 
 		newentry = fw_malloc(sizeof(struct iptables_rule_match));
 
-		for (i = matches; *i; i = &(*i)->next);
+		for (i = matches; *i; i = &(*i)->next) {
+			if (strcmp(name, (*i)->match->name) == 0)
+				(*i)->completed = 1;
+		}
 		newentry->match = ptr;
+		newentry->completed = 0;
 		newentry->next = NULL;
 		*i = newentry;
 	}
@@ -1810,6 +1829,10 @@
 			free(matchp->match->m);
 			matchp->match->m = NULL;
 		}
+		if (matchp->match == matchp->match->next) {
+			free(matchp->match);
+			matchp->match = NULL;
+		}
 		free(matchp);
 		matchp = tmp;
 	}
@@ -2134,7 +2157,9 @@
 			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);
+			if (m != m->next)
+				/* Merge options for non-cloned matches */
+				opts = merge_options(opts, m->extra_opts, &m->option_offset);
 		}
 		break;
 
@@ -2212,14 +2237,14 @@
 			exit_tryhelp(2);
 
 		default:
-			/* FIXME: This scheme doesn't allow two of the same
-			   matches --RR */
 			if (!target
 			    || !(target->parse(c - target->option_offset,
 					       argv, invert,
 					       &target->tflags,
 					       &fw, &target->t))) {
 				for (matchp = matches; matchp; matchp = matchp->next) {
+					if (matchp->completed) 
+						continue;
 					if (matchp->match->parse(c - matchp->match->option_offset,
 						     argv, invert,
 						     &matchp->match->mflags,
@@ -2234,7 +2259,7 @@
 				   actually hear this code suck. */
 
 				/* some explanations (after four different bugs
-				 * in 3 different releases): If we encountere a
+				 * in 3 different releases): If we encounter a
 				 * parameter, that has not been parsed yet,
 				 * it's not an option of an explicitly loaded
 				 * match or a target.  However, we support

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

end of thread, other threads:[~2006-03-04  9:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-27  8:54 [PATCH] Multiple matches of the same type Jozsef Kadlecsik
2006-02-28 16:28 ` Krzysztof Oledzki
2006-02-28 16:52   ` Jozsef Kadlecsik
2006-03-04  9:37 ` Patrick McHardy

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.